| author | |
| committer | |
| log | 2083208f19a4eb7caa1953980f9a2f2496115695 |
| tree | bfd2d7549780d25b012638422e38386313e0e321 |
| parent | 22015c1b3bfcf816faf10ea0fc152c4686efb363 |
This commit also reclaims +2 ZIR instruction tags by moving the
following to `extended`:
* func_var_args
* func_extra
* func_extra_var_args
The following ZIR instruction tag is added:
* func_inferred5 files changed, 215 insertions(+), 183 deletions(-)
BRANCH_TODO+24| ... | ... | @@ -737,3 +737,27 @@ fn errorSetDecl( |
| 737 | 737 | try mod.analyzeExport(&decl_scope.base, export_src, name, decl); |
| 738 | 738 | } |
| 739 | 739 | } |
| 740 | ||
| 741 | fn writeFuncExtra( | |
| 742 | self: *Writer, | |
| 743 | stream: anytype, | |
| 744 | inst: Inst.Index, | |
| 745 | var_args: bool, | |
| 746 | ) !void { | |
| 747 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | |
| 748 | const src = inst_data.src(); | |
| 749 | const extra = self.code.extraData(Inst.FuncExtra, inst_data.payload_index); | |
| 750 | const param_types = self.code.refSlice(extra.end, extra.data.param_types_len); | |
| 751 | const cc = extra.data.cc; | |
| 752 | const body = self.code.extra[extra.end + param_types.len ..][0..extra.data.body_len]; | |
| 753 | return self.writeFuncCommon( | |
| 754 | stream, | |
| 755 | param_types, | |
| 756 | extra.data.return_type, | |
| 757 | var_args, | |
| 758 | cc, | |
| 759 | body, | |
| 760 | src, | |
| 761 | ); | |
| 762 | } | |
| 763 |
src/AstGen.zig+17-37| ... | ... | @@ -1375,9 +1375,7 @@ fn blockExprStmts( |
| 1375 | 1375 | .field_ptr_named, |
| 1376 | 1376 | .field_val_named, |
| 1377 | 1377 | .func, |
| 1378 | .func_var_args, | |
| 1379 | .func_extra, | |
| 1380 | .func_extra_var_args, | |
| 1378 | .func_inferred, | |
| 1381 | 1379 | .int, |
| 1382 | 1380 | .float, |
| 1383 | 1381 | .float128, |
| ... | ... | @@ -2129,9 +2127,8 @@ fn fnDecl( |
| 2129 | 2127 | } |
| 2130 | 2128 | |
| 2131 | 2129 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; |
| 2132 | if (token_tags[maybe_bang] == .bang) { | |
| 2133 | return astgen.failTok(maybe_bang, "TODO implement inferred error sets", .{}); | |
| 2134 | } | |
| 2130 | const is_inferred_error = token_tags[maybe_bang] == .bang; | |
| 2131 | ||
| 2135 | 2132 | const return_type_inst = try AstGen.expr( |
| 2136 | 2133 | &decl_gz, |
| 2137 | 2134 | &decl_gz.base, |
| ... | ... | @@ -2153,31 +2150,24 @@ fn fnDecl( |
| 2153 | 2150 | |
| 2154 | 2151 | const func_inst: Zir.Inst.Ref = if (body_node == 0) func: { |
| 2155 | 2152 | if (is_extern) { |
| 2156 | return astgen.failNode(fn_proto.ast.fn_token, "non-extern function has no body", .{}); | |
| 2153 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{}); | |
| 2157 | 2154 | } |
| 2158 | ||
| 2159 | if (cc != .none or lib_name != 0) { | |
| 2160 | const tag: Zir.Inst.Tag = if (is_var_args) .func_extra_var_args else .func_extra; | |
| 2161 | break :func try decl_gz.addFuncExtra(tag, .{ | |
| 2162 | .src_node = fn_proto.ast.proto_node, | |
| 2163 | .ret_ty = return_type_inst, | |
| 2164 | .param_types = param_types, | |
| 2165 | .cc = cc, | |
| 2166 | .lib_name = lib_name, | |
| 2167 | .body = &[0]Zir.Inst.Index{}, | |
| 2168 | }); | |
| 2155 | if (is_inferred_error) { | |
| 2156 | return astgen.failTok(maybe_bang, "function prototype requires explicit error set", .{}); | |
| 2169 | 2157 | } |
| 2170 | ||
| 2171 | const tag: Zir.Inst.Tag = if (is_var_args) .func_var_args else .func; | |
| 2172 | break :func try decl_gz.addFunc(tag, .{ | |
| 2158 | break :func try decl_gz.addFunc(.{ | |
| 2173 | 2159 | .src_node = fn_proto.ast.proto_node, |
| 2174 | 2160 | .ret_ty = return_type_inst, |
| 2175 | 2161 | .param_types = param_types, |
| 2176 | 2162 | .body = &[0]Zir.Inst.Index{}, |
| 2163 | .cc = cc, | |
| 2164 | .lib_name = lib_name, | |
| 2165 | .is_var_args = is_var_args, | |
| 2166 | .is_inferred_error = false, | |
| 2177 | 2167 | }); |
| 2178 | 2168 | } else func: { |
| 2179 | 2169 | if (is_var_args) { |
| 2180 | return astgen.failNode(fn_proto.ast.fn_token, "non-extern function is variadic", .{}); | |
| 2170 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{}); | |
| 2181 | 2171 | } |
| 2182 | 2172 | |
| 2183 | 2173 | var fn_gz: Scope.GenZir = .{ |
| ... | ... | @@ -2224,30 +2214,20 @@ fn fnDecl( |
| 2224 | 2214 | if (fn_gz.instructions.items.len == 0 or |
| 2225 | 2215 | !astgen.instructions.items(.tag)[fn_gz.instructions.items.len - 1].isNoReturn()) |
| 2226 | 2216 | { |
| 2227 | // astgen uses result location semantics to coerce return operands. | |
| 2228 | 2217 | // Since we are adding the return instruction here, we must handle the coercion. |
| 2229 | 2218 | // We do this by using the `ret_coerce` instruction. |
| 2230 | 2219 | _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); |
| 2231 | 2220 | } |
| 2232 | 2221 | |
| 2233 | if (cc != .none or lib_name != 0) { | |
| 2234 | const tag: Zir.Inst.Tag = if (is_var_args) .func_extra_var_args else .func_extra; | |
| 2235 | break :func try decl_gz.addFuncExtra(tag, .{ | |
| 2236 | .src_node = fn_proto.ast.proto_node, | |
| 2237 | .ret_ty = return_type_inst, | |
| 2238 | .param_types = param_types, | |
| 2239 | .cc = cc, | |
| 2240 | .lib_name = lib_name, | |
| 2241 | .body = fn_gz.instructions.items, | |
| 2242 | }); | |
| 2243 | } | |
| 2244 | ||
| 2245 | const tag: Zir.Inst.Tag = if (is_var_args) .func_var_args else .func; | |
| 2246 | break :func try decl_gz.addFunc(tag, .{ | |
| 2222 | break :func try decl_gz.addFunc(.{ | |
| 2247 | 2223 | .src_node = fn_proto.ast.proto_node, |
| 2248 | 2224 | .ret_ty = return_type_inst, |
| 2249 | 2225 | .param_types = param_types, |
| 2250 | 2226 | .body = fn_gz.instructions.items, |
| 2227 | .cc = cc, | |
| 2228 | .lib_name = lib_name, | |
| 2229 | .is_var_args = is_var_args, | |
| 2230 | .is_inferred_error = is_inferred_error, | |
| 2251 | 2231 | }); |
| 2252 | 2232 | }; |
| 2253 | 2233 |
src/Module.zig+74-63| ... | ... | @@ -1278,79 +1278,90 @@ pub const Scope = struct { |
| 1278 | 1278 | } |
| 1279 | 1279 | } |
| 1280 | 1280 | |
| 1281 | pub fn addFuncExtra(gz: *GenZir, tag: Zir.Inst.Tag, args: struct { | |
| 1281 | pub fn addFunc(gz: *GenZir, args: struct { | |
| 1282 | 1282 | src_node: ast.Node.Index, |
| 1283 | 1283 | param_types: []const Zir.Inst.Ref, |
| 1284 | body: []const Zir.Inst.Index, | |
| 1284 | 1285 | ret_ty: Zir.Inst.Ref, |
| 1285 | 1286 | cc: Zir.Inst.Ref, |
| 1286 | body: []const Zir.Inst.Index, | |
| 1287 | 1287 | lib_name: u32, |
| 1288 | is_var_args: bool, | |
| 1289 | is_inferred_error: bool, | |
| 1288 | 1290 | }) !Zir.Inst.Ref { |
| 1289 | 1291 | assert(args.src_node != 0); |
| 1290 | 1292 | assert(args.ret_ty != .none); |
| 1291 | assert(args.cc != .none); | |
| 1292 | const gpa = gz.astgen.gpa; | |
| 1293 | try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1); | |
| 1294 | try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1); | |
| 1295 | try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len + | |
| 1296 | @typeInfo(Zir.Inst.FuncExtra).Struct.fields.len + args.param_types.len + | |
| 1297 | args.body.len); | |
| 1298 | ||
| 1299 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.FuncExtra{ | |
| 1300 | .return_type = args.ret_ty, | |
| 1301 | .cc = args.cc, | |
| 1302 | .param_types_len = @intCast(u32, args.param_types.len), | |
| 1303 | .body_len = @intCast(u32, args.body.len), | |
| 1304 | .lib_name = args.lib_name, | |
| 1305 | }); | |
| 1306 | gz.astgen.appendRefsAssumeCapacity(args.param_types); | |
| 1307 | gz.astgen.extra.appendSliceAssumeCapacity(args.body); | |
| 1308 | ||
| 1309 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); | |
| 1310 | gz.astgen.instructions.appendAssumeCapacity(.{ | |
| 1311 | .tag = tag, | |
| 1312 | .data = .{ .pl_node = .{ | |
| 1313 | .src_node = gz.nodeIndexToRelative(args.src_node), | |
| 1314 | .payload_index = payload_index, | |
| 1315 | } }, | |
| 1316 | }); | |
| 1317 | gz.instructions.appendAssumeCapacity(new_index); | |
| 1318 | return gz.indexToRef(new_index); | |
| 1319 | } | |
| 1320 | ||
| 1321 | pub fn addFunc(gz: *GenZir, tag: Zir.Inst.Tag, args: struct { | |
| 1322 | src_node: ast.Node.Index, | |
| 1323 | ret_ty: Zir.Inst.Ref, | |
| 1324 | param_types: []const Zir.Inst.Ref, | |
| 1325 | body: []const Zir.Inst.Index, | |
| 1326 | }) !Zir.Inst.Ref { | |
| 1327 | assert(args.src_node != 0); | |
| 1328 | assert(args.ret_ty != .none); | |
| 1329 | const gpa = gz.astgen.gpa; | |
| 1330 | try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1); | |
| 1331 | try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1); | |
| 1332 | try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len + | |
| 1333 | @typeInfo(Zir.Inst.Func).Struct.fields.len + args.param_types.len + | |
| 1334 | args.body.len); | |
| 1335 | ||
| 1336 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{ | |
| 1337 | .return_type = args.ret_ty, | |
| 1338 | .param_types_len = @intCast(u32, args.param_types.len), | |
| 1339 | .body_len = @intCast(u32, args.body.len), | |
| 1340 | }); | |
| 1341 | gz.astgen.appendRefsAssumeCapacity(args.param_types); | |
| 1342 | gz.astgen.extra.appendSliceAssumeCapacity(args.body); | |
| 1293 | const astgen = gz.astgen; | |
| 1294 | const gpa = astgen.gpa; | |
| 1343 | 1295 | |
| 1344 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); | |
| 1345 | gz.astgen.instructions.appendAssumeCapacity(.{ | |
| 1346 | .tag = tag, | |
| 1347 | .data = .{ .pl_node = .{ | |
| 1296 | try gz.instructions.ensureUnusedCapacity(gpa, 1); | |
| 1297 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); | |
| 1298 | ||
| 1299 | if (args.cc != .none or args.lib_name != 0 or args.is_var_args) { | |
| 1300 | try astgen.extra.ensureUnusedCapacity( | |
| 1301 | gpa, | |
| 1302 | @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len + | |
| 1303 | args.param_types.len + args.body.len + | |
| 1304 | @boolToInt(args.lib_name != 0) + | |
| 1305 | @boolToInt(args.cc != .none), | |
| 1306 | ); | |
| 1307 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{ | |
| 1348 | 1308 | .src_node = gz.nodeIndexToRelative(args.src_node), |
| 1349 | .payload_index = payload_index, | |
| 1350 | } }, | |
| 1351 | }); | |
| 1352 | gz.instructions.appendAssumeCapacity(new_index); | |
| 1353 | return gz.indexToRef(new_index); | |
| 1309 | .return_type = args.ret_ty, | |
| 1310 | .param_types_len = @intCast(u32, args.param_types.len), | |
| 1311 | .body_len = @intCast(u32, args.body.len), | |
| 1312 | }); | |
| 1313 | if (args.cc != .none) { | |
| 1314 | astgen.extra.appendAssumeCapacity(@enumToInt(args.cc)); | |
| 1315 | } | |
| 1316 | if (args.lib_name != 0) { | |
| 1317 | astgen.extra.appendAssumeCapacity(args.lib_name); | |
| 1318 | } | |
| 1319 | astgen.appendRefsAssumeCapacity(args.param_types); | |
| 1320 | astgen.extra.appendSliceAssumeCapacity(args.body); | |
| 1321 | ||
| 1322 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); | |
| 1323 | astgen.instructions.appendAssumeCapacity(.{ | |
| 1324 | .tag = .extended, | |
| 1325 | .data = .{ .extended = .{ | |
| 1326 | .opcode = .func, | |
| 1327 | .small = @bitCast(u16, Zir.Inst.ExtendedFunc.Small{ | |
| 1328 | .is_var_args = args.is_var_args, | |
| 1329 | .is_inferred_error = args.is_inferred_error, | |
| 1330 | .has_lib_name = args.lib_name != 0, | |
| 1331 | .has_cc = args.cc != .none, | |
| 1332 | }), | |
| 1333 | .operand = payload_index, | |
| 1334 | } }, | |
| 1335 | }); | |
| 1336 | gz.instructions.appendAssumeCapacity(new_index); | |
| 1337 | return gz.indexToRef(new_index); | |
| 1338 | } else { | |
| 1339 | try gz.astgen.extra.ensureUnusedCapacity( | |
| 1340 | gpa, | |
| 1341 | @typeInfo(Zir.Inst.Func).Struct.fields.len + | |
| 1342 | args.param_types.len + args.body.len, | |
| 1343 | ); | |
| 1344 | ||
| 1345 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{ | |
| 1346 | .return_type = args.ret_ty, | |
| 1347 | .param_types_len = @intCast(u32, args.param_types.len), | |
| 1348 | .body_len = @intCast(u32, args.body.len), | |
| 1349 | }); | |
| 1350 | gz.astgen.appendRefsAssumeCapacity(args.param_types); | |
| 1351 | gz.astgen.extra.appendSliceAssumeCapacity(args.body); | |
| 1352 | ||
| 1353 | const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func; | |
| 1354 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); | |
| 1355 | gz.astgen.instructions.appendAssumeCapacity(.{ | |
| 1356 | .tag = tag, | |
| 1357 | .data = .{ .pl_node = .{ | |
| 1358 | .src_node = gz.nodeIndexToRelative(args.src_node), | |
| 1359 | .payload_index = payload_index, | |
| 1360 | } }, | |
| 1361 | }); | |
| 1362 | gz.instructions.appendAssumeCapacity(new_index); | |
| 1363 | return gz.indexToRef(new_index); | |
| 1364 | } | |
| 1354 | 1365 | } |
| 1355 | 1366 | |
| 1356 | 1367 | pub fn addCall( |
src/Sema.zig+71-36| ... | ... | @@ -194,9 +194,7 @@ pub fn analyzeBody( |
| 194 | 194 | .field_val => try sema.zirFieldVal(block, inst), |
| 195 | 195 | .field_val_named => try sema.zirFieldValNamed(block, inst), |
| 196 | 196 | .func => try sema.zirFunc(block, inst, false), |
| 197 | .func_extra => try sema.zirFuncExtra(block, inst, false), | |
| 198 | .func_extra_var_args => try sema.zirFuncExtra(block, inst, true), | |
| 199 | .func_var_args => try sema.zirFunc(block, inst, true), | |
| 197 | .func_inferred => try sema.zirFunc(block, inst, true), | |
| 200 | 198 | .import => try sema.zirImport(block, inst), |
| 201 | 199 | .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst), |
| 202 | 200 | .int => try sema.zirInt(block, inst), |
| ... | ... | @@ -2646,7 +2644,12 @@ fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde |
| 2646 | 2644 | } |
| 2647 | 2645 | } |
| 2648 | 2646 | |
| 2649 | fn zirFunc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, var_args: bool) InnerError!*Inst { | |
| 2647 | fn zirFunc( | |
| 2648 | sema: *Sema, | |
| 2649 | block: *Scope.Block, | |
| 2650 | inst: Zir.Inst.Index, | |
| 2651 | inferred_error_set: bool, | |
| 2652 | ) InnerError!*Inst { | |
| 2650 | 2653 | const tracy = trace(@src()); |
| 2651 | 2654 | defer tracy.end(); |
| 2652 | 2655 | |
| ... | ... | @@ -2654,40 +2657,17 @@ fn zirFunc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, var_args: boo |
| 2654 | 2657 | const src = inst_data.src(); |
| 2655 | 2658 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); |
| 2656 | 2659 | const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len); |
| 2660 | const body = sema.code.extra[extra.end + param_types.len ..][0..extra.data.body_len]; | |
| 2657 | 2661 | |
| 2658 | 2662 | return sema.funcCommon( |
| 2659 | 2663 | block, |
| 2660 | 2664 | inst_data.src_node, |
| 2661 | 2665 | param_types, |
| 2666 | body, | |
| 2662 | 2667 | extra.data.return_type, |
| 2663 | 2668 | .Unspecified, |
| 2664 | var_args, | |
| 2665 | ); | |
| 2666 | } | |
| 2667 | ||
| 2668 | fn zirFuncExtra(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, var_args: bool) InnerError!*Inst { | |
| 2669 | const tracy = trace(@src()); | |
| 2670 | defer tracy.end(); | |
| 2671 | ||
| 2672 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | |
| 2673 | const src = inst_data.src(); | |
| 2674 | const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = inst_data.src_node }; | |
| 2675 | const extra = sema.code.extraData(Zir.Inst.FuncExtra, inst_data.payload_index); | |
| 2676 | const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len); | |
| 2677 | ||
| 2678 | const cc_tv = try sema.resolveInstConst(block, cc_src, extra.data.cc); | |
| 2679 | // TODO once we're capable of importing and analyzing decls from | |
| 2680 | // std.builtin, this needs to change | |
| 2681 | const cc_str = cc_tv.val.castTag(.enum_literal).?.data; | |
| 2682 | const cc = std.meta.stringToEnum(std.builtin.CallingConvention, cc_str) orelse | |
| 2683 | return sema.mod.fail(&block.base, cc_src, "Unknown calling convention {s}", .{cc_str}); | |
| 2684 | return sema.funcCommon( | |
| 2685 | block, | |
| 2686 | inst_data.src_node, | |
| 2687 | param_types, | |
| 2688 | extra.data.return_type, | |
| 2689 | cc, | |
| 2690 | var_args, | |
| 2669 | false, | |
| 2670 | inferred_error_set, | |
| 2691 | 2671 | ); |
| 2692 | 2672 | } |
| 2693 | 2673 | |
| ... | ... | @@ -2696,9 +2676,11 @@ fn funcCommon( |
| 2696 | 2676 | block: *Scope.Block, |
| 2697 | 2677 | src_node_offset: i32, |
| 2698 | 2678 | zir_param_types: []const Zir.Inst.Ref, |
| 2679 | body: []const Zir.Inst.Index, | |
| 2699 | 2680 | zir_return_type: Zir.Inst.Ref, |
| 2700 | 2681 | cc: std.builtin.CallingConvention, |
| 2701 | 2682 | var_args: bool, |
| 2683 | inferred_error_set: bool, | |
| 2702 | 2684 | ) InnerError!*Inst { |
| 2703 | 2685 | const src: LazySrcLoc = .{ .node_offset = src_node_offset }; |
| 2704 | 2686 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; |
| ... | ... | @@ -5307,15 +5289,68 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro |
| 5307 | 5289 | const extended = sema.code.instructions.items(.data)[inst].extended; |
| 5308 | 5290 | switch (extended.opcode) { |
| 5309 | 5291 | // zig fmt: off |
| 5310 | .c_undef => return sema.zirCUndef( block, inst, extended), | |
| 5311 | .c_include => return sema.zirCInclude( block, inst, extended), | |
| 5312 | .c_define => return sema.zirCDefine( block, inst, extended), | |
| 5313 | .wasm_memory_size => return sema.zirWasmMemorySize( block, inst, extended), | |
| 5314 | .wasm_memory_grow => return sema.zirWasmMemoryGrow( block, inst, extended), | |
| 5292 | .func => return sema.zirFuncExtended( block, inst, extended), | |
| 5293 | .c_undef => return sema.zirCUndef( block, inst, extended), | |
| 5294 | .c_include => return sema.zirCInclude( block, inst, extended), | |
| 5295 | .c_define => return sema.zirCDefine( block, inst, extended), | |
| 5296 | .wasm_memory_size => return sema.zirWasmMemorySize(block, inst, extended), | |
| 5297 | .wasm_memory_grow => return sema.zirWasmMemoryGrow(block, inst, extended), | |
| 5315 | 5298 | // zig fmt: on |
| 5316 | 5299 | } |
| 5317 | 5300 | } |
| 5318 | 5301 | |
| 5302 | fn zirFuncExtended( | |
| 5303 | sema: *Sema, | |
| 5304 | block: *Scope.Block, | |
| 5305 | inst: Zir.Inst.Index, | |
| 5306 | extended: Zir.Inst.Extended.InstData, | |
| 5307 | ) InnerError!*Inst { | |
| 5308 | const tracy = trace(@src()); | |
| 5309 | defer tracy.end(); | |
| 5310 | ||
| 5311 | const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, extended.operand); | |
| 5312 | const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; | |
| 5313 | const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = extra.data.src_node }; | |
| 5314 | const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small); | |
| 5315 | ||
| 5316 | var extra_index: usize = extra.end; | |
| 5317 | if (small.has_lib_name) { | |
| 5318 | const lib_name = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | |
| 5319 | extra_index += 1; | |
| 5320 | return sema.mod.fail(&block.base, src, "TODO: implement Sema func lib name", .{}); | |
| 5321 | } | |
| 5322 | const cc: std.builtin.CallingConvention = if (small.has_cc) blk: { | |
| 5323 | const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | |
| 5324 | extra_index += 1; | |
| 5325 | const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref); | |
| 5326 | // TODO this needs to resolve other kinds of Value tags rather than | |
| 5327 | // assuming the tag will be .enum_field_index. | |
| 5328 | const cc_field_index = cc_tv.val.castTag(.enum_field_index).?.data; | |
| 5329 | // TODO should `@intToEnum` do this `@intCast` for you? | |
| 5330 | const cc = @intToEnum( | |
| 5331 | std.builtin.CallingConvention, | |
| 5332 | @intCast(@typeInfo(std.builtin.CallingConvention).Enum.tag_type, cc_field_index), | |
| 5333 | ); | |
| 5334 | break :blk cc; | |
| 5335 | } else .Unspecified; | |
| 5336 | ||
| 5337 | const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len); | |
| 5338 | extra_index += 1; | |
| 5339 | ||
| 5340 | const body = sema.code.extra[extra_index..][0..extra.data.body_len]; | |
| 5341 | ||
| 5342 | return sema.funcCommon( | |
| 5343 | block, | |
| 5344 | extra.data.src_node, | |
| 5345 | param_types, | |
| 5346 | body, | |
| 5347 | extra.data.return_type, | |
| 5348 | cc, | |
| 5349 | small.is_var_args, | |
| 5350 | small.is_inferred_error, | |
| 5351 | ); | |
| 5352 | } | |
| 5353 | ||
| 5319 | 5354 | fn zirCUndef( |
| 5320 | 5355 | sema: *Sema, |
| 5321 | 5356 | block: *Scope.Block, |
src/Zir.zig+29-47| ... | ... | @@ -371,15 +371,8 @@ pub const Inst = struct { |
| 371 | 371 | /// the body_len is 0. Calling convention is auto. |
| 372 | 372 | /// Uses the `pl_node` union field. `payload_index` points to a `Func`. |
| 373 | 373 | func, |
| 374 | /// Same as `func` but the function is variadic. | |
| 375 | func_var_args, | |
| 376 | /// Same as `func` but with extra fields: | |
| 377 | /// * calling convention | |
| 378 | /// * extern lib name | |
| 379 | /// Uses the `pl_node` union field. `payload_index` points to a `FuncExtra`. | |
| 380 | func_extra, | |
| 381 | /// Same as `func_extra` but the function is variadic. | |
| 382 | func_extra_var_args, | |
| 374 | /// Same as `func` but has an inferred error set. | |
| 375 | func_inferred, | |
| 383 | 376 | /// Implements the `@import` builtin. |
| 384 | 377 | /// Uses the `str_tok` field. |
| 385 | 378 | import, |
| ... | ... | @@ -1010,9 +1003,7 @@ pub const Inst = struct { |
| 1010 | 1003 | .field_ptr_named, |
| 1011 | 1004 | .field_val_named, |
| 1012 | 1005 | .func, |
| 1013 | .func_var_args, | |
| 1014 | .func_extra, | |
| 1015 | .func_extra_var_args, | |
| 1006 | .func_inferred, | |
| 1016 | 1007 | .has_decl, |
| 1017 | 1008 | .int, |
| 1018 | 1009 | .float, |
| ... | ... | @@ -1211,6 +1202,11 @@ pub const Inst = struct { |
| 1211 | 1202 | /// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum. |
| 1212 | 1203 | /// `noreturn` instructions may not go here; they must be part of the main `Tag` enum. |
| 1213 | 1204 | pub const Extended = enum(u16) { |
| 1205 | /// Represents a function declaration or function prototype, depending on | |
| 1206 | /// whether body_len is 0. | |
| 1207 | /// `operand` is payload index to `ExtendedFunc`. | |
| 1208 | /// `small` is `ExtendedFunc.Small`. | |
| 1209 | func, | |
| 1214 | 1210 | /// `operand` is payload index to `UnNode`. |
| 1215 | 1211 | c_undef, |
| 1216 | 1212 | /// `operand` is payload index to `UnNode`. |
| ... | ... | @@ -1774,15 +1770,23 @@ pub const Inst = struct { |
| 1774 | 1770 | }; |
| 1775 | 1771 | |
| 1776 | 1772 | /// Trailing: |
| 1777 | /// 0. param_type: Ref // for each param_types_len | |
| 1778 | /// 1. body: Index // for each body_len | |
| 1779 | pub const FuncExtra = struct { | |
| 1780 | cc: Ref, | |
| 1781 | /// null terminated string index, or 0 to mean none. | |
| 1782 | lib_name: u32, | |
| 1773 | /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set | |
| 1774 | /// 1. cc: Ref, // if has_cc is set | |
| 1775 | /// 2. param_type: Ref // for each param_types_len | |
| 1776 | /// 3. body: Index // for each body_len | |
| 1777 | pub const ExtendedFunc = struct { | |
| 1778 | src_node: i32, | |
| 1783 | 1779 | return_type: Ref, |
| 1784 | 1780 | param_types_len: u32, |
| 1785 | 1781 | body_len: u32, |
| 1782 | ||
| 1783 | pub const Small = packed struct { | |
| 1784 | is_var_args: bool, | |
| 1785 | is_inferred_error: bool, | |
| 1786 | has_lib_name: bool, | |
| 1787 | has_cc: bool, | |
| 1788 | _: u12 = undefined, | |
| 1789 | }; | |
| 1786 | 1790 | }; |
| 1787 | 1791 | |
| 1788 | 1792 | /// Trailing: |
| ... | ... | @@ -2459,9 +2463,7 @@ const Writer = struct { |
| 2459 | 2463 | => try self.writeStrTok(stream, inst), |
| 2460 | 2464 | |
| 2461 | 2465 | .func => try self.writeFunc(stream, inst, false), |
| 2462 | .func_extra => try self.writeFuncExtra(stream, inst, false), | |
| 2463 | .func_var_args => try self.writeFunc(stream, inst, true), | |
| 2464 | .func_extra_var_args => try self.writeFuncExtra(stream, inst, true), | |
| 2466 | .func_inferred => try self.writeFunc(stream, inst, true), | |
| 2465 | 2467 | |
| 2466 | 2468 | .@"unreachable" => try self.writeUnreachable(stream, inst), |
| 2467 | 2469 | |
| ... | ... | @@ -3099,7 +3101,7 @@ const Writer = struct { |
| 3099 | 3101 | self: *Writer, |
| 3100 | 3102 | stream: anytype, |
| 3101 | 3103 | inst: Inst.Index, |
| 3102 | var_args: bool, | |
| 3104 | inferred_error_set: bool, | |
| 3103 | 3105 | ) !void { |
| 3104 | 3106 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 3105 | 3107 | const src = inst_data.src(); |
| ... | ... | @@ -3110,36 +3112,14 @@ const Writer = struct { |
| 3110 | 3112 | stream, |
| 3111 | 3113 | param_types, |
| 3112 | 3114 | extra.data.return_type, |
| 3113 | var_args, | |
| 3115 | inferred_error_set, | |
| 3116 | false, | |
| 3114 | 3117 | .none, |
| 3115 | 3118 | body, |
| 3116 | 3119 | src, |
| 3117 | 3120 | ); |
| 3118 | 3121 | } |
| 3119 | 3122 | |
| 3120 | fn writeFuncExtra( | |
| 3121 | self: *Writer, | |
| 3122 | stream: anytype, | |
| 3123 | inst: Inst.Index, | |
| 3124 | var_args: bool, | |
| 3125 | ) !void { | |
| 3126 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | |
| 3127 | const src = inst_data.src(); | |
| 3128 | const extra = self.code.extraData(Inst.FuncExtra, inst_data.payload_index); | |
| 3129 | const param_types = self.code.refSlice(extra.end, extra.data.param_types_len); | |
| 3130 | const cc = extra.data.cc; | |
| 3131 | const body = self.code.extra[extra.end + param_types.len ..][0..extra.data.body_len]; | |
| 3132 | return self.writeFuncCommon( | |
| 3133 | stream, | |
| 3134 | param_types, | |
| 3135 | extra.data.return_type, | |
| 3136 | var_args, | |
| 3137 | cc, | |
| 3138 | body, | |
| 3139 | src, | |
| 3140 | ); | |
| 3141 | } | |
| 3142 | ||
| 3143 | 3123 | fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| 3144 | 3124 | const inst_data = self.code.instructions.items(.data)[inst].bool_br; |
| 3145 | 3125 | const extra = self.code.extraData(Inst.Block, inst_data.payload_index); |
| ... | ... | @@ -3184,6 +3164,7 @@ const Writer = struct { |
| 3184 | 3164 | stream: anytype, |
| 3185 | 3165 | param_types: []const Inst.Ref, |
| 3186 | 3166 | ret_ty: Inst.Ref, |
| 3167 | inferred_error_set: bool, | |
| 3187 | 3168 | var_args: bool, |
| 3188 | 3169 | cc: Inst.Ref, |
| 3189 | 3170 | body: []const Inst.Index, |
| ... | ... | @@ -3197,7 +3178,8 @@ const Writer = struct { |
| 3197 | 3178 | try stream.writeAll("], "); |
| 3198 | 3179 | try self.writeInstRef(stream, ret_ty); |
| 3199 | 3180 | try self.writeOptionalInstRef(stream, ", cc=", cc); |
| 3200 | try self.writeFlag(stream, ", var_args", var_args); | |
| 3181 | try self.writeFlag(stream, ", vargs", var_args); | |
| 3182 | try self.writeFlag(stream, ", inferror", inferred_error_set); | |
| 3201 | 3183 | |
| 3202 | 3184 | try stream.writeAll(", {\n"); |
| 3203 | 3185 | self.indent += 2; |