mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
Sema: respect inline call semantics
If an argument is comptime-known but shouldn't be create an alloc to store it in to get a runtime-known value.
This commit is contained in:
parent
be9a4a1f97
commit
4e134f6dcb
33
src/Sema.zig
33
src/Sema.zig
@ -6413,9 +6413,9 @@ fn analyzeInlineCallArg(
|
||||
};
|
||||
}
|
||||
const casted_arg = try sema.coerce(arg_block, param_ty, uncasted_arg, arg_src);
|
||||
try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg);
|
||||
|
||||
if (is_comptime_call) {
|
||||
try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg);
|
||||
const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {
|
||||
if (err == error.AnalysisFail and sema.err != null) {
|
||||
try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty);
|
||||
@ -6440,6 +6440,20 @@ fn analyzeInlineCallArg(
|
||||
.ty = param_ty,
|
||||
.val = arg_val,
|
||||
};
|
||||
} else if ((try sema.resolveMaybeUndefVal(arg_block, arg_src, casted_arg) == null) or
|
||||
try sema.typeRequiresComptime(param_ty) or zir_tags[inst] == .param_comptime)
|
||||
{
|
||||
try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg);
|
||||
} else {
|
||||
// We have a comptime value but we need a runtime value to preserve inlining semantics,
|
||||
const ptr_type = try Type.ptr(sema.arena, sema.mod, .{
|
||||
.pointee_type = param_ty,
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
});
|
||||
const alloc = try arg_block.addTy(.alloc, ptr_type);
|
||||
_ = try arg_block.addBinOp(.store, alloc, casted_arg);
|
||||
const loaded = try arg_block.addTyOp(.load, param_ty, alloc);
|
||||
try sema.inst_map.putNoClobber(sema.gpa, inst, loaded);
|
||||
}
|
||||
|
||||
arg_i.* += 1;
|
||||
@ -6448,9 +6462,10 @@ fn analyzeInlineCallArg(
|
||||
// No coercion needed.
|
||||
const uncasted_arg = uncasted_args[arg_i.*];
|
||||
new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg);
|
||||
try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg);
|
||||
const param_ty = sema.typeOf(uncasted_arg);
|
||||
|
||||
if (is_comptime_call) {
|
||||
try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg);
|
||||
const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {
|
||||
if (err == error.AnalysisFail and sema.err != null) {
|
||||
try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty);
|
||||
@ -6475,6 +6490,20 @@ fn analyzeInlineCallArg(
|
||||
.ty = sema.typeOf(uncasted_arg),
|
||||
.val = arg_val,
|
||||
};
|
||||
} else if ((try sema.resolveMaybeUndefVal(arg_block, arg_src, uncasted_arg)) == null or
|
||||
try sema.typeRequiresComptime(param_ty) or zir_tags[inst] == .param_anytype_comptime)
|
||||
{
|
||||
try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg);
|
||||
} else {
|
||||
// We have a comptime value but we need a runtime value to preserve inlining semantics,
|
||||
const ptr_type = try Type.ptr(sema.arena, sema.mod, .{
|
||||
.pointee_type = param_ty,
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
});
|
||||
const alloc = try arg_block.addTy(.alloc, ptr_type);
|
||||
_ = try arg_block.addBinOp(.store, alloc, uncasted_arg);
|
||||
const loaded = try arg_block.addTyOp(.load, param_ty, alloc);
|
||||
try sema.inst_map.putNoClobber(sema.gpa, inst, loaded);
|
||||
}
|
||||
|
||||
arg_i.* += 1;
|
||||
|
||||
@ -105,6 +105,7 @@ test {
|
||||
_ = @import("behavior/bugs/13068.zig");
|
||||
_ = @import("behavior/bugs/13112.zig");
|
||||
_ = @import("behavior/bugs/13128.zig");
|
||||
_ = @import("behavior/bugs/13164.zig");
|
||||
_ = @import("behavior/byteswap.zig");
|
||||
_ = @import("behavior/byval_arg_var.zig");
|
||||
_ = @import("behavior/call.zig");
|
||||
|
||||
16
test/behavior/bugs/13164.zig
Normal file
16
test/behavior/bugs/13164.zig
Normal file
@ -0,0 +1,16 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
inline fn setLimits(min: ?u32, max: ?u32) !void {
|
||||
if (min != null and max != null) {
|
||||
try std.testing.expect(min.? <= max.?);
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
var x: u32 = 42;
|
||||
try setLimits(x, null);
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
pub fn main() void {
|
||||
var x: usize = 3;
|
||||
const y = add(10, 2, x);
|
||||
if (y - 6 != 0) unreachable;
|
||||
}
|
||||
|
||||
inline fn add(a: usize, b: usize, c: usize) usize {
|
||||
if (a == 10) @compileError("bad");
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
// error
|
||||
// output_mode=Exe
|
||||
//
|
||||
// :8:18: error: bad
|
||||
// :3:18: note: called from here
|
||||
@ -1,13 +0,0 @@
|
||||
pub fn main() void {
|
||||
var x: usize = 3;
|
||||
const y = add(1, 2, x);
|
||||
if (y - 6 != 0) unreachable;
|
||||
}
|
||||
|
||||
inline fn add(a: usize, b: usize, c: usize) usize {
|
||||
if (a == 10) @compileError("bad");
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
// run
|
||||
//
|
||||
Loading…
x
Reference in New Issue
Block a user