| 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,3 +737,27 @@ fn errorSetDecl( |
| 737 | try mod.analyzeExport(&decl_scope.base, export_src, name, decl); | 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,9 +1375,7 @@ fn blockExprStmts( |
| 1375 | .field_ptr_named, | 1375 | .field_ptr_named, |
| 1376 | .field_val_named, | 1376 | .field_val_named, |
| 1377 | .func, | 1377 | .func, |
| 1378 | .func_var_args, | 1378 | .func_inferred, |
| 1379 | .func_extra, | ||
| 1380 | .func_extra_var_args, | ||
| 1381 | .int, | 1379 | .int, |
| 1382 | .float, | 1380 | .float, |
| 1383 | .float128, | 1381 | .float128, |
| ... | @@ -2129,9 +2127,8 @@ fn fnDecl( | ... | @@ -2129,9 +2127,8 @@ fn fnDecl( |
| 2129 | } | 2127 | } |
| 2130 | 2128 | ||
| 2131 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; | 2129 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; |
| 2132 | if (token_tags[maybe_bang] == .bang) { | 2130 | const is_inferred_error = token_tags[maybe_bang] == .bang; |
| 2133 | return astgen.failTok(maybe_bang, "TODO implement inferred error sets", .{}); | 2131 | |
| 2134 | } | ||
| 2135 | const return_type_inst = try AstGen.expr( | 2132 | const return_type_inst = try AstGen.expr( |
| 2136 | &decl_gz, | 2133 | &decl_gz, |
| 2137 | &decl_gz.base, | 2134 | &decl_gz.base, |
| ... | @@ -2153,31 +2150,24 @@ fn fnDecl( | ... | @@ -2153,31 +2150,24 @@ fn fnDecl( |
| 2153 | 2150 | ||
| 2154 | const func_inst: Zir.Inst.Ref = if (body_node == 0) func: { | 2151 | const func_inst: Zir.Inst.Ref = if (body_node == 0) func: { |
| 2155 | if (is_extern) { | 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 | 2155 | if (is_inferred_error) { | |
| 2159 | if (cc != .none or lib_name != 0) { | 2156 | return astgen.failTok(maybe_bang, "function prototype requires explicit error set", .{}); |
| 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 | }); | ||
| 2169 | } | 2157 | } |
| 2170 | 2158 | break :func try decl_gz.addFunc(.{ | |
| 2171 | const tag: Zir.Inst.Tag = if (is_var_args) .func_var_args else .func; | ||
| 2172 | break :func try decl_gz.addFunc(tag, .{ | ||
| 2173 | .src_node = fn_proto.ast.proto_node, | 2159 | .src_node = fn_proto.ast.proto_node, |
| 2174 | .ret_ty = return_type_inst, | 2160 | .ret_ty = return_type_inst, |
| 2175 | .param_types = param_types, | 2161 | .param_types = param_types, |
| 2176 | .body = &[0]Zir.Inst.Index{}, | 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 | } else func: { | 2168 | } else func: { |
| 2179 | if (is_var_args) { | 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 | var fn_gz: Scope.GenZir = .{ | 2173 | var fn_gz: Scope.GenZir = .{ |
| ... | @@ -2224,30 +2214,20 @@ fn fnDecl( | ... | @@ -2224,30 +2214,20 @@ fn fnDecl( |
| 2224 | if (fn_gz.instructions.items.len == 0 or | 2214 | if (fn_gz.instructions.items.len == 0 or |
| 2225 | !astgen.instructions.items(.tag)[fn_gz.instructions.items.len - 1].isNoReturn()) | 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 | // Since we are adding the return instruction here, we must handle the coercion. | 2217 | // Since we are adding the return instruction here, we must handle the coercion. |
| 2229 | // We do this by using the `ret_coerce` instruction. | 2218 | // We do this by using the `ret_coerce` instruction. |
| 2230 | _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); | 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) { | 2222 | break :func try decl_gz.addFunc(.{ |
| 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, .{ | ||
| 2247 | .src_node = fn_proto.ast.proto_node, | 2223 | .src_node = fn_proto.ast.proto_node, |
| 2248 | .ret_ty = return_type_inst, | 2224 | .ret_ty = return_type_inst, |
| 2249 | .param_types = param_types, | 2225 | .param_types = param_types, |
| 2250 | .body = fn_gz.instructions.items, | 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,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 | src_node: ast.Node.Index, | 1282 | src_node: ast.Node.Index, |
| 1283 | param_types: []const Zir.Inst.Ref, | 1283 | param_types: []const Zir.Inst.Ref, |
| 1284 | body: []const Zir.Inst.Index, | ||
| 1284 | ret_ty: Zir.Inst.Ref, | 1285 | ret_ty: Zir.Inst.Ref, |
| 1285 | cc: Zir.Inst.Ref, | 1286 | cc: Zir.Inst.Ref, |
| 1286 | body: []const Zir.Inst.Index, | ||
| 1287 | lib_name: u32, | 1287 | lib_name: u32, |
| 1288 | is_var_args: bool, | ||
| 1289 | is_inferred_error: bool, | ||
| 1288 | }) !Zir.Inst.Ref { | 1290 | }) !Zir.Inst.Ref { |
| 1289 | assert(args.src_node != 0); | 1291 | assert(args.src_node != 0); |
| 1290 | assert(args.ret_ty != .none); | 1292 | assert(args.ret_ty != .none); |
| 1291 | assert(args.cc != .none); | 1293 | const astgen = gz.astgen; |
| 1292 | const gpa = gz.astgen.gpa; | 1294 | const gpa = 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); | ||
| 1343 | 1295 | ||
| 1344 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); | 1296 | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 1345 | gz.astgen.instructions.appendAssumeCapacity(.{ | 1297 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 1346 | .tag = tag, | 1298 | |
| 1347 | .data = .{ .pl_node = .{ | 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 | .src_node = gz.nodeIndexToRelative(args.src_node), | 1308 | .src_node = gz.nodeIndexToRelative(args.src_node), |
| 1349 | .payload_index = payload_index, | 1309 | .return_type = args.ret_ty, |
| 1350 | } }, | 1310 | .param_types_len = @intCast(u32, args.param_types.len), |
| 1351 | }); | 1311 | .body_len = @intCast(u32, args.body.len), |
| 1352 | gz.instructions.appendAssumeCapacity(new_index); | 1312 | }); |
| 1353 | return gz.indexToRef(new_index); | 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 | pub fn addCall( | 1367 | pub fn addCall( |
src/Sema.zig+71-36| ... | @@ -194,9 +194,7 @@ pub fn analyzeBody( | ... | @@ -194,9 +194,7 @@ pub fn analyzeBody( |
| 194 | .field_val => try sema.zirFieldVal(block, inst), | 194 | .field_val => try sema.zirFieldVal(block, inst), |
| 195 | .field_val_named => try sema.zirFieldValNamed(block, inst), | 195 | .field_val_named => try sema.zirFieldValNamed(block, inst), |
| 196 | .func => try sema.zirFunc(block, inst, false), | 196 | .func => try sema.zirFunc(block, inst, false), |
| 197 | .func_extra => try sema.zirFuncExtra(block, inst, false), | 197 | .func_inferred => try sema.zirFunc(block, inst, true), |
| 198 | .func_extra_var_args => try sema.zirFuncExtra(block, inst, true), | ||
| 199 | .func_var_args => try sema.zirFunc(block, inst, true), | ||
| 200 | .import => try sema.zirImport(block, inst), | 198 | .import => try sema.zirImport(block, inst), |
| 201 | .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst), | 199 | .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst), |
| 202 | .int => try sema.zirInt(block, inst), | 200 | .int => try sema.zirInt(block, inst), |
| ... | @@ -2646,7 +2644,12 @@ fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde | ... | @@ -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 | const tracy = trace(@src()); | 2653 | const tracy = trace(@src()); |
| 2651 | defer tracy.end(); | 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,40 +2657,17 @@ fn zirFunc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, var_args: boo |
| 2654 | const src = inst_data.src(); | 2657 | const src = inst_data.src(); |
| 2655 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); | 2658 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); |
| 2656 | const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len); | 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 | return sema.funcCommon( | 2662 | return sema.funcCommon( |
| 2659 | block, | 2663 | block, |
| 2660 | inst_data.src_node, | 2664 | inst_data.src_node, |
| 2661 | param_types, | 2665 | param_types, |
| 2666 | body, | ||
| 2662 | extra.data.return_type, | 2667 | extra.data.return_type, |
| 2663 | .Unspecified, | 2668 | .Unspecified, |
| 2664 | var_args, | 2669 | false, |
| 2665 | ); | 2670 | inferred_error_set, |
| 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, | ||
| 2691 | ); | 2671 | ); |
| 2692 | } | 2672 | } |
| 2693 | 2673 | ||
| ... | @@ -2696,9 +2676,11 @@ fn funcCommon( | ... | @@ -2696,9 +2676,11 @@ fn funcCommon( |
| 2696 | block: *Scope.Block, | 2676 | block: *Scope.Block, |
| 2697 | src_node_offset: i32, | 2677 | src_node_offset: i32, |
| 2698 | zir_param_types: []const Zir.Inst.Ref, | 2678 | zir_param_types: []const Zir.Inst.Ref, |
| 2679 | body: []const Zir.Inst.Index, | ||
| 2699 | zir_return_type: Zir.Inst.Ref, | 2680 | zir_return_type: Zir.Inst.Ref, |
| 2700 | cc: std.builtin.CallingConvention, | 2681 | cc: std.builtin.CallingConvention, |
| 2701 | var_args: bool, | 2682 | var_args: bool, |
| 2683 | inferred_error_set: bool, | ||
| 2702 | ) InnerError!*Inst { | 2684 | ) InnerError!*Inst { |
| 2703 | const src: LazySrcLoc = .{ .node_offset = src_node_offset }; | 2685 | const src: LazySrcLoc = .{ .node_offset = src_node_offset }; |
| 2704 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; | 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,15 +5289,68 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro |
| 5307 | const extended = sema.code.instructions.items(.data)[inst].extended; | 5289 | const extended = sema.code.instructions.items(.data)[inst].extended; |
| 5308 | switch (extended.opcode) { | 5290 | switch (extended.opcode) { |
| 5309 | // zig fmt: off | 5291 | // zig fmt: off |
| 5310 | .c_undef => return sema.zirCUndef( block, inst, extended), | 5292 | .func => return sema.zirFuncExtended( block, inst, extended), |
| 5311 | .c_include => return sema.zirCInclude( block, inst, extended), | 5293 | .c_undef => return sema.zirCUndef( block, inst, extended), |
| 5312 | .c_define => return sema.zirCDefine( block, inst, extended), | 5294 | .c_include => return sema.zirCInclude( block, inst, extended), |
| 5313 | .wasm_memory_size => return sema.zirWasmMemorySize( block, inst, extended), | 5295 | .c_define => return sema.zirCDefine( block, inst, extended), |
| 5314 | .wasm_memory_grow => return sema.zirWasmMemoryGrow( block, inst, extended), | 5296 | .wasm_memory_size => return sema.zirWasmMemorySize(block, inst, extended), |
| 5297 | .wasm_memory_grow => return sema.zirWasmMemoryGrow(block, inst, extended), | ||
| 5315 | // zig fmt: on | 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 | fn zirCUndef( | 5354 | fn zirCUndef( |
| 5320 | sema: *Sema, | 5355 | sema: *Sema, |
| 5321 | block: *Scope.Block, | 5356 | block: *Scope.Block, |
src/Zir.zig+29-47| ... | @@ -371,15 +371,8 @@ pub const Inst = struct { | ... | @@ -371,15 +371,8 @@ pub const Inst = struct { |
| 371 | /// the body_len is 0. Calling convention is auto. | 371 | /// the body_len is 0. Calling convention is auto. |
| 372 | /// Uses the `pl_node` union field. `payload_index` points to a `Func`. | 372 | /// Uses the `pl_node` union field. `payload_index` points to a `Func`. |
| 373 | func, | 373 | func, |
| 374 | /// Same as `func` but the function is variadic. | 374 | /// Same as `func` but has an inferred error set. |
| 375 | func_var_args, | 375 | func_inferred, |
| 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, | ||
| 383 | /// Implements the `@import` builtin. | 376 | /// Implements the `@import` builtin. |
| 384 | /// Uses the `str_tok` field. | 377 | /// Uses the `str_tok` field. |
| 385 | import, | 378 | import, |
| ... | @@ -1010,9 +1003,7 @@ pub const Inst = struct { | ... | @@ -1010,9 +1003,7 @@ pub const Inst = struct { |
| 1010 | .field_ptr_named, | 1003 | .field_ptr_named, |
| 1011 | .field_val_named, | 1004 | .field_val_named, |
| 1012 | .func, | 1005 | .func, |
| 1013 | .func_var_args, | 1006 | .func_inferred, |
| 1014 | .func_extra, | ||
| 1015 | .func_extra_var_args, | ||
| 1016 | .has_decl, | 1007 | .has_decl, |
| 1017 | .int, | 1008 | .int, |
| 1018 | .float, | 1009 | .float, |
| ... | @@ -1211,6 +1202,11 @@ pub const Inst = struct { | ... | @@ -1211,6 +1202,11 @@ pub const Inst = struct { |
| 1211 | /// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum. | 1202 | /// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum. |
| 1212 | /// `noreturn` instructions may not go here; they must be part of the main `Tag` enum. | 1203 | /// `noreturn` instructions may not go here; they must be part of the main `Tag` enum. |
| 1213 | pub const Extended = enum(u16) { | 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 | /// `operand` is payload index to `UnNode`. | 1210 | /// `operand` is payload index to `UnNode`. |
| 1215 | c_undef, | 1211 | c_undef, |
| 1216 | /// `operand` is payload index to `UnNode`. | 1212 | /// `operand` is payload index to `UnNode`. |
| ... | @@ -1774,15 +1770,23 @@ pub const Inst = struct { | ... | @@ -1774,15 +1770,23 @@ pub const Inst = struct { |
| 1774 | }; | 1770 | }; |
| 1775 | 1771 | ||
| 1776 | /// Trailing: | 1772 | /// Trailing: |
| 1777 | /// 0. param_type: Ref // for each param_types_len | 1773 | /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set |
| 1778 | /// 1. body: Index // for each body_len | 1774 | /// 1. cc: Ref, // if has_cc is set |
| 1779 | pub const FuncExtra = struct { | 1775 | /// 2. param_type: Ref // for each param_types_len |
| 1780 | cc: Ref, | 1776 | /// 3. body: Index // for each body_len |
| 1781 | /// null terminated string index, or 0 to mean none. | 1777 | pub const ExtendedFunc = struct { |
| 1782 | lib_name: u32, | 1778 | src_node: i32, |
| 1783 | return_type: Ref, | 1779 | return_type: Ref, |
| 1784 | param_types_len: u32, | 1780 | param_types_len: u32, |
| 1785 | body_len: u32, | 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 | /// Trailing: | 1792 | /// Trailing: |
| ... | @@ -2459,9 +2463,7 @@ const Writer = struct { | ... | @@ -2459,9 +2463,7 @@ const Writer = struct { |
| 2459 | => try self.writeStrTok(stream, inst), | 2463 | => try self.writeStrTok(stream, inst), |
| 2460 | 2464 | ||
| 2461 | .func => try self.writeFunc(stream, inst, false), | 2465 | .func => try self.writeFunc(stream, inst, false), |
| 2462 | .func_extra => try self.writeFuncExtra(stream, inst, false), | 2466 | .func_inferred => try self.writeFunc(stream, inst, true), |
| 2463 | .func_var_args => try self.writeFunc(stream, inst, true), | ||
| 2464 | .func_extra_var_args => try self.writeFuncExtra(stream, inst, true), | ||
| 2465 | 2467 | ||
| 2466 | .@"unreachable" => try self.writeUnreachable(stream, inst), | 2468 | .@"unreachable" => try self.writeUnreachable(stream, inst), |
| 2467 | 2469 | ||
| ... | @@ -3099,7 +3101,7 @@ const Writer = struct { | ... | @@ -3099,7 +3101,7 @@ const Writer = struct { |
| 3099 | self: *Writer, | 3101 | self: *Writer, |
| 3100 | stream: anytype, | 3102 | stream: anytype, |
| 3101 | inst: Inst.Index, | 3103 | inst: Inst.Index, |
| 3102 | var_args: bool, | 3104 | inferred_error_set: bool, |
| 3103 | ) !void { | 3105 | ) !void { |
| 3104 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | 3106 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 3105 | const src = inst_data.src(); | 3107 | const src = inst_data.src(); |
| ... | @@ -3110,36 +3112,14 @@ const Writer = struct { | ... | @@ -3110,36 +3112,14 @@ const Writer = struct { |
| 3110 | stream, | 3112 | stream, |
| 3111 | param_types, | 3113 | param_types, |
| 3112 | extra.data.return_type, | 3114 | extra.data.return_type, |
| 3113 | var_args, | 3115 | inferred_error_set, |
| 3116 | false, | ||
| 3114 | .none, | 3117 | .none, |
| 3115 | body, | 3118 | body, |
| 3116 | src, | 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 | fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void { | 3123 | fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| 3144 | const inst_data = self.code.instructions.items(.data)[inst].bool_br; | 3124 | const inst_data = self.code.instructions.items(.data)[inst].bool_br; |
| 3145 | const extra = self.code.extraData(Inst.Block, inst_data.payload_index); | 3125 | const extra = self.code.extraData(Inst.Block, inst_data.payload_index); |
| ... | @@ -3184,6 +3164,7 @@ const Writer = struct { | ... | @@ -3184,6 +3164,7 @@ const Writer = struct { |
| 3184 | stream: anytype, | 3164 | stream: anytype, |
| 3185 | param_types: []const Inst.Ref, | 3165 | param_types: []const Inst.Ref, |
| 3186 | ret_ty: Inst.Ref, | 3166 | ret_ty: Inst.Ref, |
| 3167 | inferred_error_set: bool, | ||
| 3187 | var_args: bool, | 3168 | var_args: bool, |
| 3188 | cc: Inst.Ref, | 3169 | cc: Inst.Ref, |
| 3189 | body: []const Inst.Index, | 3170 | body: []const Inst.Index, |
| ... | @@ -3197,7 +3178,8 @@ const Writer = struct { | ... | @@ -3197,7 +3178,8 @@ const Writer = struct { |
| 3197 | try stream.writeAll("], "); | 3178 | try stream.writeAll("], "); |
| 3198 | try self.writeInstRef(stream, ret_ty); | 3179 | try self.writeInstRef(stream, ret_ty); |
| 3199 | try self.writeOptionalInstRef(stream, ", cc=", cc); | 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 | try stream.writeAll(", {\n"); | 3184 | try stream.writeAll(", {\n"); |
| 3203 | self.indent += 2; | 3185 | self.indent += 2; |