authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-09 23:11:36-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-08-09 23:11:36-04:00
log49a270b2038709a6a0c1f4de604696278769257b
tree61c938338f48de60fb50c00fa2d0cf33833e4209
parent85a3f9b0544c1b90a77ce26f99f9fc26116d756b
parentb757a96d5c885442c38e217006d75c85a28daf09
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12356 from Vexu/stage2-call

stage2: generate call arguments in separate blocks

14 files changed, 270 insertions(+), 133 deletions(-)

lib/std/crypto/25519/ed25519.zig+3-1
...@@ -355,7 +355,9 @@ test "ed25519 batch verification" {...@@ -355,7 +355,9 @@ test "ed25519 batch verification" {
355 try Ed25519.verifyBatch(2, signature_batch);355 try Ed25519.verifyBatch(2, signature_batch);
356356
357 signature_batch[1].sig = sig1;357 signature_batch[1].sig = sig1;
358 try std.testing.expectError(error.SignatureVerificationFailed, Ed25519.verifyBatch(signature_batch.len, signature_batch));358 // TODO https://github.com/ziglang/zig/issues/12240
359 const sig_len = signature_batch.len;
360 try std.testing.expectError(error.SignatureVerificationFailed, Ed25519.verifyBatch(sig_len, signature_batch));
359 }361 }
360}362}
361363
src/AstGen.zig+36-16
...@@ -2500,7 +2500,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2500,7 +2500,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2500 .closure_get,2500 .closure_get,
2501 .array_base_ptr,2501 .array_base_ptr,
2502 .field_base_ptr,2502 .field_base_ptr,
2503 .param_type,
2504 .ret_ptr,2503 .ret_ptr,
2505 .ret_type,2504 .ret_type,
2506 .@"try",2505 .@"try",
...@@ -8228,6 +8227,33 @@ fn callExpr(...@@ -8228,6 +8227,33 @@ fn callExpr(
8228 assert(callee != .none);8227 assert(callee != .none);
8229 assert(node != 0);8228 assert(node != 0);
82308229
8230 const call_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8231 const call_inst = Zir.indexToRef(call_index);
8232 try gz.astgen.instructions.append(astgen.gpa, undefined);
8233 try gz.instructions.append(astgen.gpa, call_index);
8234
8235 const scratch_top = astgen.scratch.items.len;
8236 defer astgen.scratch.items.len = scratch_top;
8237
8238 var scratch_index = scratch_top;
8239 try astgen.scratch.resize(astgen.gpa, scratch_top + call.ast.params.len);
8240
8241 for (call.ast.params) |param_node| {
8242 var arg_block = gz.makeSubBlock(scope);
8243 defer arg_block.unstack();
8244
8245 // `call_inst` is reused to provide the param type.
8246 const arg_ref = try expr(&arg_block, &arg_block.base, .{ .coerced_ty = call_inst }, param_node);
8247 _ = try arg_block.addBreak(.break_inline, call_index, arg_ref);
8248
8249 const body = arg_block.instructionsSlice();
8250 try astgen.scratch.ensureUnusedCapacity(astgen.gpa, countBodyLenAfterFixups(astgen, body));
8251 appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body);
8252
8253 astgen.scratch.items[scratch_index] = @intCast(u32, astgen.scratch.items.len - scratch_top);
8254 scratch_index += 1;
8255 }
8256
8231 const payload_index = try addExtra(astgen, Zir.Inst.Call{8257 const payload_index = try addExtra(astgen, Zir.Inst.Call{
8232 .callee = callee,8258 .callee = callee,
8233 .flags = .{8259 .flags = .{
...@@ -8235,22 +8261,16 @@ fn callExpr(...@@ -8235,22 +8261,16 @@ fn callExpr(
8235 .args_len = @intCast(Zir.Inst.Call.Flags.PackedArgsLen, call.ast.params.len),8261 .args_len = @intCast(Zir.Inst.Call.Flags.PackedArgsLen, call.ast.params.len),
8236 },8262 },
8237 });8263 });
8238 var extra_index = try reserveExtra(astgen, call.ast.params.len);8264 if (call.ast.params.len != 0) {
82398265 try astgen.extra.appendSlice(astgen.gpa, astgen.scratch.items[scratch_top..]);
8240 for (call.ast.params) |param_node, i| {
8241 const param_type = try gz.add(.{
8242 .tag = .param_type,
8243 .data = .{ .param_type = .{
8244 .callee = callee,
8245 .param_index = @intCast(u32, i),
8246 } },
8247 });
8248 const arg_ref = try expr(gz, scope, .{ .coerced_ty = param_type }, param_node);
8249 astgen.extra.items[extra_index] = @enumToInt(arg_ref);
8250 extra_index += 1;
8251 }8266 }
82528267 gz.astgen.instructions.set(call_index, .{
8253 const call_inst = try gz.addPlNodePayloadIndex(.call, node, payload_index);8268 .tag = .call,
8269 .data = .{ .pl_node = .{
8270 .src_node = gz.nodeIndexToRelative(node),
8271 .payload_index = payload_index,
8272 } },
8273 });
8254 return rvalue(gz, rl, call_inst, node); // TODO function call with result location8274 return rvalue(gz, rl, call_inst, node); // TODO function call with result location
8255}8275}
82568276
src/Autodoc.zig+8-3
...@@ -2078,14 +2078,19 @@ fn walkInstruction(...@@ -2078,14 +2078,19 @@ fn walkInstruction(
20782078
2079 const args_len = extra.data.flags.args_len;2079 const args_len = extra.data.flags.args_len;
2080 var args = try self.arena.alloc(DocData.Expr, args_len);2080 var args = try self.arena.alloc(DocData.Expr, args_len);
2081 const arg_refs = file.zir.refSlice(extra.end, args_len);2081 const body = file.zir.extra[extra.end..];
2082 for (arg_refs) |ref, idx| {2082
2083 var i: usize = 0;
2084 while (i < args_len) : (i += 1) {
2085 const arg_end = file.zir.extra[extra.end + i];
2086 const break_index = body[arg_end - 1];
2087 const ref = data[break_index].@"break".operand;
2083 // TODO: consider toggling need_type to true if we ever want2088 // TODO: consider toggling need_type to true if we ever want
2084 // to show discrepancies between the types of provided2089 // to show discrepancies between the types of provided
2085 // arguments and the types declared in the function2090 // arguments and the types declared in the function
2086 // signature for its parameters.2091 // signature for its parameters.
2087 const wr = try self.walkRef(file, parent_scope, ref, false);2092 const wr = try self.walkRef(file, parent_scope, ref, false);
2088 args[idx] = wr.expr;2093 args[i] = wr.expr;
2089 }2094 }
20902095
2091 const cte_slot_index = self.comptime_exprs.items.len;2096 const cte_slot_index = self.comptime_exprs.items.len;
src/Sema.zig+129-55
...@@ -772,7 +772,6 @@ fn analyzeBodyInner(...@@ -772,7 +772,6 @@ fn analyzeBodyInner(
772 .optional_payload_unsafe => try sema.zirOptionalPayload(block, inst, false),772 .optional_payload_unsafe => try sema.zirOptionalPayload(block, inst, false),
773 .optional_payload_unsafe_ptr => try sema.zirOptionalPayloadPtr(block, inst, false),773 .optional_payload_unsafe_ptr => try sema.zirOptionalPayloadPtr(block, inst, false),
774 .optional_type => try sema.zirOptionalType(block, inst),774 .optional_type => try sema.zirOptionalType(block, inst),
775 .param_type => try sema.zirParamType(block, inst),
776 .ptr_type => try sema.zirPtrType(block, inst),775 .ptr_type => try sema.zirPtrType(block, inst),
777 .overflow_arithmetic_ptr => try sema.zirOverflowArithmeticPtr(block, inst),776 .overflow_arithmetic_ptr => try sema.zirOverflowArithmeticPtr(block, inst),
778 .ref => try sema.zirRef(block, inst),777 .ref => try sema.zirRef(block, inst),
...@@ -4441,43 +4440,6 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v...@@ -4441,43 +4440,6 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
4441 return sema.storePtr2(block, src, ptr, src, operand, src, if (is_ret) .ret_ptr else .store);4440 return sema.storePtr2(block, src, ptr, src, operand, src, if (is_ret) .ret_ptr else .store);
4442}4441}
44434442
4444fn zirParamType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
4445 const callee_src = sema.src;
4446
4447 const inst_data = sema.code.instructions.items(.data)[inst].param_type;
4448 const callee = try sema.resolveInst(inst_data.callee);
4449 const callee_ty = sema.typeOf(callee);
4450 var param_index = inst_data.param_index;
4451
4452 const fn_ty = if (callee_ty.tag() == .bound_fn) fn_ty: {
4453 const bound_fn_val = try sema.resolveConstValue(block, .unneeded, callee, undefined);
4454 const bound_fn = bound_fn_val.castTag(.bound_fn).?.data;
4455 const fn_ty = sema.typeOf(bound_fn.func_inst);
4456 param_index += 1;
4457 break :fn_ty fn_ty;
4458 } else callee_ty;
4459
4460 const fn_info = if (fn_ty.zigTypeTag() == .Pointer)
4461 fn_ty.childType().fnInfo()
4462 else
4463 fn_ty.fnInfo();
4464
4465 if (param_index >= fn_info.param_types.len) {
4466 if (fn_info.is_var_args) {
4467 return sema.addType(Type.initTag(.var_args_param));
4468 }
4469 // TODO implement begin_call/end_call Zir instructions and check
4470 // argument count before casting arguments to parameter types.
4471 return sema.fail(block, callee_src, "wrong number of arguments", .{});
4472 }
4473
4474 if (fn_info.param_types[param_index].tag() == .generic_poison) {
4475 return sema.addType(Type.initTag(.var_args_param));
4476 }
4477
4478 return sema.addType(fn_info.param_types[param_index]);
4479}
4480
4481fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {4443fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
4482 const tracy = trace(@src());4444 const tracy = trace(@src());
4483 defer tracy.end();4445 defer tracy.end();
...@@ -5447,6 +5409,19 @@ fn lookupInNamespace(...@@ -5447,6 +5409,19 @@ fn lookupInNamespace(
5447 return null;5409 return null;
5448}5410}
54495411
5412fn funcDeclSrc(sema: *Sema, block: *Block, src: LazySrcLoc, func_inst: Air.Inst.Ref) !?Module.SrcLoc {
5413 const func_val = (try sema.resolveMaybeUndefVal(block, src, func_inst)) orelse return null;
5414 if (func_val.isUndef()) return null;
5415 const owner_decl_index = switch (func_val.tag()) {
5416 .extern_fn => func_val.castTag(.extern_fn).?.data.owner_decl,
5417 .function => func_val.castTag(.function).?.data.owner_decl,
5418 .decl_ref => sema.mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data.owner_decl,
5419 else => return null,
5420 };
5421 const owner_decl = sema.mod.declPtr(owner_decl_index);
5422 return owner_decl.srcLoc();
5423}
5424
5450fn zirCall(5425fn zirCall(
5451 sema: *Sema,5426 sema: *Sema,
5452 block: *Block,5427 block: *Block,
...@@ -5459,13 +5434,14 @@ fn zirCall(...@@ -5459,13 +5434,14 @@ fn zirCall(
5459 const func_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };5434 const func_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };
5460 const call_src = inst_data.src();5435 const call_src = inst_data.src();
5461 const extra = sema.code.extraData(Zir.Inst.Call, inst_data.payload_index);5436 const extra = sema.code.extraData(Zir.Inst.Call, inst_data.payload_index);
5462 const args = sema.code.refSlice(extra.end, extra.data.flags.args_len);5437 const args_len = extra.data.flags.args_len;
54635438
5464 const modifier = @intToEnum(std.builtin.CallOptions.Modifier, extra.data.flags.packed_modifier);5439 const modifier = @intToEnum(std.builtin.CallOptions.Modifier, extra.data.flags.packed_modifier);
5465 const ensure_result_used = extra.data.flags.ensure_result_used;5440 const ensure_result_used = extra.data.flags.ensure_result_used;
54665441
5467 var func = try sema.resolveInst(extra.data.callee);5442 var func = try sema.resolveInst(extra.data.callee);
5468 var resolved_args: []Air.Inst.Ref = undefined;5443 var resolved_args: []Air.Inst.Ref = undefined;
5444 var arg_index: u32 = 0;
54695445
5470 const func_type = sema.typeOf(func);5446 const func_type = sema.typeOf(func);
54715447
...@@ -5476,16 +5452,93 @@ fn zirCall(...@@ -5476,16 +5452,93 @@ fn zirCall(
5476 const bound_func = try sema.resolveValue(block, .unneeded, func, undefined);5452 const bound_func = try sema.resolveValue(block, .unneeded, func, undefined);
5477 const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;5453 const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;
5478 func = bound_data.func_inst;5454 func = bound_data.func_inst;
5479 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args.len + 1);5455 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len + 1);
5480 resolved_args[0] = bound_data.arg0_inst;5456 resolved_args[arg_index] = bound_data.arg0_inst;
5481 for (args) |zir_arg, i| {5457 arg_index += 1;
5482 resolved_args[i + 1] = try sema.resolveInst(zir_arg);
5483 }
5484 } else {5458 } else {
5485 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args.len);5459 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len);
5486 for (args) |zir_arg, i| {5460 }
5487 resolved_args[i] = try sema.resolveInst(zir_arg);5461 const total_args = args_len + @boolToInt(bound_arg_src != null);
5462
5463 const callee_ty = sema.typeOf(func);
5464 const func_ty = func_ty: {
5465 switch (callee_ty.zigTypeTag()) {
5466 .Fn => break :func_ty callee_ty,
5467 .Pointer => {
5468 const ptr_info = callee_ty.ptrInfo().data;
5469 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Fn) {
5470 break :func_ty ptr_info.pointee_type;
5471 }
5472 },
5473 else => {},
5474 }
5475 return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(sema.mod)});
5476 };
5477 const func_ty_info = func_ty.fnInfo();
5478
5479 const fn_params_len = func_ty_info.param_types.len;
5480 check_args: {
5481 if (func_ty_info.is_var_args) {
5482 assert(func_ty_info.cc == .C);
5483 if (total_args >= fn_params_len) break :check_args;
5484 } else if (fn_params_len == total_args) {
5485 break :check_args;
5486 }
5487
5488 const decl_src = try sema.funcDeclSrc(block, func_src, func);
5489 const member_str = if (bound_arg_src != null) "member function " else "";
5490 const variadic_str = if (func_ty_info.is_var_args) "at least " else "";
5491 const msg = msg: {
5492 const msg = try sema.errMsg(
5493 block,
5494 func_src,
5495 "{s}expected {s}{d} argument(s), found {d}",
5496 .{
5497 member_str,
5498 variadic_str,
5499 fn_params_len - @boolToInt(bound_arg_src != null),
5500 args_len,
5501 },
5502 );
5503 errdefer msg.destroy(sema.gpa);
5504
5505 if (decl_src) |some| try sema.mod.errNoteNonLazy(some, msg, "function declared here", .{});
5506 break :msg msg;
5507 };
5508 return sema.failWithOwnedErrorMsg(msg);
5509 }
5510
5511 const args_body = sema.code.extra[extra.end..];
5512
5513 const parent_comptime = block.is_comptime;
5514 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
5515 var extra_index: usize = 0;
5516 var arg_start: u32 = args_len;
5517 while (extra_index < args_len) : ({
5518 extra_index += 1;
5519 arg_index += 1;
5520 }) {
5521 const arg_end = sema.code.extra[extra.end + extra_index];
5522 defer arg_start = arg_end;
5523
5524 const param_ty = if (arg_index >= fn_params_len or
5525 func_ty_info.param_types[arg_index].tag() == .generic_poison)
5526 Type.initTag(.var_args_param)
5527 else
5528 func_ty_info.param_types[arg_index];
5529
5530 const old_comptime = block.is_comptime;
5531 defer block.is_comptime = old_comptime;
5532 // Generate args to comptime params in comptime block.
5533 block.is_comptime = parent_comptime;
5534 if (arg_index < fn_params_len and func_ty_info.comptime_params[arg_index]) {
5535 block.is_comptime = true;
5488 }5536 }
5537
5538 const param_ty_inst = try sema.addType(param_ty);
5539 try sema.inst_map.put(sema.gpa, inst, param_ty_inst);
5540
5541 resolved_args[arg_index] = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
5489 }5542 }
54905543
5491 return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src);5544 return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src);
...@@ -5579,13 +5632,20 @@ fn analyzeCall(...@@ -5579,13 +5632,20 @@ fn analyzeCall(
5579 const func_ty_info = func_ty.fnInfo();5632 const func_ty_info = func_ty.fnInfo();
5580 const cc = func_ty_info.cc;5633 const cc = func_ty_info.cc;
5581 if (cc == .Naked) {5634 if (cc == .Naked) {
5582 // TODO add error note: declared here5635 const decl_src = try sema.funcDeclSrc(block, func_src, func);
5583 return sema.fail(5636 const msg = msg: {
5584 block,5637 const msg = try sema.errMsg(
5585 func_src,5638 block,
5586 "unable to call function with naked calling convention",5639 func_src,
5587 .{},5640 "unable to call function with naked calling convention",
5588 );5641 .{},
5642 );
5643 errdefer msg.destroy(sema.gpa);
5644
5645 if (decl_src) |some| try sema.mod.errNoteNonLazy(some, msg, "function declared here", .{});
5646 break :msg msg;
5647 };
5648 return sema.failWithOwnedErrorMsg(msg);
5589 }5649 }
5590 const fn_params_len = func_ty_info.param_types.len;5650 const fn_params_len = func_ty_info.param_types.len;
5591 if (func_ty_info.is_var_args) {5651 if (func_ty_info.is_var_args) {
...@@ -5964,7 +6024,18 @@ fn analyzeCall(...@@ -5964,7 +6024,18 @@ fn analyzeCall(
5964 else => |e| return e,6024 else => |e| return e,
5965 };6025 };
5966 } else {6026 } else {
5967 args[i] = uncasted_arg;6027 args[i] = sema.coerceVarArgParam(block, uncasted_arg, .unneeded) catch |err| switch (err) {
6028 error.NeededSourceLocation => {
6029 const decl = sema.mod.declPtr(block.src_decl);
6030 _ = try sema.coerceVarArgParam(
6031 block,
6032 uncasted_arg,
6033 Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src),
6034 );
6035 return error.AnalysisFail;
6036 },
6037 else => |e| return e,
6038 };
5968 }6039 }
5969 }6040 }
59706041
...@@ -23534,7 +23605,10 @@ fn coerceVarArgParam(...@@ -23534,7 +23605,10 @@ fn coerceVarArgParam(
23534 inst_src: LazySrcLoc,23605 inst_src: LazySrcLoc,
23535) !Air.Inst.Ref {23606) !Air.Inst.Ref {
23536 const inst_ty = sema.typeOf(inst);23607 const inst_ty = sema.typeOf(inst);
23608 if (block.is_typeof) return inst;
23609
23537 switch (inst_ty.zigTypeTag()) {23610 switch (inst_ty.zigTypeTag()) {
23611 // TODO consider casting to c_int/f64 if they fit
23538 .ComptimeInt, .ComptimeFloat => return sema.fail(block, inst_src, "integer and float literals in var args function must be casted", .{}),23612 .ComptimeInt, .ComptimeFloat => return sema.fail(block, inst_src, "integer and float literals in var args function must be casted", .{}),
23539 else => {},23613 else => {},
23540 }23614 }
src/Zir.zig+3-17
...@@ -490,14 +490,6 @@ pub const Inst = struct {...@@ -490,14 +490,6 @@ pub const Inst = struct {
490 /// Merge two error sets into one, `E1 || E2`.490 /// Merge two error sets into one, `E1 || E2`.
491 /// Uses the `pl_node` field with payload `Bin`.491 /// Uses the `pl_node` field with payload `Bin`.
492 merge_error_sets,492 merge_error_sets,
493 /// Given a reference to a function and a parameter index, returns the
494 /// type of the parameter. The only usage of this instruction is for the
495 /// result location of parameters of function calls. In the case of a function's
496 /// parameter type being `anytype`, it is the type coercion's job to detect this
497 /// scenario and skip the coercion, so that semantic analysis of this instruction
498 /// is not in a position where it must create an invalid type.
499 /// Uses the `param_type` union field.
500 param_type,
501 /// Turns an R-Value into a const L-Value. In other words, it takes a value,493 /// Turns an R-Value into a const L-Value. In other words, it takes a value,
502 /// stores it in a memory location, and returns a const pointer to it. If the value494 /// stores it in a memory location, and returns a const pointer to it. If the value
503 /// is `comptime`, the memory location is global static constant data. Otherwise,495 /// is `comptime`, the memory location is global static constant data. Otherwise,
...@@ -1095,7 +1087,6 @@ pub const Inst = struct {...@@ -1095,7 +1087,6 @@ pub const Inst = struct {
1095 .mul,1087 .mul,
1096 .mulwrap,1088 .mulwrap,
1097 .mul_sat,1089 .mul_sat,
1098 .param_type,
1099 .ref,1090 .ref,
1100 .shl,1091 .shl,
1101 .shl_sat,1092 .shl_sat,
...@@ -1397,7 +1388,6 @@ pub const Inst = struct {...@@ -1397,7 +1388,6 @@ pub const Inst = struct {
1397 .mul,1388 .mul,
1398 .mulwrap,1389 .mulwrap,
1399 .mul_sat,1390 .mul_sat,
1400 .param_type,
1401 .ref,1391 .ref,
1402 .shl,1392 .shl,
1403 .shl_sat,1393 .shl_sat,
...@@ -1569,7 +1559,6 @@ pub const Inst = struct {...@@ -1569,7 +1559,6 @@ pub const Inst = struct {
1569 .mulwrap = .pl_node,1559 .mulwrap = .pl_node,
1570 .mul_sat = .pl_node,1560 .mul_sat = .pl_node,
15711561
1572 .param_type = .param_type,
1573 .param = .pl_tok,1562 .param = .pl_tok,
1574 .param_comptime = .pl_tok,1563 .param_comptime = .pl_tok,
1575 .param_anytype = .str_tok,1564 .param_anytype = .str_tok,
...@@ -2540,10 +2529,6 @@ pub const Inst = struct {...@@ -2540,10 +2529,6 @@ pub const Inst = struct {
2540 /// Points to a `Block`.2529 /// Points to a `Block`.
2541 payload_index: u32,2530 payload_index: u32,
2542 },2531 },
2543 param_type: struct {
2544 callee: Ref,
2545 param_index: u32,
2546 },
2547 @"unreachable": struct {2532 @"unreachable": struct {
2548 /// Offset from Decl AST node index.2533 /// Offset from Decl AST node index.
2549 /// `Tag` determines which kind of AST node this points to.2534 /// `Tag` determines which kind of AST node this points to.
...@@ -2614,7 +2599,6 @@ pub const Inst = struct {...@@ -2614,7 +2599,6 @@ pub const Inst = struct {
2614 ptr_type,2599 ptr_type,
2615 int_type,2600 int_type,
2616 bool_br,2601 bool_br,
2617 param_type,
2618 @"unreachable",2602 @"unreachable",
2619 @"break",2603 @"break",
2620 switch_capture,2604 switch_capture,
...@@ -2794,7 +2778,9 @@ pub const Inst = struct {...@@ -2794,7 +2778,9 @@ pub const Inst = struct {
2794 };2778 };
27952779
2796 /// Stored inside extra, with trailing arguments according to `args_len`.2780 /// Stored inside extra, with trailing arguments according to `args_len`.
2797 /// Each argument is a `Ref`.2781 /// Implicit 0. arg_0_start: u32, // always same as `args_len`
2782 /// 1. arg_end: u32, // for each `args_len`
2783 /// arg_N_start is the same as arg_N-1_end
2798 pub const Call = struct {2784 pub const Call = struct {
2799 // Note: Flags *must* come first so that unusedResultExpr2785 // Note: Flags *must* come first so that unusedResultExpr
2800 // can find it when it goes to modify them.2786 // can find it when it goes to modify them.
src/print_zir.zig+22-15
...@@ -246,7 +246,6 @@ const Writer = struct {...@@ -246,7 +246,6 @@ const Writer = struct {
246246
247 .validate_array_init_ty => try self.writeValidateArrayInitTy(stream, inst),247 .validate_array_init_ty => try self.writeValidateArrayInitTy(stream, inst),
248 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),248 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
249 .param_type => try self.writeParamType(stream, inst),
250 .ptr_type => try self.writePtrType(stream, inst),249 .ptr_type => try self.writePtrType(stream, inst),
251 .int => try self.writeInt(stream, inst),250 .int => try self.writeInt(stream, inst),
252 .int_big => try self.writeIntBig(stream, inst),251 .int_big => try self.writeIntBig(stream, inst),
...@@ -605,16 +604,6 @@ const Writer = struct {...@@ -605,16 +604,6 @@ const Writer = struct {
605 try self.writeSrc(stream, inst_data.src());604 try self.writeSrc(stream, inst_data.src());
606 }605 }
607606
608 fn writeParamType(
609 self: *Writer,
610 stream: anytype,
611 inst: Zir.Inst.Index,
612 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
613 const inst_data = self.code.instructions.items(.data)[inst].param_type;
614 try self.writeInstRef(stream, inst_data.callee);
615 try stream.print(", {d})", .{inst_data.param_index});
616 }
617
618 fn writePtrType(607 fn writePtrType(
619 self: *Writer,608 self: *Writer,
620 stream: anytype,609 stream: anytype,
...@@ -1158,7 +1147,8 @@ const Writer = struct {...@@ -1158,7 +1147,8 @@ const Writer = struct {
1158 fn writeCall(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1147 fn writeCall(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1159 const inst_data = self.code.instructions.items(.data)[inst].pl_node;1148 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1160 const extra = self.code.extraData(Zir.Inst.Call, inst_data.payload_index);1149 const extra = self.code.extraData(Zir.Inst.Call, inst_data.payload_index);
1161 const args = self.code.refSlice(extra.end, extra.data.flags.args_len);1150 const args_len = extra.data.flags.args_len;
1151 const body = self.code.extra[extra.end..];
11621152
1163 if (extra.data.flags.ensure_result_used) {1153 if (extra.data.flags.ensure_result_used) {
1164 try stream.writeAll("nodiscard ");1154 try stream.writeAll("nodiscard ");
...@@ -1166,10 +1156,27 @@ const Writer = struct {...@@ -1166,10 +1156,27 @@ const Writer = struct {
1166 try stream.print(".{s}, ", .{@tagName(@intToEnum(std.builtin.CallOptions.Modifier, extra.data.flags.packed_modifier))});1156 try stream.print(".{s}, ", .{@tagName(@intToEnum(std.builtin.CallOptions.Modifier, extra.data.flags.packed_modifier))});
1167 try self.writeInstRef(stream, extra.data.callee);1157 try self.writeInstRef(stream, extra.data.callee);
1168 try stream.writeAll(", [");1158 try stream.writeAll(", [");
1169 for (args) |arg, i| {1159
1170 if (i != 0) try stream.writeAll(", ");1160 self.indent += 2;
1171 try self.writeInstRef(stream, arg);1161 if (args_len != 0) {
1162 try stream.writeAll("\n");
1163 }
1164 var i: usize = 0;
1165 var arg_start: u32 = args_len;
1166 while (i < args_len) : (i += 1) {
1167 try stream.writeByteNTimes(' ', self.indent);
1168 const arg_end = self.code.extra[extra.end + i];
1169 defer arg_start = arg_end;
1170 const arg_body = body[arg_start..arg_end];
1171 try self.writeBracedBody(stream, arg_body);
1172
1173 try stream.writeAll(",\n");
1172 }1174 }
1175 self.indent -= 2;
1176 if (args_len != 0) {
1177 try stream.writeByteNTimes(' ', self.indent);
1178 }
1179
1173 try stream.writeAll("]) ");1180 try stream.writeAll("]) ");
1174 try self.writeSrc(stream, inst_data.src());1181 try self.writeSrc(stream, inst_data.src());
1175 }1182 }
test/behavior/call.zig+15
...@@ -246,3 +246,18 @@ test "function call with 40 arguments" {...@@ -246,3 +246,18 @@ test "function call with 40 arguments" {
246 };246 };
247 try S.doTheTest(39);247 try S.doTheTest(39);
248}248}
249
250test "arguments to comptime parameters generated in comptime blocks" {
251 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
252
253 const S = struct {
254 fn fortyTwo() i32 {
255 return 42;
256 }
257
258 fn foo(comptime x: i32) void {
259 if (x != 42) @compileError("bad");
260 }
261 };
262 S.foo(S.fortyTwo());
263}
test/cases/compile_errors/calling_function_with_naked_calling_convention.zig created+11
...@@ -0,0 +1,11 @@
1export fn entry() void {
2 foo();
3}
4fn foo() callconv(.Naked) void { }
5
6// error
7// backend=llvm
8// target=native
9//
10// :2:5: error: unable to call function with naked calling convention
11// :4:1: note: function declared here
test/cases/compile_errors/int_literal_passed_as_variadic_arg.zig created+11
...@@ -0,0 +1,11 @@
1extern fn printf([*:0]const u8, ...) c_int;
2
3pub export fn entry() void {
4 _ = printf("%d %d %d %d\n", 1, 2, 3, 4);
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :4:33: error: integer and float literals in var args function must be casted
test/cases/compile_errors/member_function_arg_mismatch.zig created+15
...@@ -0,0 +1,15 @@
1const S = struct {
2 a: u32,
3 fn foo(_: *S, _: u32, _: bool) void {}
4};
5pub export fn entry() void {
6 var s: S = undefined;
7 s.foo(true);
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :7:6: error: member function expected 2 argument(s), found 1
15// :3:5: note: function declared here
test/cases/compile_errors/stage1/obj/calling_function_with_naked_calling_convention.zig deleted-11
...@@ -1,11 +0,0 @@
1export fn entry() void {
2 foo();
3}
4fn foo() callconv(.Naked) void { }
5
6// error
7// backend=stage1
8// target=native
9//
10// tmp.zig:2:5: error: unable to call function with naked calling convention
11// tmp.zig:4:1: note: declared here
test/cases/compile_errors/stage1/obj/wrong_number_of_arguments_for_method_fn_call.zig deleted-14
...@@ -1,14 +0,0 @@
1const Foo = struct {
2 fn method(self: *const Foo, a: i32) void {_ = self; _ = a;}
3};
4fn f(foo: *const Foo) void {
5
6 foo.method(1, 2);
7}
8export fn entry() usize { return @sizeOf(@TypeOf(f)); }
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:6:15: error: expected 2 argument(s), found 3
test/cases/compile_errors/wrong_number_of_arguments.zig+2-1
...@@ -7,4 +7,5 @@ fn c(d: i32, e: i32, f: i32) void { _ = d; _ = e; _ = f; }...@@ -7,4 +7,5 @@ fn c(d: i32, e: i32, f: i32) void { _ = d; _ = e; _ = f; }
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :2:6: error: expected 3 argument(s), found 110// :2:5: error: expected 3 argument(s), found 1
11// :4:1: note: function declared here
test/cases/compile_errors/wrong_number_of_arguments_for_method_fn_call.zig created+15
...@@ -0,0 +1,15 @@
1const Foo = struct {
2 fn method(self: *const Foo, a: i32) void {_ = self; _ = a;}
3};
4fn f(foo: *const Foo) void {
5
6 foo.method(1, 2);
7}
8export fn entry() usize { return @sizeOf(@TypeOf(&f)); }
9
10// error
11// backend=stage2
12// target=native
13//
14// :6:8: error: member function expected 1 argument(s), found 2
15// :2:5: note: function declared here