| author | |
| committer | |
| log | 34cb5934ddd7c79fb96ffed87768764247740260 |
| tree | d4ca1d9e3c6a335caf311de1383e45758f221438 |
| parent | 9f722f43ac449caa0e09c1b7bb1bad0581ef323d |
| parent | 8c6e7fb2c7488faab0c41a4ea241f0110237ce91 |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
Stage2: astgen async stuff, implement var args functions8 files changed, 370 insertions(+), 43 deletions(-)
src/Module.zig+123-16| ... | @@ -370,6 +370,8 @@ pub const Scope = struct { | ... | @@ -370,6 +370,8 @@ pub const Scope = struct { |
| 370 | .gen_zir => return self.cast(GenZIR).?.arena, | 370 | .gen_zir => return self.cast(GenZIR).?.arena, |
| 371 | .local_val => return self.cast(LocalVal).?.gen_zir.arena, | 371 | .local_val => return self.cast(LocalVal).?.gen_zir.arena, |
| 372 | .local_ptr => return self.cast(LocalPtr).?.gen_zir.arena, | 372 | .local_ptr => return self.cast(LocalPtr).?.gen_zir.arena, |
| 373 | .gen_suspend => return self.cast(GenZIR).?.arena, | ||
| 374 | .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.arena, | ||
| 373 | .file => unreachable, | 375 | .file => unreachable, |
| 374 | .container => unreachable, | 376 | .container => unreachable, |
| 375 | } | 377 | } |
| ... | @@ -385,6 +387,8 @@ pub const Scope = struct { | ... | @@ -385,6 +387,8 @@ pub const Scope = struct { |
| 385 | .gen_zir => self.cast(GenZIR).?.decl, | 387 | .gen_zir => self.cast(GenZIR).?.decl, |
| 386 | .local_val => self.cast(LocalVal).?.gen_zir.decl, | 388 | .local_val => self.cast(LocalVal).?.gen_zir.decl, |
| 387 | .local_ptr => self.cast(LocalPtr).?.gen_zir.decl, | 389 | .local_ptr => self.cast(LocalPtr).?.gen_zir.decl, |
| 390 | .gen_suspend => return self.cast(GenZIR).?.decl, | ||
| 391 | .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.decl, | ||
| 388 | .file => null, | 392 | .file => null, |
| 389 | .container => null, | 393 | .container => null, |
| 390 | }; | 394 | }; |
| ... | @@ -396,6 +400,8 @@ pub const Scope = struct { | ... | @@ -396,6 +400,8 @@ pub const Scope = struct { |
| 396 | .gen_zir => self.cast(GenZIR).?.decl, | 400 | .gen_zir => self.cast(GenZIR).?.decl, |
| 397 | .local_val => self.cast(LocalVal).?.gen_zir.decl, | 401 | .local_val => self.cast(LocalVal).?.gen_zir.decl, |
| 398 | .local_ptr => self.cast(LocalPtr).?.gen_zir.decl, | 402 | .local_ptr => self.cast(LocalPtr).?.gen_zir.decl, |
| 403 | .gen_suspend => return self.cast(GenZIR).?.decl, | ||
| 404 | .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.decl, | ||
| 399 | .file => null, | 405 | .file => null, |
| 400 | .container => null, | 406 | .container => null, |
| 401 | }; | 407 | }; |
| ... | @@ -410,6 +416,8 @@ pub const Scope = struct { | ... | @@ -410,6 +416,8 @@ pub const Scope = struct { |
| 410 | .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.container, | 416 | .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.container, |
| 411 | .file => return &self.cast(File).?.root_container, | 417 | .file => return &self.cast(File).?.root_container, |
| 412 | .container => return self.cast(Container).?, | 418 | .container => return self.cast(Container).?, |
| 419 | .gen_suspend => return self.cast(GenZIR).?.decl.container, | ||
| 420 | .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.decl.container, | ||
| 413 | } | 421 | } |
| 414 | } | 422 | } |
| 415 | 423 | ||
| ... | @@ -422,6 +430,8 @@ pub const Scope = struct { | ... | @@ -422,6 +430,8 @@ pub const Scope = struct { |
| 422 | .gen_zir => unreachable, | 430 | .gen_zir => unreachable, |
| 423 | .local_val => unreachable, | 431 | .local_val => unreachable, |
| 424 | .local_ptr => unreachable, | 432 | .local_ptr => unreachable, |
| 433 | .gen_suspend => unreachable, | ||
| 434 | .gen_nosuspend => unreachable, | ||
| 425 | .file => unreachable, | 435 | .file => unreachable, |
| 426 | .container => return self.cast(Container).?.fullyQualifiedNameHash(name), | 436 | .container => return self.cast(Container).?.fullyQualifiedNameHash(name), |
| 427 | } | 437 | } |
| ... | @@ -436,6 +446,8 @@ pub const Scope = struct { | ... | @@ -436,6 +446,8 @@ pub const Scope = struct { |
| 436 | .local_val => return &self.cast(LocalVal).?.gen_zir.decl.container.file_scope.tree, | 446 | .local_val => return &self.cast(LocalVal).?.gen_zir.decl.container.file_scope.tree, |
| 437 | .local_ptr => return &self.cast(LocalPtr).?.gen_zir.decl.container.file_scope.tree, | 447 | .local_ptr => return &self.cast(LocalPtr).?.gen_zir.decl.container.file_scope.tree, |
| 438 | .container => return &self.cast(Container).?.file_scope.tree, | 448 | .container => return &self.cast(Container).?.file_scope.tree, |
| 449 | .gen_suspend => return &self.cast(GenZIR).?.decl.container.file_scope.tree, | ||
| 450 | .gen_nosuspend => return &self.cast(Nosuspend).?.gen_zir.decl.container.file_scope.tree, | ||
| 439 | } | 451 | } |
| 440 | } | 452 | } |
| 441 | 453 | ||
| ... | @@ -443,9 +455,10 @@ pub const Scope = struct { | ... | @@ -443,9 +455,10 @@ pub const Scope = struct { |
| 443 | pub fn getGenZIR(self: *Scope) *GenZIR { | 455 | pub fn getGenZIR(self: *Scope) *GenZIR { |
| 444 | return switch (self.tag) { | 456 | return switch (self.tag) { |
| 445 | .block => unreachable, | 457 | .block => unreachable, |
| 446 | .gen_zir => self.cast(GenZIR).?, | 458 | .gen_zir, .gen_suspend => self.cast(GenZIR).?, |
| 447 | .local_val => return self.cast(LocalVal).?.gen_zir, | 459 | .local_val => return self.cast(LocalVal).?.gen_zir, |
| 448 | .local_ptr => return self.cast(LocalPtr).?.gen_zir, | 460 | .local_ptr => return self.cast(LocalPtr).?.gen_zir, |
| 461 | .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir, | ||
| 449 | .file => unreachable, | 462 | .file => unreachable, |
| 450 | .container => unreachable, | 463 | .container => unreachable, |
| 451 | }; | 464 | }; |
| ... | @@ -461,6 +474,8 @@ pub const Scope = struct { | ... | @@ -461,6 +474,8 @@ pub const Scope = struct { |
| 461 | .gen_zir => unreachable, | 474 | .gen_zir => unreachable, |
| 462 | .local_val => unreachable, | 475 | .local_val => unreachable, |
| 463 | .local_ptr => unreachable, | 476 | .local_ptr => unreachable, |
| 477 | .gen_suspend => unreachable, | ||
| 478 | .gen_nosuspend => unreachable, | ||
| 464 | } | 479 | } |
| 465 | } | 480 | } |
| 466 | 481 | ||
| ... | @@ -472,6 +487,8 @@ pub const Scope = struct { | ... | @@ -472,6 +487,8 @@ pub const Scope = struct { |
| 472 | .local_val => unreachable, | 487 | .local_val => unreachable, |
| 473 | .local_ptr => unreachable, | 488 | .local_ptr => unreachable, |
| 474 | .block => unreachable, | 489 | .block => unreachable, |
| 490 | .gen_suspend => unreachable, | ||
| 491 | .gen_nosuspend => unreachable, | ||
| 475 | } | 492 | } |
| 476 | } | 493 | } |
| 477 | 494 | ||
| ... | @@ -486,6 +503,36 @@ pub const Scope = struct { | ... | @@ -486,6 +503,36 @@ pub const Scope = struct { |
| 486 | .local_val => @fieldParentPtr(LocalVal, "base", cur).parent, | 503 | .local_val => @fieldParentPtr(LocalVal, "base", cur).parent, |
| 487 | .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent, | 504 | .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent, |
| 488 | .block => return @fieldParentPtr(Block, "base", cur).src_decl.container.file_scope, | 505 | .block => return @fieldParentPtr(Block, "base", cur).src_decl.container.file_scope, |
| 506 | .gen_suspend => @fieldParentPtr(GenZIR, "base", cur).parent, | ||
| 507 | .gen_nosuspend => @fieldParentPtr(Nosuspend, "base", cur).parent, | ||
| 508 | }; | ||
| 509 | } | ||
| 510 | } | ||
| 511 | |||
| 512 | pub fn getSuspend(base: *Scope) ?*Scope.GenZIR { | ||
| 513 | var cur = base; | ||
| 514 | while (true) { | ||
| 515 | cur = switch (cur.tag) { | ||
| 516 | .gen_zir => @fieldParentPtr(GenZIR, "base", cur).parent, | ||
| 517 | .local_val => @fieldParentPtr(LocalVal, "base", cur).parent, | ||
| 518 | .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent, | ||
| 519 | .gen_nosuspend => @fieldParentPtr(Nosuspend, "base", cur).parent, | ||
| 520 | .gen_suspend => return @fieldParentPtr(GenZIR, "base", cur), | ||
| 521 | else => return null, | ||
| 522 | }; | ||
| 523 | } | ||
| 524 | } | ||
| 525 | |||
| 526 | pub fn getNosuspend(base: *Scope) ?*Scope.Nosuspend { | ||
| 527 | var cur = base; | ||
| 528 | while (true) { | ||
| 529 | cur = switch (cur.tag) { | ||
| 530 | .gen_zir => @fieldParentPtr(GenZIR, "base", cur).parent, | ||
| 531 | .local_val => @fieldParentPtr(LocalVal, "base", cur).parent, | ||
| 532 | .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent, | ||
| 533 | .gen_suspend => @fieldParentPtr(GenZIR, "base", cur).parent, | ||
| 534 | .gen_nosuspend => return @fieldParentPtr(Nosuspend, "base", cur), | ||
| 535 | else => return null, | ||
| 489 | }; | 536 | }; |
| 490 | } | 537 | } |
| 491 | } | 538 | } |
| ... | @@ -507,6 +554,8 @@ pub const Scope = struct { | ... | @@ -507,6 +554,8 @@ pub const Scope = struct { |
| 507 | gen_zir, | 554 | gen_zir, |
| 508 | local_val, | 555 | local_val, |
| 509 | local_ptr, | 556 | local_ptr, |
| 557 | gen_suspend, | ||
| 558 | gen_nosuspend, | ||
| 510 | }; | 559 | }; |
| 511 | 560 | ||
| 512 | pub const Container = struct { | 561 | pub const Container = struct { |
| ... | @@ -740,6 +789,8 @@ pub const Scope = struct { | ... | @@ -740,6 +789,8 @@ pub const Scope = struct { |
| 740 | /// so they can possibly be elided later if the labeled block ends up not needing | 789 | /// so they can possibly be elided later if the labeled block ends up not needing |
| 741 | /// a result location pointer. | 790 | /// a result location pointer. |
| 742 | labeled_store_to_block_ptr_list: std.ArrayListUnmanaged(*zir.Inst.BinOp) = .{}, | 791 | labeled_store_to_block_ptr_list: std.ArrayListUnmanaged(*zir.Inst.BinOp) = .{}, |
| 792 | /// for suspend error notes | ||
| 793 | src: usize = 0, | ||
| 743 | 794 | ||
| 744 | pub const Label = struct { | 795 | pub const Label = struct { |
| 745 | token: ast.TokenIndex, | 796 | token: ast.TokenIndex, |
| ... | @@ -773,6 +824,16 @@ pub const Scope = struct { | ... | @@ -773,6 +824,16 @@ pub const Scope = struct { |
| 773 | name: []const u8, | 824 | name: []const u8, |
| 774 | ptr: *zir.Inst, | 825 | ptr: *zir.Inst, |
| 775 | }; | 826 | }; |
| 827 | |||
| 828 | pub const Nosuspend = struct { | ||
| 829 | pub const base_tag: Tag = .gen_nosuspend; | ||
| 830 | |||
| 831 | base: Scope = Scope{ .tag = base_tag }, | ||
| 832 | /// Parents can be: `LocalVal`, `LocalPtr`, `GenZIR`. | ||
| 833 | parent: *Scope, | ||
| 834 | gen_zir: *GenZIR, | ||
| 835 | src: usize, | ||
| 836 | }; | ||
| 776 | }; | 837 | }; |
| 777 | 838 | ||
| 778 | /// This struct holds data necessary to construct API-facing `AllErrors.Message`. | 839 | /// This struct holds data necessary to construct API-facing `AllErrors.Message`. |
| ... | @@ -1122,7 +1183,8 @@ fn astgenAndSemaFn( | ... | @@ -1122,7 +1183,8 @@ fn astgenAndSemaFn( |
| 1122 | const param_count = blk: { | 1183 | const param_count = blk: { |
| 1123 | var count: usize = 0; | 1184 | var count: usize = 0; |
| 1124 | var it = fn_proto.iterate(tree); | 1185 | var it = fn_proto.iterate(tree); |
| 1125 | while (it.next()) |_| { | 1186 | while (it.next()) |param| { |
| 1187 | if (param.anytype_ellipsis3) |some| if (token_tags[some] == .ellipsis3) break; | ||
| 1126 | count += 1; | 1188 | count += 1; |
| 1127 | } | 1189 | } |
| 1128 | break :blk count; | 1190 | break :blk count; |
| ... | @@ -1135,6 +1197,7 @@ fn astgenAndSemaFn( | ... | @@ -1135,6 +1197,7 @@ fn astgenAndSemaFn( |
| 1135 | }); | 1197 | }); |
| 1136 | const type_type_rl: astgen.ResultLoc = .{ .ty = type_type }; | 1198 | const type_type_rl: astgen.ResultLoc = .{ .ty = type_type }; |
| 1137 | 1199 | ||
| 1200 | var is_var_args = false; | ||
| 1138 | { | 1201 | { |
| 1139 | var param_type_i: usize = 0; | 1202 | var param_type_i: usize = 0; |
| 1140 | var it = fn_proto.iterate(tree); | 1203 | var it = fn_proto.iterate(tree); |
| ... | @@ -1147,12 +1210,10 @@ fn astgenAndSemaFn( | ... | @@ -1147,12 +1210,10 @@ fn astgenAndSemaFn( |
| 1147 | "TODO implement anytype parameter", | 1210 | "TODO implement anytype parameter", |
| 1148 | .{}, | 1211 | .{}, |
| 1149 | ), | 1212 | ), |
| 1150 | .ellipsis3 => return mod.failTok( | 1213 | .ellipsis3 => { |
| 1151 | &fn_type_scope.base, | 1214 | is_var_args = true; |
| 1152 | token, | 1215 | break; |
| 1153 | "TODO implement var args", | 1216 | }, |
| 1154 | .{}, | ||
| 1155 | ), | ||
| 1156 | else => unreachable, | 1217 | else => unreachable, |
| 1157 | } | 1218 | } |
| 1158 | } | 1219 | } |
| ... | @@ -1234,7 +1295,13 @@ fn astgenAndSemaFn( | ... | @@ -1234,7 +1295,13 @@ fn astgenAndSemaFn( |
| 1234 | type_type_rl, | 1295 | type_type_rl, |
| 1235 | fn_proto.ast.return_type, | 1296 | fn_proto.ast.return_type, |
| 1236 | ); | 1297 | ); |
| 1237 | const fn_type_inst = if (fn_proto.ast.callconv_expr != 0) cc: { | 1298 | |
| 1299 | const is_extern = if (fn_proto.extern_export_token) |maybe_export_token| | ||
| 1300 | token_tags[maybe_export_token] == .keyword_extern | ||
| 1301 | else | ||
| 1302 | false; | ||
| 1303 | |||
| 1304 | const cc_inst = if (fn_proto.ast.callconv_expr != 0) cc: { | ||
| 1238 | // TODO instead of enum literal type, this needs to be the | 1305 | // TODO instead of enum literal type, this needs to be the |
| 1239 | // std.builtin.CallingConvention enum. We need to implement importing other files | 1306 | // std.builtin.CallingConvention enum. We need to implement importing other files |
| 1240 | // and enums in order to fix this. | 1307 | // and enums in order to fix this. |
| ... | @@ -1243,18 +1310,31 @@ fn astgenAndSemaFn( | ... | @@ -1243,18 +1310,31 @@ fn astgenAndSemaFn( |
| 1243 | .ty = Type.initTag(.type), | 1310 | .ty = Type.initTag(.type), |
| 1244 | .val = Value.initTag(.enum_literal_type), | 1311 | .val = Value.initTag(.enum_literal_type), |
| 1245 | }); | 1312 | }); |
| 1246 | const cc = try astgen.comptimeExpr(mod, &fn_type_scope.base, .{ | 1313 | break :cc try astgen.comptimeExpr(mod, &fn_type_scope.base, .{ |
| 1247 | .ty = enum_lit_ty, | 1314 | .ty = enum_lit_ty, |
| 1248 | }, fn_proto.ast.callconv_expr); | 1315 | }, fn_proto.ast.callconv_expr); |
| 1249 | break :cc try astgen.addZirInstTag(mod, &fn_type_scope.base, fn_src, .fn_type_cc, .{ | 1316 | } else if (is_extern) cc: { |
| 1317 | // note: https://github.com/ziglang/zig/issues/5269 | ||
| 1318 | const src = token_starts[fn_proto.extern_export_token.?]; | ||
| 1319 | break :cc try astgen.addZIRInst(mod, &fn_type_scope.base, src, zir.Inst.EnumLiteral, .{ .name = "C" }, .{}); | ||
| 1320 | } else null; | ||
| 1321 | |||
| 1322 | const fn_type_inst = if (cc_inst) |cc| fn_type: { | ||
| 1323 | var fn_type = try astgen.addZirInstTag(mod, &fn_type_scope.base, fn_src, .fn_type_cc, .{ | ||
| 1250 | .return_type = return_type_inst, | 1324 | .return_type = return_type_inst, |
| 1251 | .param_types = param_types, | 1325 | .param_types = param_types, |
| 1252 | .cc = cc, | 1326 | .cc = cc, |
| 1253 | }); | 1327 | }); |
| 1254 | } else try astgen.addZirInstTag(mod, &fn_type_scope.base, fn_src, .fn_type, .{ | 1328 | if (is_var_args) fn_type.tag = .fn_type_cc_var_args; |
| 1255 | .return_type = return_type_inst, | 1329 | break :fn_type fn_type; |
| 1256 | .param_types = param_types, | 1330 | } else fn_type: { |
| 1257 | }); | 1331 | var fn_type = try astgen.addZirInstTag(mod, &fn_type_scope.base, fn_src, .fn_type, .{ |
| 1332 | .return_type = return_type_inst, | ||
| 1333 | .param_types = param_types, | ||
| 1334 | }); | ||
| 1335 | if (is_var_args) fn_type.tag = .fn_type_var_args; | ||
| 1336 | break :fn_type fn_type; | ||
| 1337 | }; | ||
| 1258 | 1338 | ||
| 1259 | if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { | 1339 | if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { |
| 1260 | zir.dumpZir(mod.gpa, "fn_type", decl.name, fn_type_scope.instructions.items) catch {}; | 1340 | zir.dumpZir(mod.gpa, "fn_type", decl.name, fn_type_scope.instructions.items) catch {}; |
| ... | @@ -1287,7 +1367,12 @@ fn astgenAndSemaFn( | ... | @@ -1287,7 +1367,12 @@ fn astgenAndSemaFn( |
| 1287 | const fn_type = try zir_sema.analyzeBodyValueAsType(mod, &block_scope, fn_type_inst, .{ | 1367 | const fn_type = try zir_sema.analyzeBodyValueAsType(mod, &block_scope, fn_type_inst, .{ |
| 1288 | .instructions = fn_type_scope.instructions.items, | 1368 | .instructions = fn_type_scope.instructions.items, |
| 1289 | }); | 1369 | }); |
| 1370 | |||
| 1290 | if (body_node == 0) { | 1371 | if (body_node == 0) { |
| 1372 | if (!is_extern) { | ||
| 1373 | return mod.failNode(&block_scope.base, fn_proto.ast.fn_token, "non-extern function has no body", .{}); | ||
| 1374 | } | ||
| 1375 | |||
| 1291 | // Extern function. | 1376 | // Extern function. |
| 1292 | var type_changed = true; | 1377 | var type_changed = true; |
| 1293 | if (decl.typedValueManaged()) |tvm| { | 1378 | if (decl.typedValueManaged()) |tvm| { |
| ... | @@ -1317,6 +1402,10 @@ fn astgenAndSemaFn( | ... | @@ -1317,6 +1402,10 @@ fn astgenAndSemaFn( |
| 1317 | return type_changed; | 1402 | return type_changed; |
| 1318 | } | 1403 | } |
| 1319 | 1404 | ||
| 1405 | if (fn_type.fnIsVarArgs()) { | ||
| 1406 | return mod.failNode(&block_scope.base, fn_proto.ast.fn_token, "non-extern function is variadic", .{}); | ||
| 1407 | } | ||
| 1408 | |||
| 1320 | const new_func = try decl_arena.allocator.create(Fn); | 1409 | const new_func = try decl_arena.allocator.create(Fn); |
| 1321 | const fn_payload = try decl_arena.allocator.create(Value.Payload.Function); | 1410 | const fn_payload = try decl_arena.allocator.create(Value.Payload.Function); |
| 1322 | 1411 | ||
| ... | @@ -3295,6 +3384,9 @@ pub fn resolvePeerTypes(self: *Module, scope: *Scope, instructions: []*Inst) !Ty | ... | @@ -3295,6 +3384,9 @@ pub fn resolvePeerTypes(self: *Module, scope: *Scope, instructions: []*Inst) !Ty |
| 3295 | } | 3384 | } |
| 3296 | 3385 | ||
| 3297 | pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) InnerError!*Inst { | 3386 | pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) InnerError!*Inst { |
| 3387 | if (dest_type.tag() == .var_args_param) { | ||
| 3388 | return self.coerceVarArgParam(scope, inst); | ||
| 3389 | } | ||
| 3298 | // If the types are the same, we can return the operand. | 3390 | // If the types are the same, we can return the operand. |
| 3299 | if (dest_type.eql(inst.ty)) | 3391 | if (dest_type.eql(inst.ty)) |
| 3300 | return inst; | 3392 | return inst; |
| ... | @@ -3447,6 +3539,15 @@ pub fn coerceNum(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) Inn | ... | @@ -3447,6 +3539,15 @@ pub fn coerceNum(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) Inn |
| 3447 | return null; | 3539 | return null; |
| 3448 | } | 3540 | } |
| 3449 | 3541 | ||
| 3542 | pub fn coerceVarArgParam(mod: *Module, scope: *Scope, inst: *Inst) !*Inst { | ||
| 3543 | switch (inst.ty.zigTypeTag()) { | ||
| 3544 | .ComptimeInt, .ComptimeFloat => return mod.fail(scope, inst.src, "integer and float literals in var args function must be casted", .{}), | ||
| 3545 | else => {}, | ||
| 3546 | } | ||
| 3547 | // TODO implement more of this function. | ||
| 3548 | return inst; | ||
| 3549 | } | ||
| 3550 | |||
| 3450 | pub fn storePtr(self: *Module, scope: *Scope, src: usize, ptr: *Inst, uncasted_value: *Inst) !*Inst { | 3551 | pub fn storePtr(self: *Module, scope: *Scope, src: usize, ptr: *Inst, uncasted_value: *Inst) !*Inst { |
| 3451 | if (ptr.ty.isConstPtr()) | 3552 | if (ptr.ty.isConstPtr()) |
| 3452 | return self.fail(scope, src, "cannot assign to constant", .{}); | 3553 | return self.fail(scope, src, "cannot assign to constant", .{}); |
| ... | @@ -3586,7 +3687,7 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I | ... | @@ -3586,7 +3687,7 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I |
| 3586 | } | 3687 | } |
| 3587 | self.failed_decls.putAssumeCapacityNoClobber(block.owner_decl, err_msg); | 3688 | self.failed_decls.putAssumeCapacityNoClobber(block.owner_decl, err_msg); |
| 3588 | }, | 3689 | }, |
| 3589 | .gen_zir => { | 3690 | .gen_zir, .gen_suspend => { |
| 3590 | const gen_zir = scope.cast(Scope.GenZIR).?; | 3691 | const gen_zir = scope.cast(Scope.GenZIR).?; |
| 3591 | gen_zir.decl.analysis = .sema_failure; | 3692 | gen_zir.decl.analysis = .sema_failure; |
| 3592 | gen_zir.decl.generation = self.generation; | 3693 | gen_zir.decl.generation = self.generation; |
| ... | @@ -3604,6 +3705,12 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I | ... | @@ -3604,6 +3705,12 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I |
| 3604 | gen_zir.decl.generation = self.generation; | 3705 | gen_zir.decl.generation = self.generation; |
| 3605 | self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg); | 3706 | self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg); |
| 3606 | }, | 3707 | }, |
| 3708 | .gen_nosuspend => { | ||
| 3709 | const gen_zir = scope.cast(Scope.Nosuspend).?.gen_zir; | ||
| 3710 | gen_zir.decl.analysis = .sema_failure; | ||
| 3711 | gen_zir.decl.generation = self.generation; | ||
| 3712 | self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg); | ||
| 3713 | }, | ||
| 3607 | .file => unreachable, | 3714 | .file => unreachable, |
| 3608 | .container => unreachable, | 3715 | .container => unreachable, |
| 3609 | } | 3716 | } |
src/astgen.zig+110-5| ... | @@ -626,10 +626,13 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -626,10 +626,13 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 626 | .@"comptime" => return comptimeExpr(mod, scope, rl, node_datas[node].lhs), | 626 | .@"comptime" => return comptimeExpr(mod, scope, rl, node_datas[node].lhs), |
| 627 | .@"switch", .switch_comma => return switchExpr(mod, scope, rl, node), | 627 | .@"switch", .switch_comma => return switchExpr(mod, scope, rl, node), |
| 628 | 628 | ||
| 629 | .@"nosuspend" => return nosuspendExpr(mod, scope, rl, node), | ||
| 630 | .@"suspend" => return rvalue(mod, scope, rl, try suspendExpr(mod, scope, node)), | ||
| 631 | .@"await" => return awaitExpr(mod, scope, rl, node), | ||
| 632 | .@"resume" => return rvalue(mod, scope, rl, try resumeExpr(mod, scope, node)), | ||
| 633 | |||
| 629 | .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}), | 634 | .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}), |
| 630 | .@"errdefer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .errdefer", .{}), | 635 | .@"errdefer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .errdefer", .{}), |
| 631 | .@"await" => return mod.failNode(scope, node, "TODO implement astgen.expr for .await", .{}), | ||
| 632 | .@"resume" => return mod.failNode(scope, node, "TODO implement astgen.expr for .resume", .{}), | ||
| 633 | .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), | 636 | .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), |
| 634 | 637 | ||
| 635 | .array_init_one, | 638 | .array_init_one, |
| ... | @@ -652,15 +655,12 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -652,15 +655,12 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 652 | .struct_init_comma, | 655 | .struct_init_comma, |
| 653 | => return mod.failNode(scope, node, "TODO implement astgen.expr for struct literals", .{}), | 656 | => return mod.failNode(scope, node, "TODO implement astgen.expr for struct literals", .{}), |
| 654 | 657 | ||
| 655 | .@"suspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .suspend", .{}), | ||
| 656 | .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}), | 658 | .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}), |
| 657 | .fn_proto_simple, | 659 | .fn_proto_simple, |
| 658 | .fn_proto_multi, | 660 | .fn_proto_multi, |
| 659 | .fn_proto_one, | 661 | .fn_proto_one, |
| 660 | .fn_proto, | 662 | .fn_proto, |
| 661 | => return mod.failNode(scope, node, "TODO implement astgen.expr for function prototypes", .{}), | 663 | => return mod.failNode(scope, node, "TODO implement astgen.expr for function prototypes", .{}), |
| 662 | |||
| 663 | .@"nosuspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .nosuspend", .{}), | ||
| 664 | } | 664 | } |
| 665 | } | 665 | } |
| 666 | 666 | ||
| ... | @@ -766,6 +766,8 @@ fn breakExpr( | ... | @@ -766,6 +766,8 @@ fn breakExpr( |
| 766 | }, | 766 | }, |
| 767 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 767 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 768 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 768 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 769 | .gen_suspend => scope = scope.cast(Scope.GenZIR).?.parent, | ||
| 770 | .gen_nosuspend => scope = scope.cast(Scope.Nosuspend).?.parent, | ||
| 769 | else => if (break_label != 0) { | 771 | else => if (break_label != 0) { |
| 770 | const label_name = try mod.identifierTokenString(parent_scope, break_label); | 772 | const label_name = try mod.identifierTokenString(parent_scope, break_label); |
| 771 | return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name}); | 773 | return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name}); |
| ... | @@ -819,6 +821,8 @@ fn continueExpr( | ... | @@ -819,6 +821,8 @@ fn continueExpr( |
| 819 | }, | 821 | }, |
| 820 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 822 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 821 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 823 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 824 | .gen_suspend => scope = scope.cast(Scope.GenZIR).?.parent, | ||
| 825 | .gen_nosuspend => scope = scope.cast(Scope.Nosuspend).?.parent, | ||
| 822 | else => if (break_label != 0) { | 826 | else => if (break_label != 0) { |
| 823 | const label_name = try mod.identifierTokenString(parent_scope, break_label); | 827 | const label_name = try mod.identifierTokenString(parent_scope, break_label); |
| 824 | return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name}); | 828 | return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name}); |
| ... | @@ -893,6 +897,8 @@ fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIn | ... | @@ -893,6 +897,8 @@ fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIn |
| 893 | }, | 897 | }, |
| 894 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 898 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 895 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 899 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 900 | .gen_suspend => scope = scope.cast(Scope.GenZIR).?.parent, | ||
| 901 | .gen_nosuspend => scope = scope.cast(Scope.Nosuspend).?.parent, | ||
| 896 | else => return, | 902 | else => return, |
| 897 | } | 903 | } |
| 898 | } | 904 | } |
| ... | @@ -1100,6 +1106,8 @@ fn varDecl( | ... | @@ -1100,6 +1106,8 @@ fn varDecl( |
| 1100 | s = local_ptr.parent; | 1106 | s = local_ptr.parent; |
| 1101 | }, | 1107 | }, |
| 1102 | .gen_zir => s = s.cast(Scope.GenZIR).?.parent, | 1108 | .gen_zir => s = s.cast(Scope.GenZIR).?.parent, |
| 1109 | .gen_suspend => s = s.cast(Scope.GenZIR).?.parent, | ||
| 1110 | .gen_nosuspend => s = s.cast(Scope.Nosuspend).?.parent, | ||
| 1103 | else => break, | 1111 | else => break, |
| 1104 | }; | 1112 | }; |
| 1105 | } | 1113 | } |
| ... | @@ -3021,6 +3029,8 @@ fn identifier( | ... | @@ -3021,6 +3029,8 @@ fn identifier( |
| 3021 | s = local_ptr.parent; | 3029 | s = local_ptr.parent; |
| 3022 | }, | 3030 | }, |
| 3023 | .gen_zir => s = s.cast(Scope.GenZIR).?.parent, | 3031 | .gen_zir => s = s.cast(Scope.GenZIR).?.parent, |
| 3032 | .gen_suspend => s = s.cast(Scope.GenZIR).?.parent, | ||
| 3033 | .gen_nosuspend => s = s.cast(Scope.Nosuspend).?.parent, | ||
| 3024 | else => break, | 3034 | else => break, |
| 3025 | }; | 3035 | }; |
| 3026 | } | 3036 | } |
| ... | @@ -3633,14 +3643,109 @@ fn callExpr( | ... | @@ -3633,14 +3643,109 @@ fn callExpr( |
| 3633 | } | 3643 | } |
| 3634 | 3644 | ||
| 3635 | const src = token_starts[call.ast.lparen]; | 3645 | const src = token_starts[call.ast.lparen]; |
| 3646 | var modifier: std.builtin.CallOptions.Modifier = .auto; | ||
| 3647 | if (call.async_token) |_| modifier = .async_kw; | ||
| 3648 | |||
| 3636 | const result = try addZIRInst(mod, scope, src, zir.Inst.Call, .{ | 3649 | const result = try addZIRInst(mod, scope, src, zir.Inst.Call, .{ |
| 3637 | .func = lhs, | 3650 | .func = lhs, |
| 3638 | .args = args, | 3651 | .args = args, |
| 3652 | .modifier = modifier, | ||
| 3639 | }, .{}); | 3653 | }, .{}); |
| 3640 | // TODO function call with result location | 3654 | // TODO function call with result location |
| 3641 | return rvalue(mod, scope, rl, result); | 3655 | return rvalue(mod, scope, rl, result); |
| 3642 | } | 3656 | } |
| 3643 | 3657 | ||
| 3658 | fn suspendExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst { | ||
| 3659 | const tree = scope.tree(); | ||
| 3660 | const src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]]; | ||
| 3661 | |||
| 3662 | if (scope.getNosuspend()) |some| { | ||
| 3663 | const msg = msg: { | ||
| 3664 | const msg = try mod.errMsg(scope, src, "suspend in nosuspend block", .{}); | ||
| 3665 | errdefer msg.destroy(mod.gpa); | ||
| 3666 | try mod.errNote(scope, some.src, msg, "nosuspend block here", .{}); | ||
| 3667 | break :msg msg; | ||
| 3668 | }; | ||
| 3669 | return mod.failWithOwnedErrorMsg(scope, msg); | ||
| 3670 | } | ||
| 3671 | |||
| 3672 | if (scope.getSuspend()) |some| { | ||
| 3673 | const msg = msg: { | ||
| 3674 | const msg = try mod.errMsg(scope, src, "cannot suspend inside suspend block", .{}); | ||
| 3675 | errdefer msg.destroy(mod.gpa); | ||
| 3676 | try mod.errNote(scope, some.src, msg, "other suspend block here", .{}); | ||
| 3677 | break :msg msg; | ||
| 3678 | }; | ||
| 3679 | return mod.failWithOwnedErrorMsg(scope, msg); | ||
| 3680 | } | ||
| 3681 | |||
| 3682 | var suspend_scope: Scope.GenZIR = .{ | ||
| 3683 | .base = .{ .tag = .gen_suspend }, | ||
| 3684 | .parent = scope, | ||
| 3685 | .decl = scope.ownerDecl().?, | ||
| 3686 | .arena = scope.arena(), | ||
| 3687 | .force_comptime = scope.isComptime(), | ||
| 3688 | .instructions = .{}, | ||
| 3689 | }; | ||
| 3690 | defer suspend_scope.instructions.deinit(mod.gpa); | ||
| 3691 | |||
| 3692 | const operand = tree.nodes.items(.data)[node].lhs; | ||
| 3693 | if (operand != 0) { | ||
| 3694 | const possibly_unused_result = try expr(mod, &suspend_scope.base, .none, operand); | ||
| 3695 | if (!possibly_unused_result.tag.isNoReturn()) { | ||
| 3696 | _ = try addZIRUnOp(mod, &suspend_scope.base, src, .ensure_result_used, possibly_unused_result); | ||
| 3697 | } | ||
| 3698 | } else { | ||
| 3699 | return addZIRNoOp(mod, scope, src, .@"suspend"); | ||
| 3700 | } | ||
| 3701 | |||
| 3702 | const block = try addZIRInstBlock(mod, scope, src, .suspend_block, .{ | ||
| 3703 | .instructions = try scope.arena().dupe(*zir.Inst, suspend_scope.instructions.items), | ||
| 3704 | }); | ||
| 3705 | return &block.base; | ||
| 3706 | } | ||
| 3707 | |||
| 3708 | fn nosuspendExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!*zir.Inst { | ||
| 3709 | const tree = scope.tree(); | ||
| 3710 | var child_scope = Scope.Nosuspend{ | ||
| 3711 | .parent = scope, | ||
| 3712 | .gen_zir = scope.getGenZIR(), | ||
| 3713 | .src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]], | ||
| 3714 | }; | ||
| 3715 | |||
| 3716 | return expr(mod, &child_scope.base, rl, tree.nodes.items(.data)[node].lhs); | ||
| 3717 | } | ||
| 3718 | |||
| 3719 | fn awaitExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!*zir.Inst { | ||
| 3720 | const tree = scope.tree(); | ||
| 3721 | const src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]]; | ||
| 3722 | const is_nosuspend = scope.getNosuspend() != null; | ||
| 3723 | |||
| 3724 | // TODO some @asyncCall stuff | ||
| 3725 | |||
| 3726 | if (scope.getSuspend()) |some| { | ||
| 3727 | const msg = msg: { | ||
| 3728 | const msg = try mod.errMsg(scope, src, "cannot await inside suspend block", .{}); | ||
| 3729 | errdefer msg.destroy(mod.gpa); | ||
| 3730 | try mod.errNote(scope, some.src, msg, "suspend block here", .{}); | ||
| 3731 | break :msg msg; | ||
| 3732 | }; | ||
| 3733 | return mod.failWithOwnedErrorMsg(scope, msg); | ||
| 3734 | } | ||
| 3735 | |||
| 3736 | const operand = try expr(mod, scope, .ref, tree.nodes.items(.data)[node].lhs); | ||
| 3737 | // TODO pass result location | ||
| 3738 | return addZIRUnOp(mod, scope, src, if (is_nosuspend) .nosuspend_await else .@"await", operand); | ||
| 3739 | } | ||
| 3740 | |||
| 3741 | fn resumeExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst { | ||
| 3742 | const tree = scope.tree(); | ||
| 3743 | const src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]]; | ||
| 3744 | |||
| 3745 | const operand = try expr(mod, scope, .ref, tree.nodes.items(.data)[node].lhs); | ||
| 3746 | return addZIRUnOp(mod, scope, src, .@"resume", operand); | ||
| 3747 | } | ||
| 3748 | |||
| 3644 | pub const simple_types = std.ComptimeStringMap(Value.Tag, .{ | 3749 | pub const simple_types = std.ComptimeStringMap(Value.Tag, .{ |
| 3645 | .{ "u8", .u8_type }, | 3750 | .{ "u8", .u8_type }, |
| 3646 | .{ "i8", .i8_type }, | 3751 | .{ "i8", .i8_type }, |
src/codegen/c.zig+7-2| ... | @@ -215,8 +215,9 @@ pub const DeclGen = struct { | ... | @@ -215,8 +215,9 @@ pub const DeclGen = struct { |
| 215 | try dg.renderType(w, tv.ty.fnReturnType()); | 215 | try dg.renderType(w, tv.ty.fnReturnType()); |
| 216 | const decl_name = mem.span(dg.decl.name); | 216 | const decl_name = mem.span(dg.decl.name); |
| 217 | try w.print(" {s}(", .{decl_name}); | 217 | try w.print(" {s}(", .{decl_name}); |
| 218 | var param_len = tv.ty.fnParamLen(); | 218 | const param_len = tv.ty.fnParamLen(); |
| 219 | if (param_len == 0) | 219 | const is_var_args = tv.ty.fnIsVarArgs(); |
| 220 | if (param_len == 0 and !is_var_args) | ||
| 220 | try w.writeAll("void") | 221 | try w.writeAll("void") |
| 221 | else { | 222 | else { |
| 222 | var index: usize = 0; | 223 | var index: usize = 0; |
| ... | @@ -228,6 +229,10 @@ pub const DeclGen = struct { | ... | @@ -228,6 +229,10 @@ pub const DeclGen = struct { |
| 228 | try w.print(" a{d}", .{index}); | 229 | try w.print(" a{d}", .{index}); |
| 229 | } | 230 | } |
| 230 | } | 231 | } |
| 232 | if (is_var_args) { | ||
| 233 | if (param_len != 0) try w.writeAll(", "); | ||
| 234 | try w.writeAll("..."); | ||
| 235 | } | ||
| 231 | try w.writeByte(')'); | 236 | try w.writeByte(')'); |
| 232 | } | 237 | } |
| 233 | 238 |
src/test.zig+1| ... | @@ -871,6 +871,7 @@ pub const TestContext = struct { | ... | @@ -871,6 +871,7 @@ pub const TestContext = struct { |
| 871 | "-std=c89", | 871 | "-std=c89", |
| 872 | "-pedantic", | 872 | "-pedantic", |
| 873 | "-Werror", | 873 | "-Werror", |
| 874 | "-Wno-incompatible-library-redeclaration", // https://github.com/ziglang/zig/issues/875 | ||
| 874 | "-Wno-declaration-after-statement", | 875 | "-Wno-declaration-after-statement", |
| 875 | "--", | 876 | "--", |
| 876 | "-lc", | 877 | "-lc", |
src/type.zig+46-1| ... | @@ -97,6 +97,8 @@ pub const Type = extern union { | ... | @@ -97,6 +97,8 @@ pub const Type = extern union { |
| 97 | .@"struct", .empty_struct => return .Struct, | 97 | .@"struct", .empty_struct => return .Struct, |
| 98 | .@"enum" => return .Enum, | 98 | .@"enum" => return .Enum, |
| 99 | .@"union" => return .Union, | 99 | .@"union" => return .Union, |
| 100 | |||
| 101 | .var_args_param => unreachable, // can be any type | ||
| 100 | } | 102 | } |
| 101 | } | 103 | } |
| 102 | 104 | ||
| ... | @@ -258,6 +260,8 @@ pub const Type = extern union { | ... | @@ -258,6 +260,8 @@ pub const Type = extern union { |
| 258 | if (!a.fnParamType(i).eql(b.fnParamType(i))) | 260 | if (!a.fnParamType(i).eql(b.fnParamType(i))) |
| 259 | return false; | 261 | return false; |
| 260 | } | 262 | } |
| 263 | if (a.fnIsVarArgs() != b.fnIsVarArgs()) | ||
| 264 | return false; | ||
| 261 | return true; | 265 | return true; |
| 262 | }, | 266 | }, |
| 263 | .Optional => { | 267 | .Optional => { |
| ... | @@ -323,6 +327,7 @@ pub const Type = extern union { | ... | @@ -323,6 +327,7 @@ pub const Type = extern union { |
| 323 | while (i < params_len) : (i += 1) { | 327 | while (i < params_len) : (i += 1) { |
| 324 | std.hash.autoHash(&hasher, self.fnParamType(i).hash()); | 328 | std.hash.autoHash(&hasher, self.fnParamType(i).hash()); |
| 325 | } | 329 | } |
| 330 | std.hash.autoHash(&hasher, self.fnIsVarArgs()); | ||
| 326 | }, | 331 | }, |
| 327 | .Optional => { | 332 | .Optional => { |
| 328 | var buf: Payload.ElemType = undefined; | 333 | var buf: Payload.ElemType = undefined; |
| ... | @@ -397,6 +402,7 @@ pub const Type = extern union { | ... | @@ -397,6 +402,7 @@ pub const Type = extern union { |
| 397 | .@"anyframe", | 402 | .@"anyframe", |
| 398 | .inferred_alloc_const, | 403 | .inferred_alloc_const, |
| 399 | .inferred_alloc_mut, | 404 | .inferred_alloc_mut, |
| 405 | .var_args_param, | ||
| 400 | => unreachable, | 406 | => unreachable, |
| 401 | 407 | ||
| 402 | .array_u8, | 408 | .array_u8, |
| ... | @@ -446,6 +452,7 @@ pub const Type = extern union { | ... | @@ -446,6 +452,7 @@ pub const Type = extern union { |
| 446 | .return_type = try payload.return_type.copy(allocator), | 452 | .return_type = try payload.return_type.copy(allocator), |
| 447 | .param_types = param_types, | 453 | .param_types = param_types, |
| 448 | .cc = payload.cc, | 454 | .cc = payload.cc, |
| 455 | .is_var_args = payload.is_var_args, | ||
| 449 | }); | 456 | }); |
| 450 | }, | 457 | }, |
| 451 | .pointer => { | 458 | .pointer => { |
| ... | @@ -535,6 +542,7 @@ pub const Type = extern union { | ... | @@ -535,6 +542,7 @@ pub const Type = extern union { |
| 535 | .comptime_int, | 542 | .comptime_int, |
| 536 | .comptime_float, | 543 | .comptime_float, |
| 537 | .noreturn, | 544 | .noreturn, |
| 545 | .var_args_param, | ||
| 538 | => return out_stream.writeAll(@tagName(t)), | 546 | => return out_stream.writeAll(@tagName(t)), |
| 539 | 547 | ||
| 540 | .enum_literal => return out_stream.writeAll("@Type(.EnumLiteral)"), | 548 | .enum_literal => return out_stream.writeAll("@Type(.EnumLiteral)"), |
| ... | @@ -558,6 +566,12 @@ pub const Type = extern union { | ... | @@ -558,6 +566,12 @@ pub const Type = extern union { |
| 558 | if (i != 0) try out_stream.writeAll(", "); | 566 | if (i != 0) try out_stream.writeAll(", "); |
| 559 | try param_type.format("", .{}, out_stream); | 567 | try param_type.format("", .{}, out_stream); |
| 560 | } | 568 | } |
| 569 | if (payload.is_var_args) { | ||
| 570 | if (payload.param_types.len != 0) { | ||
| 571 | try out_stream.writeAll(", "); | ||
| 572 | } | ||
| 573 | try out_stream.writeAll("..."); | ||
| 574 | } | ||
| 561 | try out_stream.writeAll(") callconv(."); | 575 | try out_stream.writeAll(") callconv(."); |
| 562 | try out_stream.writeAll(@tagName(payload.cc)); | 576 | try out_stream.writeAll(@tagName(payload.cc)); |
| 563 | try out_stream.writeAll(")"); | 577 | try out_stream.writeAll(")"); |
| ... | @@ -844,6 +858,7 @@ pub const Type = extern union { | ... | @@ -844,6 +858,7 @@ pub const Type = extern union { |
| 844 | 858 | ||
| 845 | .inferred_alloc_const => unreachable, | 859 | .inferred_alloc_const => unreachable, |
| 846 | .inferred_alloc_mut => unreachable, | 860 | .inferred_alloc_mut => unreachable, |
| 861 | .var_args_param => unreachable, | ||
| 847 | }; | 862 | }; |
| 848 | } | 863 | } |
| 849 | 864 | ||
| ... | @@ -969,6 +984,7 @@ pub const Type = extern union { | ... | @@ -969,6 +984,7 @@ pub const Type = extern union { |
| 969 | .inferred_alloc_const, | 984 | .inferred_alloc_const, |
| 970 | .inferred_alloc_mut, | 985 | .inferred_alloc_mut, |
| 971 | .@"opaque", | 986 | .@"opaque", |
| 987 | .var_args_param, | ||
| 972 | => unreachable, | 988 | => unreachable, |
| 973 | }; | 989 | }; |
| 974 | } | 990 | } |
| ... | @@ -995,6 +1011,7 @@ pub const Type = extern union { | ... | @@ -995,6 +1011,7 @@ pub const Type = extern union { |
| 995 | .inferred_alloc_const => unreachable, | 1011 | .inferred_alloc_const => unreachable, |
| 996 | .inferred_alloc_mut => unreachable, | 1012 | .inferred_alloc_mut => unreachable, |
| 997 | .@"opaque" => unreachable, | 1013 | .@"opaque" => unreachable, |
| 1014 | .var_args_param => unreachable, | ||
| 998 | 1015 | ||
| 999 | .u8, | 1016 | .u8, |
| 1000 | .i8, | 1017 | .i8, |
| ... | @@ -1179,6 +1196,7 @@ pub const Type = extern union { | ... | @@ -1179,6 +1196,7 @@ pub const Type = extern union { |
| 1179 | .@"struct", | 1196 | .@"struct", |
| 1180 | .@"union", | 1197 | .@"union", |
| 1181 | .@"opaque", | 1198 | .@"opaque", |
| 1199 | .var_args_param, | ||
| 1182 | => false, | 1200 | => false, |
| 1183 | 1201 | ||
| 1184 | .single_const_pointer, | 1202 | .single_const_pointer, |
| ... | @@ -1256,6 +1274,7 @@ pub const Type = extern union { | ... | @@ -1256,6 +1274,7 @@ pub const Type = extern union { |
| 1256 | .@"struct", | 1274 | .@"struct", |
| 1257 | .@"union", | 1275 | .@"union", |
| 1258 | .@"opaque", | 1276 | .@"opaque", |
| 1277 | .var_args_param, | ||
| 1259 | => unreachable, | 1278 | => unreachable, |
| 1260 | 1279 | ||
| 1261 | .const_slice, | 1280 | .const_slice, |
| ... | @@ -1354,6 +1373,7 @@ pub const Type = extern union { | ... | @@ -1354,6 +1373,7 @@ pub const Type = extern union { |
| 1354 | .@"struct", | 1373 | .@"struct", |
| 1355 | .@"union", | 1374 | .@"union", |
| 1356 | .@"opaque", | 1375 | .@"opaque", |
| 1376 | .var_args_param, | ||
| 1357 | => false, | 1377 | => false, |
| 1358 | 1378 | ||
| 1359 | .const_slice, | 1379 | .const_slice, |
| ... | @@ -1434,6 +1454,7 @@ pub const Type = extern union { | ... | @@ -1434,6 +1454,7 @@ pub const Type = extern union { |
| 1434 | .@"struct", | 1454 | .@"struct", |
| 1435 | .@"union", | 1455 | .@"union", |
| 1436 | .@"opaque", | 1456 | .@"opaque", |
| 1457 | .var_args_param, | ||
| 1437 | => false, | 1458 | => false, |
| 1438 | 1459 | ||
| 1439 | .single_const_pointer, | 1460 | .single_const_pointer, |
| ... | @@ -1523,6 +1544,7 @@ pub const Type = extern union { | ... | @@ -1523,6 +1544,7 @@ pub const Type = extern union { |
| 1523 | .@"struct", | 1544 | .@"struct", |
| 1524 | .@"union", | 1545 | .@"union", |
| 1525 | .@"opaque", | 1546 | .@"opaque", |
| 1547 | .var_args_param, | ||
| 1526 | => false, | 1548 | => false, |
| 1527 | 1549 | ||
| 1528 | .pointer => { | 1550 | .pointer => { |
| ... | @@ -1607,6 +1629,7 @@ pub const Type = extern union { | ... | @@ -1607,6 +1629,7 @@ pub const Type = extern union { |
| 1607 | .@"struct", | 1629 | .@"struct", |
| 1608 | .@"union", | 1630 | .@"union", |
| 1609 | .@"opaque", | 1631 | .@"opaque", |
| 1632 | .var_args_param, | ||
| 1610 | => false, | 1633 | => false, |
| 1611 | 1634 | ||
| 1612 | .pointer => { | 1635 | .pointer => { |
| ... | @@ -1733,6 +1756,7 @@ pub const Type = extern union { | ... | @@ -1733,6 +1756,7 @@ pub const Type = extern union { |
| 1733 | .@"struct" => unreachable, | 1756 | .@"struct" => unreachable, |
| 1734 | .@"union" => unreachable, | 1757 | .@"union" => unreachable, |
| 1735 | .@"opaque" => unreachable, | 1758 | .@"opaque" => unreachable, |
| 1759 | .var_args_param => unreachable, | ||
| 1736 | 1760 | ||
| 1737 | .array => self.castTag(.array).?.data.elem_type, | 1761 | .array => self.castTag(.array).?.data.elem_type, |
| 1738 | .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type, | 1762 | .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type, |
| ... | @@ -1862,6 +1886,7 @@ pub const Type = extern union { | ... | @@ -1862,6 +1886,7 @@ pub const Type = extern union { |
| 1862 | .@"struct", | 1886 | .@"struct", |
| 1863 | .@"union", | 1887 | .@"union", |
| 1864 | .@"opaque", | 1888 | .@"opaque", |
| 1889 | .var_args_param, | ||
| 1865 | => unreachable, | 1890 | => unreachable, |
| 1866 | 1891 | ||
| 1867 | .array => self.castTag(.array).?.data.len, | 1892 | .array => self.castTag(.array).?.data.len, |
| ... | @@ -1936,6 +1961,7 @@ pub const Type = extern union { | ... | @@ -1936,6 +1961,7 @@ pub const Type = extern union { |
| 1936 | .@"struct", | 1961 | .@"struct", |
| 1937 | .@"union", | 1962 | .@"union", |
| 1938 | .@"opaque", | 1963 | .@"opaque", |
| 1964 | .var_args_param, | ||
| 1939 | => unreachable, | 1965 | => unreachable, |
| 1940 | 1966 | ||
| 1941 | .single_const_pointer, | 1967 | .single_const_pointer, |
| ... | @@ -2025,6 +2051,7 @@ pub const Type = extern union { | ... | @@ -2025,6 +2051,7 @@ pub const Type = extern union { |
| 2025 | .@"struct", | 2051 | .@"struct", |
| 2026 | .@"union", | 2052 | .@"union", |
| 2027 | .@"opaque", | 2053 | .@"opaque", |
| 2054 | .var_args_param, | ||
| 2028 | => false, | 2055 | => false, |
| 2029 | 2056 | ||
| 2030 | .int_signed, | 2057 | .int_signed, |
| ... | @@ -2110,6 +2137,7 @@ pub const Type = extern union { | ... | @@ -2110,6 +2137,7 @@ pub const Type = extern union { |
| 2110 | .@"struct", | 2137 | .@"struct", |
| 2111 | .@"union", | 2138 | .@"union", |
| 2112 | .@"opaque", | 2139 | .@"opaque", |
| 2140 | .var_args_param, | ||
| 2113 | => false, | 2141 | => false, |
| 2114 | 2142 | ||
| 2115 | .int_unsigned, | 2143 | .int_unsigned, |
| ... | @@ -2181,6 +2209,7 @@ pub const Type = extern union { | ... | @@ -2181,6 +2209,7 @@ pub const Type = extern union { |
| 2181 | .@"struct", | 2209 | .@"struct", |
| 2182 | .@"union", | 2210 | .@"union", |
| 2183 | .@"opaque", | 2211 | .@"opaque", |
| 2212 | .var_args_param, | ||
| 2184 | => unreachable, | 2213 | => unreachable, |
| 2185 | 2214 | ||
| 2186 | .int_unsigned => .{ | 2215 | .int_unsigned => .{ |
| ... | @@ -2280,6 +2309,7 @@ pub const Type = extern union { | ... | @@ -2280,6 +2309,7 @@ pub const Type = extern union { |
| 2280 | .@"struct", | 2309 | .@"struct", |
| 2281 | .@"union", | 2310 | .@"union", |
| 2282 | .@"opaque", | 2311 | .@"opaque", |
| 2312 | .var_args_param, | ||
| 2283 | => false, | 2313 | => false, |
| 2284 | 2314 | ||
| 2285 | .usize, | 2315 | .usize, |
| ... | @@ -2400,6 +2430,7 @@ pub const Type = extern union { | ... | @@ -2400,6 +2430,7 @@ pub const Type = extern union { |
| 2400 | .@"struct", | 2430 | .@"struct", |
| 2401 | .@"union", | 2431 | .@"union", |
| 2402 | .@"opaque", | 2432 | .@"opaque", |
| 2433 | .var_args_param, | ||
| 2403 | => unreachable, | 2434 | => unreachable, |
| 2404 | }; | 2435 | }; |
| 2405 | } | 2436 | } |
| ... | @@ -2486,6 +2517,7 @@ pub const Type = extern union { | ... | @@ -2486,6 +2517,7 @@ pub const Type = extern union { |
| 2486 | .@"struct", | 2517 | .@"struct", |
| 2487 | .@"union", | 2518 | .@"union", |
| 2488 | .@"opaque", | 2519 | .@"opaque", |
| 2520 | .var_args_param, | ||
| 2489 | => unreachable, | 2521 | => unreachable, |
| 2490 | } | 2522 | } |
| 2491 | } | 2523 | } |
| ... | @@ -2571,6 +2603,7 @@ pub const Type = extern union { | ... | @@ -2571,6 +2603,7 @@ pub const Type = extern union { |
| 2571 | .@"struct", | 2603 | .@"struct", |
| 2572 | .@"union", | 2604 | .@"union", |
| 2573 | .@"opaque", | 2605 | .@"opaque", |
| 2606 | .var_args_param, | ||
| 2574 | => unreachable, | 2607 | => unreachable, |
| 2575 | } | 2608 | } |
| 2576 | } | 2609 | } |
| ... | @@ -2656,6 +2689,7 @@ pub const Type = extern union { | ... | @@ -2656,6 +2689,7 @@ pub const Type = extern union { |
| 2656 | .@"struct", | 2689 | .@"struct", |
| 2657 | .@"union", | 2690 | .@"union", |
| 2658 | .@"opaque", | 2691 | .@"opaque", |
| 2692 | .var_args_param, | ||
| 2659 | => unreachable, | 2693 | => unreachable, |
| 2660 | }; | 2694 | }; |
| 2661 | } | 2695 | } |
| ... | @@ -2738,6 +2772,7 @@ pub const Type = extern union { | ... | @@ -2738,6 +2772,7 @@ pub const Type = extern union { |
| 2738 | .@"struct", | 2772 | .@"struct", |
| 2739 | .@"union", | 2773 | .@"union", |
| 2740 | .@"opaque", | 2774 | .@"opaque", |
| 2775 | .var_args_param, | ||
| 2741 | => unreachable, | 2776 | => unreachable, |
| 2742 | }; | 2777 | }; |
| 2743 | } | 2778 | } |
| ... | @@ -2749,7 +2784,7 @@ pub const Type = extern union { | ... | @@ -2749,7 +2784,7 @@ pub const Type = extern union { |
| 2749 | .fn_void_no_args => false, | 2784 | .fn_void_no_args => false, |
| 2750 | .fn_naked_noreturn_no_args => false, | 2785 | .fn_naked_noreturn_no_args => false, |
| 2751 | .fn_ccc_void_no_args => false, | 2786 | .fn_ccc_void_no_args => false, |
| 2752 | .function => false, | 2787 | .function => self.castTag(.function).?.data.is_var_args, |
| 2753 | 2788 | ||
| 2754 | .f16, | 2789 | .f16, |
| 2755 | .f32, | 2790 | .f32, |
| ... | @@ -2820,6 +2855,7 @@ pub const Type = extern union { | ... | @@ -2820,6 +2855,7 @@ pub const Type = extern union { |
| 2820 | .@"struct", | 2855 | .@"struct", |
| 2821 | .@"union", | 2856 | .@"union", |
| 2822 | .@"opaque", | 2857 | .@"opaque", |
| 2858 | .var_args_param, | ||
| 2823 | => unreachable, | 2859 | => unreachable, |
| 2824 | }; | 2860 | }; |
| 2825 | } | 2861 | } |
| ... | @@ -2902,6 +2938,7 @@ pub const Type = extern union { | ... | @@ -2902,6 +2938,7 @@ pub const Type = extern union { |
| 2902 | .@"struct", | 2938 | .@"struct", |
| 2903 | .@"union", | 2939 | .@"union", |
| 2904 | .@"opaque", | 2940 | .@"opaque", |
| 2941 | .var_args_param, | ||
| 2905 | => false, | 2942 | => false, |
| 2906 | }; | 2943 | }; |
| 2907 | } | 2944 | } |
| ... | @@ -2962,6 +2999,7 @@ pub const Type = extern union { | ... | @@ -2962,6 +2999,7 @@ pub const Type = extern union { |
| 2962 | .error_set, | 2999 | .error_set, |
| 2963 | .error_set_single, | 3000 | .error_set_single, |
| 2964 | .@"opaque", | 3001 | .@"opaque", |
| 3002 | .var_args_param, | ||
| 2965 | => return null, | 3003 | => return null, |
| 2966 | 3004 | ||
| 2967 | .@"enum" => @panic("TODO onePossibleValue enum"), | 3005 | .@"enum" => @panic("TODO onePossibleValue enum"), |
| ... | @@ -3079,6 +3117,7 @@ pub const Type = extern union { | ... | @@ -3079,6 +3117,7 @@ pub const Type = extern union { |
| 3079 | .@"struct", | 3117 | .@"struct", |
| 3080 | .@"union", | 3118 | .@"union", |
| 3081 | .@"opaque", | 3119 | .@"opaque", |
| 3120 | .var_args_param, | ||
| 3082 | => return false, | 3121 | => return false, |
| 3083 | 3122 | ||
| 3084 | .c_const_pointer, | 3123 | .c_const_pointer, |
| ... | @@ -3168,6 +3207,7 @@ pub const Type = extern union { | ... | @@ -3168,6 +3207,7 @@ pub const Type = extern union { |
| 3168 | .pointer, | 3207 | .pointer, |
| 3169 | .inferred_alloc_const, | 3208 | .inferred_alloc_const, |
| 3170 | .inferred_alloc_mut, | 3209 | .inferred_alloc_mut, |
| 3210 | .var_args_param, | ||
| 3171 | => unreachable, | 3211 | => unreachable, |
| 3172 | 3212 | ||
| 3173 | .empty_struct => self.castTag(.empty_struct).?.data, | 3213 | .empty_struct => self.castTag(.empty_struct).?.data, |
| ... | @@ -3285,6 +3325,9 @@ pub const Type = extern union { | ... | @@ -3285,6 +3325,9 @@ pub const Type = extern union { |
| 3285 | anyerror_void_error_union, | 3325 | anyerror_void_error_union, |
| 3286 | @"anyframe", | 3326 | @"anyframe", |
| 3287 | const_slice_u8, | 3327 | const_slice_u8, |
| 3328 | /// This is a special type for variadic parameters of a function call. | ||
| 3329 | /// Casts to it will validate that the type can be passed to a c calling convetion function. | ||
| 3330 | var_args_param, | ||
| 3288 | /// This is a special value that tracks a set of types that have been stored | 3331 | /// This is a special value that tracks a set of types that have been stored |
| 3289 | /// to an inferred allocation. It does not support most of the normal type queries. | 3332 | /// to an inferred allocation. It does not support most of the normal type queries. |
| 3290 | /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc. | 3333 | /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc. |
| ... | @@ -3373,6 +3416,7 @@ pub const Type = extern union { | ... | @@ -3373,6 +3416,7 @@ pub const Type = extern union { |
| 3373 | .const_slice_u8, | 3416 | .const_slice_u8, |
| 3374 | .inferred_alloc_const, | 3417 | .inferred_alloc_const, |
| 3375 | .inferred_alloc_mut, | 3418 | .inferred_alloc_mut, |
| 3419 | .var_args_param, | ||
| 3376 | => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), | 3420 | => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), |
| 3377 | 3421 | ||
| 3378 | .array_u8, | 3422 | .array_u8, |
| ... | @@ -3479,6 +3523,7 @@ pub const Type = extern union { | ... | @@ -3479,6 +3523,7 @@ pub const Type = extern union { |
| 3479 | param_types: []Type, | 3523 | param_types: []Type, |
| 3480 | return_type: Type, | 3524 | return_type: Type, |
| 3481 | cc: std.builtin.CallingConvention, | 3525 | cc: std.builtin.CallingConvention, |
| 3526 | is_var_args: bool, | ||
| 3482 | }, | 3527 | }, |
| 3483 | }; | 3528 | }; |
| 3484 | 3529 |
src/zir.zig+29-2| ... | @@ -61,6 +61,8 @@ pub const Inst = struct { | ... | @@ -61,6 +61,8 @@ pub const Inst = struct { |
| 61 | as, | 61 | as, |
| 62 | /// Inline assembly. | 62 | /// Inline assembly. |
| 63 | @"asm", | 63 | @"asm", |
| 64 | /// Await an async function. | ||
| 65 | @"await", | ||
| 64 | /// Bitwise AND. `&` | 66 | /// Bitwise AND. `&` |
| 65 | bit_and, | 67 | bit_and, |
| 66 | /// TODO delete this instruction, it has no purpose. | 68 | /// TODO delete this instruction, it has no purpose. |
| ... | @@ -176,8 +178,12 @@ pub const Inst = struct { | ... | @@ -176,8 +178,12 @@ pub const Inst = struct { |
| 176 | @"fn", | 178 | @"fn", |
| 177 | /// Returns a function type, assuming unspecified calling convention. | 179 | /// Returns a function type, assuming unspecified calling convention. |
| 178 | fn_type, | 180 | fn_type, |
| 181 | /// Same as `fn_type` but the function is variadic. | ||
| 182 | fn_type_var_args, | ||
| 179 | /// Returns a function type, with a calling convention instruction operand. | 183 | /// Returns a function type, with a calling convention instruction operand. |
| 180 | fn_type_cc, | 184 | fn_type_cc, |
| 185 | /// Same as `fn_type_cc` but the function is variadic. | ||
| 186 | fn_type_cc_var_args, | ||
| 181 | /// @import(operand) | 187 | /// @import(operand) |
| 182 | import, | 188 | import, |
| 183 | /// Integer literal. | 189 | /// Integer literal. |
| ... | @@ -212,6 +218,8 @@ pub const Inst = struct { | ... | @@ -212,6 +218,8 @@ pub const Inst = struct { |
| 212 | mul, | 218 | mul, |
| 213 | /// Twos complement wrapping integer multiplication. | 219 | /// Twos complement wrapping integer multiplication. |
| 214 | mulwrap, | 220 | mulwrap, |
| 221 | /// An await inside a nosuspend scope. | ||
| 222 | nosuspend_await, | ||
| 215 | /// Given a reference to a function and a parameter index, returns the | 223 | /// Given a reference to a function and a parameter index, returns the |
| 216 | /// type of the parameter. TODO what happens when the parameter is `anytype`? | 224 | /// type of the parameter. TODO what happens when the parameter is `anytype`? |
| 217 | param_type, | 225 | param_type, |
| ... | @@ -226,6 +234,8 @@ pub const Inst = struct { | ... | @@ -226,6 +234,8 @@ pub const Inst = struct { |
| 226 | /// the memory location is in the stack frame, local to the scope containing the | 234 | /// the memory location is in the stack frame, local to the scope containing the |
| 227 | /// instruction. | 235 | /// instruction. |
| 228 | ref, | 236 | ref, |
| 237 | /// Resume an async function. | ||
| 238 | @"resume", | ||
| 229 | /// Obtains a pointer to the return value. | 239 | /// Obtains a pointer to the return value. |
| 230 | ret_ptr, | 240 | ret_ptr, |
| 231 | /// Obtains the return type of the in-scope function. | 241 | /// Obtains the return type of the in-scope function. |
| ... | @@ -348,6 +358,11 @@ pub const Inst = struct { | ... | @@ -348,6 +358,11 @@ pub const Inst = struct { |
| 348 | enum_type, | 358 | enum_type, |
| 349 | /// Does nothing; returns a void value. | 359 | /// Does nothing; returns a void value. |
| 350 | void_value, | 360 | void_value, |
| 361 | /// Suspend an async function. | ||
| 362 | @"suspend", | ||
| 363 | /// Suspend an async function. | ||
| 364 | /// Same as .suspend but with a block. | ||
| 365 | suspend_block, | ||
| 351 | /// A switch expression. | 366 | /// A switch expression. |
| 352 | switchbr, | 367 | switchbr, |
| 353 | /// Same as `switchbr` but the target is a pointer to the value being switched on. | 368 | /// Same as `switchbr` but the target is a pointer to the value being switched on. |
| ... | @@ -369,6 +384,7 @@ pub const Inst = struct { | ... | @@ -369,6 +384,7 @@ pub const Inst = struct { |
| 369 | .unreachable_unsafe, | 384 | .unreachable_unsafe, |
| 370 | .unreachable_safe, | 385 | .unreachable_safe, |
| 371 | .void_value, | 386 | .void_value, |
| 387 | .@"suspend", | ||
| 372 | => NoOp, | 388 | => NoOp, |
| 373 | 389 | ||
| 374 | .alloc, | 390 | .alloc, |
| ... | @@ -417,6 +433,9 @@ pub const Inst = struct { | ... | @@ -417,6 +433,9 @@ pub const Inst = struct { |
| 417 | .import, | 433 | .import, |
| 418 | .set_eval_branch_quota, | 434 | .set_eval_branch_quota, |
| 419 | .indexable_ptr_len, | 435 | .indexable_ptr_len, |
| 436 | .@"resume", | ||
| 437 | .@"await", | ||
| 438 | .nosuspend_await, | ||
| 420 | => UnOp, | 439 | => UnOp, |
| 421 | 440 | ||
| 422 | .add, | 441 | .add, |
| ... | @@ -461,6 +480,7 @@ pub const Inst = struct { | ... | @@ -461,6 +480,7 @@ pub const Inst = struct { |
| 461 | .block_flat, | 480 | .block_flat, |
| 462 | .block_comptime, | 481 | .block_comptime, |
| 463 | .block_comptime_flat, | 482 | .block_comptime_flat, |
| 483 | .suspend_block, | ||
| 464 | => Block, | 484 | => Block, |
| 465 | 485 | ||
| 466 | .switchbr, .switchbr_ref => SwitchBr, | 486 | .switchbr, .switchbr_ref => SwitchBr, |
| ... | @@ -486,8 +506,8 @@ pub const Inst = struct { | ... | @@ -486,8 +506,8 @@ pub const Inst = struct { |
| 486 | .@"export" => Export, | 506 | .@"export" => Export, |
| 487 | .param_type => ParamType, | 507 | .param_type => ParamType, |
| 488 | .primitive => Primitive, | 508 | .primitive => Primitive, |
| 489 | .fn_type => FnType, | 509 | .fn_type, .fn_type_var_args => FnType, |
| 490 | .fn_type_cc => FnTypeCc, | 510 | .fn_type_cc, .fn_type_cc_var_args => FnTypeCc, |
| 491 | .elem_ptr, .elem_val => Elem, | 511 | .elem_ptr, .elem_val => Elem, |
| 492 | .condbr => CondBr, | 512 | .condbr => CondBr, |
| 493 | .ptr_type => PtrType, | 513 | .ptr_type => PtrType, |
| ... | @@ -563,7 +583,9 @@ pub const Inst = struct { | ... | @@ -563,7 +583,9 @@ pub const Inst = struct { |
| 563 | .field_val_named, | 583 | .field_val_named, |
| 564 | .@"fn", | 584 | .@"fn", |
| 565 | .fn_type, | 585 | .fn_type, |
| 586 | .fn_type_var_args, | ||
| 566 | .fn_type_cc, | 587 | .fn_type_cc, |
| 588 | .fn_type_cc_var_args, | ||
| 567 | .int, | 589 | .int, |
| 568 | .intcast, | 590 | .intcast, |
| 569 | .int_type, | 591 | .int_type, |
| ... | @@ -633,6 +655,9 @@ pub const Inst = struct { | ... | @@ -633,6 +655,9 @@ pub const Inst = struct { |
| 633 | .struct_type, | 655 | .struct_type, |
| 634 | .void_value, | 656 | .void_value, |
| 635 | .switch_range, | 657 | .switch_range, |
| 658 | .@"resume", | ||
| 659 | .@"await", | ||
| 660 | .nosuspend_await, | ||
| 636 | => false, | 661 | => false, |
| 637 | 662 | ||
| 638 | .@"break", | 663 | .@"break", |
| ... | @@ -649,6 +674,8 @@ pub const Inst = struct { | ... | @@ -649,6 +674,8 @@ pub const Inst = struct { |
| 649 | .container_field, | 674 | .container_field, |
| 650 | .switchbr, | 675 | .switchbr, |
| 651 | .switchbr_ref, | 676 | .switchbr_ref, |
| 677 | .@"suspend", | ||
| 678 | .suspend_block, | ||
| 652 | => true, | 679 | => true, |
| 653 | }; | 680 | }; |
| 654 | } | 681 | } |
src/zir_sema.zig+41-17| ... | @@ -91,8 +91,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! | ... | @@ -91,8 +91,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 91 | .@"fn" => return zirFn(mod, scope, old_inst.castTag(.@"fn").?), | 91 | .@"fn" => return zirFn(mod, scope, old_inst.castTag(.@"fn").?), |
| 92 | .@"export" => return zirExport(mod, scope, old_inst.castTag(.@"export").?), | 92 | .@"export" => return zirExport(mod, scope, old_inst.castTag(.@"export").?), |
| 93 | .primitive => return zirPrimitive(mod, scope, old_inst.castTag(.primitive).?), | 93 | .primitive => return zirPrimitive(mod, scope, old_inst.castTag(.primitive).?), |
| 94 | .fn_type => return zirFnType(mod, scope, old_inst.castTag(.fn_type).?), | 94 | .fn_type => return zirFnType(mod, scope, old_inst.castTag(.fn_type).?, false), |
| 95 | .fn_type_cc => return zirFnTypeCc(mod, scope, old_inst.castTag(.fn_type_cc).?), | 95 | .fn_type_cc => return zirFnTypeCc(mod, scope, old_inst.castTag(.fn_type_cc).?, false), |
| 96 | .fn_type_var_args => return zirFnType(mod, scope, old_inst.castTag(.fn_type_var_args).?, true), | ||
| 97 | .fn_type_cc_var_args => return zirFnTypeCc(mod, scope, old_inst.castTag(.fn_type_cc_var_args).?, true), | ||
| 96 | .intcast => return zirIntcast(mod, scope, old_inst.castTag(.intcast).?), | 98 | .intcast => return zirIntcast(mod, scope, old_inst.castTag(.intcast).?), |
| 97 | .bitcast => return zirBitcast(mod, scope, old_inst.castTag(.bitcast).?), | 99 | .bitcast => return zirBitcast(mod, scope, old_inst.castTag(.bitcast).?), |
| 98 | .floatcast => return zirFloatcast(mod, scope, old_inst.castTag(.floatcast).?), | 100 | .floatcast => return zirFloatcast(mod, scope, old_inst.castTag(.floatcast).?), |
| ... | @@ -160,6 +162,11 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! | ... | @@ -160,6 +162,11 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 160 | .switchbr => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr).?, false), | 162 | .switchbr => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr).?, false), |
| 161 | .switchbr_ref => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr_ref).?, true), | 163 | .switchbr_ref => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr_ref).?, true), |
| 162 | .switch_range => return zirSwitchRange(mod, scope, old_inst.castTag(.switch_range).?), | 164 | .switch_range => return zirSwitchRange(mod, scope, old_inst.castTag(.switch_range).?), |
| 165 | .@"await" => return zirAwait(mod, scope, old_inst.castTag(.@"await").?), | ||
| 166 | .nosuspend_await => return zirAwait(mod, scope, old_inst.castTag(.nosuspend_await).?), | ||
| 167 | .@"resume" => return zirResume(mod, scope, old_inst.castTag(.@"resume").?), | ||
| 168 | .@"suspend" => return zirSuspend(mod, scope, old_inst.castTag(.@"suspend").?), | ||
| 169 | .suspend_block => return zirSuspendBlock(mod, scope, old_inst.castTag(.suspend_block).?), | ||
| 163 | 170 | ||
| 164 | .container_field_named, | 171 | .container_field_named, |
| 165 | .container_field_typed, | 172 | .container_field_typed, |
| ... | @@ -517,9 +524,11 @@ fn zirParamType(mod: *Module, scope: *Scope, inst: *zir.Inst.ParamType) InnerErr | ... | @@ -517,9 +524,11 @@ fn zirParamType(mod: *Module, scope: *Scope, inst: *zir.Inst.ParamType) InnerErr |
| 517 | }, | 524 | }, |
| 518 | }; | 525 | }; |
| 519 | 526 | ||
| 520 | // TODO support C-style var args | ||
| 521 | const param_count = fn_ty.fnParamLen(); | 527 | const param_count = fn_ty.fnParamLen(); |
| 522 | if (arg_index >= param_count) { | 528 | if (arg_index >= param_count) { |
| 529 | if (fn_ty.fnIsVarArgs()) { | ||
| 530 | return mod.constType(scope, inst.base.src, Type.initTag(.var_args_param)); | ||
| 531 | } | ||
| 523 | return mod.fail(scope, inst.base.src, "arg index {d} out of bounds; '{}' has {d} argument(s)", .{ | 532 | return mod.fail(scope, inst.base.src, "arg index {d} out of bounds; '{}' has {d} argument(s)", .{ |
| 524 | arg_index, | 533 | arg_index, |
| 525 | fn_ty, | 534 | fn_ty, |
| ... | @@ -941,6 +950,7 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst { | ... | @@ -941,6 +950,7 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst { |
| 941 | const call_params_len = inst.positionals.args.len; | 950 | const call_params_len = inst.positionals.args.len; |
| 942 | const fn_params_len = func.ty.fnParamLen(); | 951 | const fn_params_len = func.ty.fnParamLen(); |
| 943 | if (func.ty.fnIsVarArgs()) { | 952 | if (func.ty.fnIsVarArgs()) { |
| 953 | assert(cc == .C); | ||
| 944 | if (call_params_len < fn_params_len) { | 954 | if (call_params_len < fn_params_len) { |
| 945 | // TODO add error note: declared here | 955 | // TODO add error note: declared here |
| 946 | return mod.fail( | 956 | return mod.fail( |
| ... | @@ -950,7 +960,6 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst { | ... | @@ -950,7 +960,6 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst { |
| 950 | .{ fn_params_len, call_params_len }, | 960 | .{ fn_params_len, call_params_len }, |
| 951 | ); | 961 | ); |
| 952 | } | 962 | } |
| 953 | return mod.fail(scope, inst.base.src, "TODO implement support for calling var args functions", .{}); | ||
| 954 | } else if (fn_params_len != call_params_len) { | 963 | } else if (fn_params_len != call_params_len) { |
| 955 | // TODO add error note: declared here | 964 | // TODO add error note: declared here |
| 956 | return mod.fail( | 965 | return mod.fail( |
| ... | @@ -969,15 +978,10 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst { | ... | @@ -969,15 +978,10 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst { |
| 969 | } | 978 | } |
| 970 | 979 | ||
| 971 | // TODO handle function calls of generic functions | 980 | // TODO handle function calls of generic functions |
| 972 | 981 | const casted_args = try scope.arena().alloc(*Inst, call_params_len); | |
| 973 | const fn_param_types = try mod.gpa.alloc(Type, fn_params_len); | ||
| 974 | defer mod.gpa.free(fn_param_types); | ||
| 975 | func.ty.fnParamTypes(fn_param_types); | ||
| 976 | |||
| 977 | const casted_args = try scope.arena().alloc(*Inst, fn_params_len); | ||
| 978 | for (inst.positionals.args) |src_arg, i| { | 982 | for (inst.positionals.args) |src_arg, i| { |
| 979 | const uncasted_arg = try resolveInst(mod, scope, src_arg); | 983 | // the args are already casted to the result of a param type instruction. |
| 980 | casted_args[i] = try mod.coerce(scope, fn_param_types[i], uncasted_arg); | 984 | casted_args[i] = try resolveInst(mod, scope, src_arg); |
| 981 | } | 985 | } |
| 982 | 986 | ||
| 983 | const ret_type = func.ty.fnReturnType(); | 987 | const ret_type = func.ty.fnReturnType(); |
| ... | @@ -1080,6 +1084,22 @@ fn zirFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst { | ... | @@ -1080,6 +1084,22 @@ fn zirFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst { |
| 1080 | }); | 1084 | }); |
| 1081 | } | 1085 | } |
| 1082 | 1086 | ||
| 1087 | fn zirAwait(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | ||
| 1088 | return mod.fail(scope, inst.base.src, "TODO implement await", .{}); | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | fn zirResume(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | ||
| 1092 | return mod.fail(scope, inst.base.src, "TODO implement resume", .{}); | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | fn zirSuspend(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { | ||
| 1096 | return mod.fail(scope, inst.base.src, "TODO implement suspend", .{}); | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | fn zirSuspendBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst { | ||
| 1100 | return mod.fail(scope, inst.base.src, "TODO implement suspend", .{}); | ||
| 1101 | } | ||
| 1102 | |||
| 1083 | fn zirIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) InnerError!*Inst { | 1103 | fn zirIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) InnerError!*Inst { |
| 1084 | const tracy = trace(@src()); | 1104 | const tracy = trace(@src()); |
| 1085 | defer tracy.end(); | 1105 | defer tracy.end(); |
| ... | @@ -1482,7 +1502,7 @@ fn zirEnsureErrPayloadVoid(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) | ... | @@ -1482,7 +1502,7 @@ fn zirEnsureErrPayloadVoid(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) |
| 1482 | return mod.constVoid(scope, unwrap.base.src); | 1502 | return mod.constVoid(scope, unwrap.base.src); |
| 1483 | } | 1503 | } |
| 1484 | 1504 | ||
| 1485 | fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst { | 1505 | fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType, var_args: bool) InnerError!*Inst { |
| 1486 | const tracy = trace(@src()); | 1506 | const tracy = trace(@src()); |
| 1487 | defer tracy.end(); | 1507 | defer tracy.end(); |
| 1488 | 1508 | ||
| ... | @@ -1493,10 +1513,11 @@ fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!* | ... | @@ -1493,10 +1513,11 @@ fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!* |
| 1493 | fntype.positionals.param_types, | 1513 | fntype.positionals.param_types, |
| 1494 | fntype.positionals.return_type, | 1514 | fntype.positionals.return_type, |
| 1495 | .Unspecified, | 1515 | .Unspecified, |
| 1516 | var_args, | ||
| 1496 | ); | 1517 | ); |
| 1497 | } | 1518 | } |
| 1498 | 1519 | ||
| 1499 | fn zirFnTypeCc(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnTypeCc) InnerError!*Inst { | 1520 | fn zirFnTypeCc(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnTypeCc, var_args: bool) InnerError!*Inst { |
| 1500 | const tracy = trace(@src()); | 1521 | const tracy = trace(@src()); |
| 1501 | defer tracy.end(); | 1522 | defer tracy.end(); |
| 1502 | 1523 | ||
| ... | @@ -1513,6 +1534,7 @@ fn zirFnTypeCc(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnTypeCc) InnerErr | ... | @@ -1513,6 +1534,7 @@ fn zirFnTypeCc(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnTypeCc) InnerErr |
| 1513 | fntype.positionals.param_types, | 1534 | fntype.positionals.param_types, |
| 1514 | fntype.positionals.return_type, | 1535 | fntype.positionals.return_type, |
| 1515 | cc, | 1536 | cc, |
| 1537 | var_args, | ||
| 1516 | ); | 1538 | ); |
| 1517 | } | 1539 | } |
| 1518 | 1540 | ||
| ... | @@ -1523,11 +1545,12 @@ fn fnTypeCommon( | ... | @@ -1523,11 +1545,12 @@ fn fnTypeCommon( |
| 1523 | zir_param_types: []*zir.Inst, | 1545 | zir_param_types: []*zir.Inst, |
| 1524 | zir_return_type: *zir.Inst, | 1546 | zir_return_type: *zir.Inst, |
| 1525 | cc: std.builtin.CallingConvention, | 1547 | cc: std.builtin.CallingConvention, |
| 1548 | var_args: bool, | ||
| 1526 | ) InnerError!*Inst { | 1549 | ) InnerError!*Inst { |
| 1527 | const return_type = try resolveType(mod, scope, zir_return_type); | 1550 | const return_type = try resolveType(mod, scope, zir_return_type); |
| 1528 | 1551 | ||
| 1529 | // Hot path for some common function types. | 1552 | // Hot path for some common function types. |
| 1530 | if (zir_param_types.len == 0) { | 1553 | if (zir_param_types.len == 0 and !var_args) { |
| 1531 | if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) { | 1554 | if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) { |
| 1532 | return mod.constType(scope, zir_inst.src, Type.initTag(.fn_noreturn_no_args)); | 1555 | return mod.constType(scope, zir_inst.src, Type.initTag(.fn_noreturn_no_args)); |
| 1533 | } | 1556 | } |
| ... | @@ -1560,6 +1583,7 @@ fn fnTypeCommon( | ... | @@ -1560,6 +1583,7 @@ fn fnTypeCommon( |
| 1560 | .param_types = param_types, | 1583 | .param_types = param_types, |
| 1561 | .return_type = return_type, | 1584 | .return_type = return_type, |
| 1562 | .cc = cc, | 1585 | .cc = cc, |
| 1586 | .is_var_args = var_args, | ||
| 1563 | }); | 1587 | }); |
| 1564 | return mod.constType(scope, zir_inst.src, fn_ty); | 1588 | return mod.constType(scope, zir_inst.src, fn_ty); |
| 1565 | } | 1589 | } |
| ... | @@ -2046,7 +2070,7 @@ fn zirBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*In | ... | @@ -2046,7 +2070,7 @@ fn zirBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*In |
| 2046 | rhs.ty.arrayLen(), | 2070 | rhs.ty.arrayLen(), |
| 2047 | }); | 2071 | }); |
| 2048 | } | 2072 | } |
| 2049 | return mod.fail(scope, inst.base.src, "TODO implement support for vectors in analyzeInstBitwise", .{}); | 2073 | return mod.fail(scope, inst.base.src, "TODO implement support for vectors in zirBitwise", .{}); |
| 2050 | } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) { | 2074 | } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) { |
| 2051 | return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{ | 2075 | return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{ |
| 2052 | lhs.ty, | 2076 | lhs.ty, |
| ... | @@ -2127,7 +2151,7 @@ fn zirArithmetic(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError! | ... | @@ -2127,7 +2151,7 @@ fn zirArithmetic(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError! |
| 2127 | rhs.ty.arrayLen(), | 2151 | rhs.ty.arrayLen(), |
| 2128 | }); | 2152 | }); |
| 2129 | } | 2153 | } |
| 2130 | return mod.fail(scope, inst.base.src, "TODO implement support for vectors in analyzeInstBinOp", .{}); | 2154 | return mod.fail(scope, inst.base.src, "TODO implement support for vectors in zirBinOp", .{}); |
| 2131 | } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) { | 2155 | } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) { |
| 2132 | return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{ | 2156 | return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{ |
| 2133 | lhs.ty, | 2157 | lhs.ty, |
test/stage2/cbe.zig+13| ... | @@ -41,6 +41,19 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -41,6 +41,19 @@ pub fn addCases(ctx: *TestContext) !void { |
| 41 | , "yo!" ++ std.cstr.line_sep); | 41 | , "yo!" ++ std.cstr.line_sep); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | { | ||
| 45 | var case = ctx.exeFromCompiledC("var args", .{}); | ||
| 46 | |||
| 47 | case.addCompareOutput( | ||
| 48 | \\extern fn printf(format: [*:0]const u8, ...) c_int; | ||
| 49 | \\ | ||
| 50 | \\export fn main() c_int { | ||
| 51 | \\ _ = printf("Hello, %s!\n", "world"); | ||
| 52 | \\ return 0; | ||
| 53 | \\} | ||
| 54 | , "Hello, world!\n"); | ||
| 55 | } | ||
| 56 | |||
| 44 | { | 57 | { |
| 45 | var case = ctx.exeFromCompiledC("x86_64-linux inline assembly", linux_x64); | 58 | var case = ctx.exeFromCompiledC("x86_64-linux inline assembly", linux_x64); |
| 46 | 59 |