Skip to content

Commit

Permalink
stage2: introduce support for noalias
Browse files Browse the repository at this point in the history
Not implemented yet is enhancements to coerceInMemory to account for
noalias parameters.

Related to ziglang#11498.
  • Loading branch information
andrewrk authored and wooster0 committed Jul 24, 2022
1 parent 088c4f4 commit d31e4e6
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 23 deletions.
43 changes: 33 additions & 10 deletions src/AstGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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]) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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]) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -3623,6 +3637,7 @@ fn fnDecl(
.is_inferred_error = is_inferred_error,
.is_test = false,
.is_extern = false,
.noalias_bits = noalias_bits,
});
};

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 = &.{};
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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);

Expand Down
17 changes: 12 additions & 5 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 };

Expand Down Expand Up @@ -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,
});
};

Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -16996,6 +17002,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
has_body,
src_locs,
lib_name,
noalias_bits,
);
}

Expand Down
14 changes: 11 additions & 3 deletions src/Zir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
};
};

Expand Down Expand Up @@ -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);
},
Expand Down Expand Up @@ -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 .{
Expand Down
6 changes: 5 additions & 1 deletion src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
13 changes: 13 additions & 0 deletions src/print_zir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1961,6 +1961,7 @@ const Writer = struct {
body,
src,
src_locs,
0,
);
}

Expand Down Expand Up @@ -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;

Expand All @@ -2059,6 +2066,7 @@ const Writer = struct {
body,
src,
src_locs,
noalias_bits,
);
}

Expand Down Expand Up @@ -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);
Expand All @@ -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(") ");
Expand Down
38 changes: 34 additions & 4 deletions src/type.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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| {
Expand Down Expand Up @@ -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 => {
Expand Down Expand Up @@ -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 = &.{},
Expand All @@ -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 = &.{},
Expand All @@ -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 = &.{},
Expand All @@ -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,

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit d31e4e6

Please sign in to comment.