mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
stage2: introduce support for noalias
Not implemented yet is enhancements to coerceInMemory to account for noalias parameters. Related to #11498.
This commit is contained in:
parent
602af1b88f
commit
356a865b87
@ -1155,14 +1155,20 @@ fn fnProtoExpr(
|
||||
|
||||
const block_inst = try gz.makeBlockInst(.block_inline, node);
|
||||
|
||||
var noalias_bits: u32 = 0;
|
||||
const is_var_args = is_var_args: {
|
||||
var param_type_i: usize = 0;
|
||||
var it = fn_proto.iterate(tree);
|
||||
while (it.next()) |param| : (param_type_i += 1) {
|
||||
const is_comptime = if (param.comptime_noalias) |token|
|
||||
token_tags[token] == .keyword_comptime
|
||||
else
|
||||
false;
|
||||
const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) {
|
||||
.keyword_noalias => is_comptime: {
|
||||
noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse
|
||||
return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
|
||||
break :is_comptime false;
|
||||
},
|
||||
.keyword_comptime => true,
|
||||
else => false,
|
||||
} else false;
|
||||
|
||||
const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
|
||||
switch (token_tags[token]) {
|
||||
@ -1255,6 +1261,7 @@ fn fnProtoExpr(
|
||||
.is_inferred_error = false,
|
||||
.is_test = false,
|
||||
.is_extern = false,
|
||||
.noalias_bits = noalias_bits,
|
||||
});
|
||||
|
||||
_ = try block_scope.addBreak(.break_inline, block_inst, result);
|
||||
@ -3381,15 +3388,21 @@ fn fnDecl(
|
||||
// align, linksection, and addrspace is passed in the func instruction in this case.
|
||||
wip_members.nextDecl(is_pub, is_export, false, false);
|
||||
|
||||
var noalias_bits: u32 = 0;
|
||||
var params_scope = &fn_gz.base;
|
||||
const is_var_args = is_var_args: {
|
||||
var param_type_i: usize = 0;
|
||||
var it = fn_proto.iterate(tree);
|
||||
while (it.next()) |param| : (param_type_i += 1) {
|
||||
const is_comptime = if (param.comptime_noalias) |token|
|
||||
token_tags[token] == .keyword_comptime
|
||||
else
|
||||
false;
|
||||
const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) {
|
||||
.keyword_noalias => is_comptime: {
|
||||
noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse
|
||||
return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
|
||||
break :is_comptime false;
|
||||
},
|
||||
.keyword_comptime => true,
|
||||
else => false,
|
||||
} else false;
|
||||
|
||||
const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
|
||||
switch (token_tags[token]) {
|
||||
@ -3576,6 +3589,7 @@ fn fnDecl(
|
||||
.is_inferred_error = false,
|
||||
.is_test = false,
|
||||
.is_extern = true,
|
||||
.noalias_bits = noalias_bits,
|
||||
});
|
||||
} else func: {
|
||||
if (is_var_args) {
|
||||
@ -3623,6 +3637,7 @@ fn fnDecl(
|
||||
.is_inferred_error = is_inferred_error,
|
||||
.is_test = false,
|
||||
.is_extern = false,
|
||||
.noalias_bits = noalias_bits,
|
||||
});
|
||||
};
|
||||
|
||||
@ -4057,6 +4072,7 @@ fn testDecl(
|
||||
.is_inferred_error = true,
|
||||
.is_test = true,
|
||||
.is_extern = false,
|
||||
.noalias_bits = 0,
|
||||
});
|
||||
|
||||
_ = try decl_block.addBreak(.break_inline, block_inst, func_inst);
|
||||
@ -10024,6 +10040,7 @@ const GenZir = struct {
|
||||
ret_ref: Zir.Inst.Ref,
|
||||
|
||||
lib_name: u32,
|
||||
noalias_bits: u32,
|
||||
is_var_args: bool,
|
||||
is_inferred_error: bool,
|
||||
is_test: bool,
|
||||
@ -10071,7 +10088,7 @@ const GenZir = struct {
|
||||
if (args.cc_ref != .none or args.lib_name != 0 or
|
||||
args.is_var_args or args.is_test or args.is_extern or
|
||||
args.align_ref != .none or args.section_ref != .none or
|
||||
args.addrspace_ref != .none)
|
||||
args.addrspace_ref != .none or args.noalias_bits != 0)
|
||||
{
|
||||
var align_body: []Zir.Inst.Index = &.{};
|
||||
var addrspace_body: []Zir.Inst.Index = &.{};
|
||||
@ -10093,7 +10110,8 @@ const GenZir = struct {
|
||||
fancyFnExprExtraLen(cc_body, args.cc_ref) +
|
||||
fancyFnExprExtraLen(ret_body, ret_ref) +
|
||||
body.len + src_locs.len +
|
||||
@boolToInt(args.lib_name != 0),
|
||||
@boolToInt(args.lib_name != 0) +
|
||||
@boolToInt(args.noalias_bits != 0),
|
||||
);
|
||||
const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{
|
||||
.param_block = args.param_block,
|
||||
@ -10104,6 +10122,7 @@ const GenZir = struct {
|
||||
.is_test = args.is_test,
|
||||
.is_extern = args.is_extern,
|
||||
.has_lib_name = args.lib_name != 0,
|
||||
.has_any_noalias = args.noalias_bits != 0,
|
||||
|
||||
.has_align_ref = args.align_ref != .none,
|
||||
.has_addrspace_ref = args.addrspace_ref != .none,
|
||||
@ -10159,6 +10178,10 @@ const GenZir = struct {
|
||||
astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref));
|
||||
}
|
||||
|
||||
if (args.noalias_bits != 0) {
|
||||
astgen.extra.appendAssumeCapacity(args.noalias_bits);
|
||||
}
|
||||
|
||||
astgen.extra.appendSliceAssumeCapacity(body);
|
||||
astgen.extra.appendSliceAssumeCapacity(src_locs);
|
||||
|
||||
|
||||
17
src/Sema.zig
17
src/Sema.zig
@ -6565,12 +6565,10 @@ fn zirFunc(
|
||||
has_body,
|
||||
src_locs,
|
||||
null,
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
// TODO this function and its callsites along with funcCommon need to be reworked
|
||||
// to handle when callconv, align, linksection, addrspace depend on comptime values
|
||||
// (thus triggering error.GenericPoison)
|
||||
fn resolveGenericBody(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
@ -6696,6 +6694,7 @@ fn funcCommon(
|
||||
has_body: bool,
|
||||
src_locs: Zir.Inst.Func.SrcLocs,
|
||||
opt_lib_name: ?[]const u8,
|
||||
noalias_bits: u32,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
|
||||
|
||||
@ -6807,6 +6806,7 @@ fn funcCommon(
|
||||
.addrspace_is_generic = address_space == null,
|
||||
.is_var_args = var_args,
|
||||
.is_generic = is_generic,
|
||||
.noalias_bits = noalias_bits,
|
||||
});
|
||||
};
|
||||
|
||||
@ -9626,7 +9626,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
|
||||
const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
|
||||
|
||||
// In `**` rhs has to be comptime-known, but lhs can be runtime-known
|
||||
// In `**` rhs must be comptime-known, but lhs can be runtime-known
|
||||
const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize);
|
||||
|
||||
if (lhs_ty.isTuple()) {
|
||||
@ -11916,7 +11916,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
|
||||
try sema.queueFullTypeResolution(try error_field_ty.copy(sema.arena));
|
||||
|
||||
// If the error set is inferred it has to be resolved at this point
|
||||
// If the error set is inferred it must be resolved at this point
|
||||
try sema.resolveInferredErrorSetTy(block, src, ty);
|
||||
|
||||
// Build our list of Error values
|
||||
@ -16970,6 +16970,12 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
break :blk ty;
|
||||
} else Type.void;
|
||||
|
||||
const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: {
|
||||
const x = sema.code.extra[extra_index];
|
||||
extra_index += 1;
|
||||
break :blk x;
|
||||
} else 0;
|
||||
|
||||
var src_locs: Zir.Inst.Func.SrcLocs = undefined;
|
||||
const has_body = extra.data.body_len != 0;
|
||||
if (has_body) {
|
||||
@ -16996,6 +17002,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
has_body,
|
||||
src_locs,
|
||||
lib_name,
|
||||
noalias_bits,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
14
src/Zir.zig
14
src/Zir.zig
@ -2670,8 +2670,10 @@ pub const Inst = struct {
|
||||
/// 14. ret_ty_body_len: u32
|
||||
/// 15. ret_ty_body: u32 // for each ret_ty_body_len
|
||||
/// }
|
||||
/// 16. body: Index // for each body_len
|
||||
/// 17. src_locs: Func.SrcLocs // if body_len != 0
|
||||
/// 16. noalias_bits: u32 // if has_any_noalias
|
||||
/// - each bit starting with LSB corresponds to parameter indexes
|
||||
/// 17. body: Index // for each body_len
|
||||
/// 18. src_locs: Func.SrcLocs // if body_len != 0
|
||||
pub const FuncFancy = struct {
|
||||
/// Points to the block that contains the param instructions for this function.
|
||||
param_block: Index,
|
||||
@ -2699,7 +2701,8 @@ pub const Inst = struct {
|
||||
has_ret_ty_ref: bool,
|
||||
has_ret_ty_body: bool,
|
||||
has_lib_name: bool,
|
||||
_: u17 = undefined,
|
||||
has_any_noalias: bool,
|
||||
_: u16 = undefined,
|
||||
};
|
||||
};
|
||||
|
||||
@ -3699,6 +3702,8 @@ fn findDeclsInner(
|
||||
extra_index += 1;
|
||||
}
|
||||
|
||||
extra_index += @boolToInt(extra.data.bits.has_any_noalias);
|
||||
|
||||
const body = zir.extra[extra_index..][0..extra.data.body_len];
|
||||
return zir.findDeclsBody(list, body);
|
||||
},
|
||||
@ -3906,6 +3911,9 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
|
||||
ret_ty_ref = @intToEnum(Inst.Ref, zir.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
}
|
||||
|
||||
extra_index += @boolToInt(extra.data.bits.has_any_noalias);
|
||||
|
||||
const body = zir.extra[extra_index..][0..extra.data.body_len];
|
||||
extra_index += body.len;
|
||||
break :blk .{
|
||||
|
||||
@ -725,8 +725,12 @@ pub const Object = struct {
|
||||
try args.append(param);
|
||||
|
||||
if (param_ty.isPtrAtRuntime()) {
|
||||
// TODO noalias attribute
|
||||
const ptr_info = param_ty.ptrInfo().data;
|
||||
if (math.cast(u5, it.zig_index - 1)) |i| {
|
||||
if (@truncate(u1, fn_info.noalias_bits >> i) != 0) {
|
||||
dg.addArgAttr(llvm_func, llvm_arg_i, "noalias");
|
||||
}
|
||||
}
|
||||
if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") {
|
||||
dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull");
|
||||
}
|
||||
|
||||
@ -1961,6 +1961,7 @@ const Writer = struct {
|
||||
body,
|
||||
src,
|
||||
src_locs,
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
@ -2034,6 +2035,12 @@ const Writer = struct {
|
||||
extra_index += 1;
|
||||
}
|
||||
|
||||
const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: {
|
||||
const x = self.code.extra[extra_index];
|
||||
extra_index += 1;
|
||||
break :blk x;
|
||||
} else 0;
|
||||
|
||||
const body = self.code.extra[extra_index..][0..extra.data.body_len];
|
||||
extra_index += body.len;
|
||||
|
||||
@ -2059,6 +2066,7 @@ const Writer = struct {
|
||||
body,
|
||||
src,
|
||||
src_locs,
|
||||
noalias_bits,
|
||||
);
|
||||
}
|
||||
|
||||
@ -2216,6 +2224,7 @@ const Writer = struct {
|
||||
body: []const Zir.Inst.Index,
|
||||
src: LazySrcLoc,
|
||||
src_locs: Zir.Inst.Func.SrcLocs,
|
||||
noalias_bits: u32,
|
||||
) !void {
|
||||
try self.writeOptionalInstRefOrBody(stream, "align=", align_ref, align_body);
|
||||
try self.writeOptionalInstRefOrBody(stream, "addrspace=", addrspace_ref, addrspace_body);
|
||||
@ -2226,6 +2235,10 @@ const Writer = struct {
|
||||
try self.writeFlag(stream, "extern, ", is_extern);
|
||||
try self.writeFlag(stream, "inferror, ", inferred_error_set);
|
||||
|
||||
if (noalias_bits != 0) {
|
||||
try stream.print("noalias=0b{b}, ", .{noalias_bits});
|
||||
}
|
||||
|
||||
try stream.writeAll("body=");
|
||||
try self.writeBracedBody(stream, body);
|
||||
try stream.writeAll(") ");
|
||||
|
||||
38
src/type.zig
38
src/type.zig
@ -646,6 +646,9 @@ pub const Type = extern union {
|
||||
if (a_info.is_generic != b_info.is_generic)
|
||||
return false;
|
||||
|
||||
if (a_info.noalias_bits != b_info.noalias_bits)
|
||||
return false;
|
||||
|
||||
if (!a_info.cc_is_generic and a_info.cc != b_info.cc)
|
||||
return false;
|
||||
|
||||
@ -1047,6 +1050,7 @@ pub const Type = extern union {
|
||||
}
|
||||
std.hash.autoHash(hasher, fn_info.is_var_args);
|
||||
std.hash.autoHash(hasher, fn_info.is_generic);
|
||||
std.hash.autoHash(hasher, fn_info.noalias_bits);
|
||||
|
||||
std.hash.autoHash(hasher, fn_info.param_types.len);
|
||||
for (fn_info.param_types) |param_ty, i| {
|
||||
@ -1424,6 +1428,11 @@ pub const Type = extern union {
|
||||
.is_var_args = payload.is_var_args,
|
||||
.is_generic = payload.is_generic,
|
||||
.comptime_params = comptime_params.ptr,
|
||||
.align_is_generic = payload.align_is_generic,
|
||||
.cc_is_generic = payload.cc_is_generic,
|
||||
.section_is_generic = payload.section_is_generic,
|
||||
.addrspace_is_generic = payload.addrspace_is_generic,
|
||||
.noalias_bits = payload.noalias_bits,
|
||||
});
|
||||
},
|
||||
.pointer => {
|
||||
@ -4738,6 +4747,11 @@ pub const Type = extern union {
|
||||
.alignment = 0,
|
||||
.is_var_args = false,
|
||||
.is_generic = false,
|
||||
.align_is_generic = false,
|
||||
.cc_is_generic = false,
|
||||
.section_is_generic = false,
|
||||
.addrspace_is_generic = false,
|
||||
.noalias_bits = 0,
|
||||
},
|
||||
.fn_void_no_args => .{
|
||||
.param_types = &.{},
|
||||
@ -4747,6 +4761,11 @@ pub const Type = extern union {
|
||||
.alignment = 0,
|
||||
.is_var_args = false,
|
||||
.is_generic = false,
|
||||
.align_is_generic = false,
|
||||
.cc_is_generic = false,
|
||||
.section_is_generic = false,
|
||||
.addrspace_is_generic = false,
|
||||
.noalias_bits = 0,
|
||||
},
|
||||
.fn_naked_noreturn_no_args => .{
|
||||
.param_types = &.{},
|
||||
@ -4756,6 +4775,11 @@ pub const Type = extern union {
|
||||
.alignment = 0,
|
||||
.is_var_args = false,
|
||||
.is_generic = false,
|
||||
.align_is_generic = false,
|
||||
.cc_is_generic = false,
|
||||
.section_is_generic = false,
|
||||
.addrspace_is_generic = false,
|
||||
.noalias_bits = 0,
|
||||
},
|
||||
.fn_ccc_void_no_args => .{
|
||||
.param_types = &.{},
|
||||
@ -4765,6 +4789,11 @@ pub const Type = extern union {
|
||||
.alignment = 0,
|
||||
.is_var_args = false,
|
||||
.is_generic = false,
|
||||
.align_is_generic = false,
|
||||
.cc_is_generic = false,
|
||||
.section_is_generic = false,
|
||||
.addrspace_is_generic = false,
|
||||
.noalias_bits = 0,
|
||||
},
|
||||
.function => ty.castTag(.function).?.data,
|
||||
|
||||
@ -6123,13 +6152,14 @@ pub const Type = extern union {
|
||||
return_type: Type,
|
||||
/// If zero use default target function code alignment.
|
||||
alignment: u32,
|
||||
noalias_bits: u32,
|
||||
cc: std.builtin.CallingConvention,
|
||||
is_var_args: bool,
|
||||
is_generic: bool,
|
||||
align_is_generic: bool = false,
|
||||
cc_is_generic: bool = false,
|
||||
section_is_generic: bool = false,
|
||||
addrspace_is_generic: bool = false,
|
||||
align_is_generic: bool,
|
||||
cc_is_generic: bool,
|
||||
section_is_generic: bool,
|
||||
addrspace_is_generic: bool,
|
||||
|
||||
pub fn paramIsComptime(self: @This(), i: usize) bool {
|
||||
assert(i < self.param_types.len);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user