authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-06 13:35:48-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-03-06 13:35:48-08:00
log34cb5934ddd7c79fb96ffed87768764247740260
treed4ca1d9e3c6a335caf311de1383e45758f221438
parent9f722f43ac449caa0e09c1b7bb1bad0581ef323d
parent8c6e7fb2c7488faab0c41a4ea241f0110237ce91
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7910 from Vexu/stage2-async

Stage2: astgen async stuff, implement var args functions

8 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 }
415423
...@@ -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 }
441453
...@@ -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 }
466481
...@@ -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 }
477494
...@@ -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 };
511560
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 needing789 /// 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,
743794
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};
777838
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 };
11371199
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 the1305 // TODO instead of enum literal type, this needs to be the
1239 // std.builtin.CallingConvention enum. We need to implement importing other files1306 // 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 };
12581338
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 }
13191404
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);
13221411
...@@ -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}
32963385
3297pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) InnerError!*Inst {3386pub 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}
34493541
3542pub 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
3450pub fn storePtr(self: *Module, scope: *Scope, src: usize, ptr: *Inst, uncasted_value: *Inst) !*Inst {3551pub 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),
628628
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", .{}),
634637
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", .{}),
654657
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}
666666
...@@ -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 }
36343644
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 location3654 // TODO function call with result location
3641 return rvalue(mod, scope, rl, result);3655 return rvalue(mod, scope, rl, result);
3642}3656}
36433657
3658fn 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
3708fn 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
3719fn 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
3741fn 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
3644pub const simple_types = std.ComptimeStringMap(Value.Tag, .{3749pub 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 }
233238
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 }
102104
...@@ -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,
401407
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)),
539547
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 {
844858
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 }
849864
...@@ -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,
9981015
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,
11831201
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,
12601279
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,
13581378
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,
14381459
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,
15271549
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,
16111634
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,
17361760
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,
18661891
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,
19401966
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,
20292056
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,
21142142
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,
21852214
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,
22842314
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,
27532788
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,
29663004
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,
30833122
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,
31723212
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 stored3331 /// 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"),
33773421
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 };
34843529
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 the223 /// 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 the234 /// 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,
373389
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,
421440
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,
465485
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,
637662
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).?),
163170
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 };
519526
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 here955 // 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 here964 // 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 }
970979
971 // TODO handle function calls of generic functions980 // TODO handle function calls of generic functions
972981 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 }
982986
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}
10821086
1087fn zirAwait(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1088 return mod.fail(scope, inst.base.src, "TODO implement await", .{});
1089}
1090
1091fn zirResume(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1092 return mod.fail(scope, inst.base.src, "TODO implement resume", .{});
1093}
1094
1095fn zirSuspend(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
1096 return mod.fail(scope, inst.base.src, "TODO implement suspend", .{});
1097}
1098
1099fn zirSuspendBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {
1100 return mod.fail(scope, inst.base.src, "TODO implement suspend", .{});
1101}
1102
1083fn zirIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) InnerError!*Inst {1103fn 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}
14841504
1485fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {1505fn 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();
14881508
...@@ -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}
14981519
1499fn zirFnTypeCc(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnTypeCc) InnerError!*Inst {1520fn 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();
15021523
...@@ -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}
15181540
...@@ -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);
15281551
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 }
4343
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);
4659