Skip to content

Commit 356a865

Browse files
committed
stage2: introduce support for noalias
Not implemented yet is enhancements to coerceInMemory to account for noalias parameters. Related to #11498.
1 parent 602af1b commit 356a865

File tree

6 files changed

+108
-23
lines changed

6 files changed

+108
-23
lines changed

src/AstGen.zig

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,14 +1155,20 @@ fn fnProtoExpr(
11551155

11561156
const block_inst = try gz.makeBlockInst(.block_inline, node);
11571157

1158+
var noalias_bits: u32 = 0;
11581159
const is_var_args = is_var_args: {
11591160
var param_type_i: usize = 0;
11601161
var it = fn_proto.iterate(tree);
11611162
while (it.next()) |param| : (param_type_i += 1) {
1162-
const is_comptime = if (param.comptime_noalias) |token|
1163-
token_tags[token] == .keyword_comptime
1164-
else
1165-
false;
1163+
const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) {
1164+
.keyword_noalias => is_comptime: {
1165+
noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse
1166+
return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
1167+
break :is_comptime false;
1168+
},
1169+
.keyword_comptime => true,
1170+
else => false,
1171+
} else false;
11661172

11671173
const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
11681174
switch (token_tags[token]) {
@@ -1255,6 +1261,7 @@ fn fnProtoExpr(
12551261
.is_inferred_error = false,
12561262
.is_test = false,
12571263
.is_extern = false,
1264+
.noalias_bits = noalias_bits,
12581265
});
12591266

12601267
_ = try block_scope.addBreak(.break_inline, block_inst, result);
@@ -3381,15 +3388,21 @@ fn fnDecl(
33813388
// align, linksection, and addrspace is passed in the func instruction in this case.
33823389
wip_members.nextDecl(is_pub, is_export, false, false);
33833390

3391+
var noalias_bits: u32 = 0;
33843392
var params_scope = &fn_gz.base;
33853393
const is_var_args = is_var_args: {
33863394
var param_type_i: usize = 0;
33873395
var it = fn_proto.iterate(tree);
33883396
while (it.next()) |param| : (param_type_i += 1) {
3389-
const is_comptime = if (param.comptime_noalias) |token|
3390-
token_tags[token] == .keyword_comptime
3391-
else
3392-
false;
3397+
const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) {
3398+
.keyword_noalias => is_comptime: {
3399+
noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse
3400+
return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
3401+
break :is_comptime false;
3402+
},
3403+
.keyword_comptime => true,
3404+
else => false,
3405+
} else false;
33933406

33943407
const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
33953408
switch (token_tags[token]) {
@@ -3576,6 +3589,7 @@ fn fnDecl(
35763589
.is_inferred_error = false,
35773590
.is_test = false,
35783591
.is_extern = true,
3592+
.noalias_bits = noalias_bits,
35793593
});
35803594
} else func: {
35813595
if (is_var_args) {
@@ -3623,6 +3637,7 @@ fn fnDecl(
36233637
.is_inferred_error = is_inferred_error,
36243638
.is_test = false,
36253639
.is_extern = false,
3640+
.noalias_bits = noalias_bits,
36263641
});
36273642
};
36283643

@@ -4057,6 +4072,7 @@ fn testDecl(
40574072
.is_inferred_error = true,
40584073
.is_test = true,
40594074
.is_extern = false,
4075+
.noalias_bits = 0,
40604076
});
40614077

40624078
_ = try decl_block.addBreak(.break_inline, block_inst, func_inst);
@@ -10024,6 +10040,7 @@ const GenZir = struct {
1002410040
ret_ref: Zir.Inst.Ref,
1002510041

1002610042
lib_name: u32,
10043+
noalias_bits: u32,
1002710044
is_var_args: bool,
1002810045
is_inferred_error: bool,
1002910046
is_test: bool,
@@ -10071,7 +10088,7 @@ const GenZir = struct {
1007110088
if (args.cc_ref != .none or args.lib_name != 0 or
1007210089
args.is_var_args or args.is_test or args.is_extern or
1007310090
args.align_ref != .none or args.section_ref != .none or
10074-
args.addrspace_ref != .none)
10091+
args.addrspace_ref != .none or args.noalias_bits != 0)
1007510092
{
1007610093
var align_body: []Zir.Inst.Index = &.{};
1007710094
var addrspace_body: []Zir.Inst.Index = &.{};
@@ -10093,7 +10110,8 @@ const GenZir = struct {
1009310110
fancyFnExprExtraLen(cc_body, args.cc_ref) +
1009410111
fancyFnExprExtraLen(ret_body, ret_ref) +
1009510112
body.len + src_locs.len +
10096-
@boolToInt(args.lib_name != 0),
10113+
@boolToInt(args.lib_name != 0) +
10114+
@boolToInt(args.noalias_bits != 0),
1009710115
);
1009810116
const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{
1009910117
.param_block = args.param_block,
@@ -10104,6 +10122,7 @@ const GenZir = struct {
1010410122
.is_test = args.is_test,
1010510123
.is_extern = args.is_extern,
1010610124
.has_lib_name = args.lib_name != 0,
10125+
.has_any_noalias = args.noalias_bits != 0,
1010710126

1010810127
.has_align_ref = args.align_ref != .none,
1010910128
.has_addrspace_ref = args.addrspace_ref != .none,
@@ -10159,6 +10178,10 @@ const GenZir = struct {
1015910178
astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref));
1016010179
}
1016110180

10181+
if (args.noalias_bits != 0) {
10182+
astgen.extra.appendAssumeCapacity(args.noalias_bits);
10183+
}
10184+
1016210185
astgen.extra.appendSliceAssumeCapacity(body);
1016310186
astgen.extra.appendSliceAssumeCapacity(src_locs);
1016410187

src/Sema.zig

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6565,12 +6565,10 @@ fn zirFunc(
65656565
has_body,
65666566
src_locs,
65676567
null,
6568+
0,
65686569
);
65696570
}
65706571

6571-
// TODO this function and its callsites along with funcCommon need to be reworked
6572-
// to handle when callconv, align, linksection, addrspace depend on comptime values
6573-
// (thus triggering error.GenericPoison)
65746572
fn resolveGenericBody(
65756573
sema: *Sema,
65766574
block: *Block,
@@ -6696,6 +6694,7 @@ fn funcCommon(
66966694
has_body: bool,
66976695
src_locs: Zir.Inst.Func.SrcLocs,
66986696
opt_lib_name: ?[]const u8,
6697+
noalias_bits: u32,
66996698
) CompileError!Air.Inst.Ref {
67006699
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
67016700

@@ -6807,6 +6806,7 @@ fn funcCommon(
68076806
.addrspace_is_generic = address_space == null,
68086807
.is_var_args = var_args,
68096808
.is_generic = is_generic,
6809+
.noalias_bits = noalias_bits,
68106810
});
68116811
};
68126812

@@ -9626,7 +9626,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
96269626
const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
96279627
const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
96289628

9629-
// In `**` rhs has to be comptime-known, but lhs can be runtime-known
9629+
// In `**` rhs must be comptime-known, but lhs can be runtime-known
96309630
const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize);
96319631

96329632
if (lhs_ty.isTuple()) {
@@ -11916,7 +11916,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1191611916

1191711917
try sema.queueFullTypeResolution(try error_field_ty.copy(sema.arena));
1191811918

11919-
// If the error set is inferred it has to be resolved at this point
11919+
// If the error set is inferred it must be resolved at this point
1192011920
try sema.resolveInferredErrorSetTy(block, src, ty);
1192111921

1192211922
// Build our list of Error values
@@ -16970,6 +16970,12 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1697016970
break :blk ty;
1697116971
} else Type.void;
1697216972

16973+
const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: {
16974+
const x = sema.code.extra[extra_index];
16975+
extra_index += 1;
16976+
break :blk x;
16977+
} else 0;
16978+
1697316979
var src_locs: Zir.Inst.Func.SrcLocs = undefined;
1697416980
const has_body = extra.data.body_len != 0;
1697516981
if (has_body) {
@@ -16996,6 +17002,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1699617002
has_body,
1699717003
src_locs,
1699817004
lib_name,
17005+
noalias_bits,
1699917006
);
1700017007
}
1700117008

src/Zir.zig

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2670,8 +2670,10 @@ pub const Inst = struct {
26702670
/// 14. ret_ty_body_len: u32
26712671
/// 15. ret_ty_body: u32 // for each ret_ty_body_len
26722672
/// }
2673-
/// 16. body: Index // for each body_len
2674-
/// 17. src_locs: Func.SrcLocs // if body_len != 0
2673+
/// 16. noalias_bits: u32 // if has_any_noalias
2674+
/// - each bit starting with LSB corresponds to parameter indexes
2675+
/// 17. body: Index // for each body_len
2676+
/// 18. src_locs: Func.SrcLocs // if body_len != 0
26752677
pub const FuncFancy = struct {
26762678
/// Points to the block that contains the param instructions for this function.
26772679
param_block: Index,
@@ -2699,7 +2701,8 @@ pub const Inst = struct {
26992701
has_ret_ty_ref: bool,
27002702
has_ret_ty_body: bool,
27012703
has_lib_name: bool,
2702-
_: u17 = undefined,
2704+
has_any_noalias: bool,
2705+
_: u16 = undefined,
27032706
};
27042707
};
27052708

@@ -3699,6 +3702,8 @@ fn findDeclsInner(
36993702
extra_index += 1;
37003703
}
37013704

3705+
extra_index += @boolToInt(extra.data.bits.has_any_noalias);
3706+
37023707
const body = zir.extra[extra_index..][0..extra.data.body_len];
37033708
return zir.findDeclsBody(list, body);
37043709
},
@@ -3906,6 +3911,9 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
39063911
ret_ty_ref = @intToEnum(Inst.Ref, zir.extra[extra_index]);
39073912
extra_index += 1;
39083913
}
3914+
3915+
extra_index += @boolToInt(extra.data.bits.has_any_noalias);
3916+
39093917
const body = zir.extra[extra_index..][0..extra.data.body_len];
39103918
extra_index += body.len;
39113919
break :blk .{

src/codegen/llvm.zig

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,8 +725,12 @@ pub const Object = struct {
725725
try args.append(param);
726726

727727
if (param_ty.isPtrAtRuntime()) {
728-
// TODO noalias attribute
729728
const ptr_info = param_ty.ptrInfo().data;
729+
if (math.cast(u5, it.zig_index - 1)) |i| {
730+
if (@truncate(u1, fn_info.noalias_bits >> i) != 0) {
731+
dg.addArgAttr(llvm_func, llvm_arg_i, "noalias");
732+
}
733+
}
730734
if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") {
731735
dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull");
732736
}

src/print_zir.zig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1961,6 +1961,7 @@ const Writer = struct {
19611961
body,
19621962
src,
19631963
src_locs,
1964+
0,
19641965
);
19651966
}
19661967

@@ -2034,6 +2035,12 @@ const Writer = struct {
20342035
extra_index += 1;
20352036
}
20362037

2038+
const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: {
2039+
const x = self.code.extra[extra_index];
2040+
extra_index += 1;
2041+
break :blk x;
2042+
} else 0;
2043+
20372044
const body = self.code.extra[extra_index..][0..extra.data.body_len];
20382045
extra_index += body.len;
20392046

@@ -2059,6 +2066,7 @@ const Writer = struct {
20592066
body,
20602067
src,
20612068
src_locs,
2069+
noalias_bits,
20622070
);
20632071
}
20642072

@@ -2216,6 +2224,7 @@ const Writer = struct {
22162224
body: []const Zir.Inst.Index,
22172225
src: LazySrcLoc,
22182226
src_locs: Zir.Inst.Func.SrcLocs,
2227+
noalias_bits: u32,
22192228
) !void {
22202229
try self.writeOptionalInstRefOrBody(stream, "align=", align_ref, align_body);
22212230
try self.writeOptionalInstRefOrBody(stream, "addrspace=", addrspace_ref, addrspace_body);
@@ -2226,6 +2235,10 @@ const Writer = struct {
22262235
try self.writeFlag(stream, "extern, ", is_extern);
22272236
try self.writeFlag(stream, "inferror, ", inferred_error_set);
22282237

2238+
if (noalias_bits != 0) {
2239+
try stream.print("noalias=0b{b}, ", .{noalias_bits});
2240+
}
2241+
22292242
try stream.writeAll("body=");
22302243
try self.writeBracedBody(stream, body);
22312244
try stream.writeAll(") ");

src/type.zig

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,9 @@ pub const Type = extern union {
646646
if (a_info.is_generic != b_info.is_generic)
647647
return false;
648648

649+
if (a_info.noalias_bits != b_info.noalias_bits)
650+
return false;
651+
649652
if (!a_info.cc_is_generic and a_info.cc != b_info.cc)
650653
return false;
651654

@@ -1047,6 +1050,7 @@ pub const Type = extern union {
10471050
}
10481051
std.hash.autoHash(hasher, fn_info.is_var_args);
10491052
std.hash.autoHash(hasher, fn_info.is_generic);
1053+
std.hash.autoHash(hasher, fn_info.noalias_bits);
10501054

10511055
std.hash.autoHash(hasher, fn_info.param_types.len);
10521056
for (fn_info.param_types) |param_ty, i| {
@@ -1424,6 +1428,11 @@ pub const Type = extern union {
14241428
.is_var_args = payload.is_var_args,
14251429
.is_generic = payload.is_generic,
14261430
.comptime_params = comptime_params.ptr,
1431+
.align_is_generic = payload.align_is_generic,
1432+
.cc_is_generic = payload.cc_is_generic,
1433+
.section_is_generic = payload.section_is_generic,
1434+
.addrspace_is_generic = payload.addrspace_is_generic,
1435+
.noalias_bits = payload.noalias_bits,
14271436
});
14281437
},
14291438
.pointer => {
@@ -4738,6 +4747,11 @@ pub const Type = extern union {
47384747
.alignment = 0,
47394748
.is_var_args = false,
47404749
.is_generic = false,
4750+
.align_is_generic = false,
4751+
.cc_is_generic = false,
4752+
.section_is_generic = false,
4753+
.addrspace_is_generic = false,
4754+
.noalias_bits = 0,
47414755
},
47424756
.fn_void_no_args => .{
47434757
.param_types = &.{},
@@ -4747,6 +4761,11 @@ pub const Type = extern union {
47474761
.alignment = 0,
47484762
.is_var_args = false,
47494763
.is_generic = false,
4764+
.align_is_generic = false,
4765+
.cc_is_generic = false,
4766+
.section_is_generic = false,
4767+
.addrspace_is_generic = false,
4768+
.noalias_bits = 0,
47504769
},
47514770
.fn_naked_noreturn_no_args => .{
47524771
.param_types = &.{},
@@ -4756,6 +4775,11 @@ pub const Type = extern union {
47564775
.alignment = 0,
47574776
.is_var_args = false,
47584777
.is_generic = false,
4778+
.align_is_generic = false,
4779+
.cc_is_generic = false,
4780+
.section_is_generic = false,
4781+
.addrspace_is_generic = false,
4782+
.noalias_bits = 0,
47594783
},
47604784
.fn_ccc_void_no_args => .{
47614785
.param_types = &.{},
@@ -4765,6 +4789,11 @@ pub const Type = extern union {
47654789
.alignment = 0,
47664790
.is_var_args = false,
47674791
.is_generic = false,
4792+
.align_is_generic = false,
4793+
.cc_is_generic = false,
4794+
.section_is_generic = false,
4795+
.addrspace_is_generic = false,
4796+
.noalias_bits = 0,
47684797
},
47694798
.function => ty.castTag(.function).?.data,
47704799

@@ -6123,13 +6152,14 @@ pub const Type = extern union {
61236152
return_type: Type,
61246153
/// If zero use default target function code alignment.
61256154
alignment: u32,
6155+
noalias_bits: u32,
61266156
cc: std.builtin.CallingConvention,
61276157
is_var_args: bool,
61286158
is_generic: bool,
6129-
align_is_generic: bool = false,
6130-
cc_is_generic: bool = false,
6131-
section_is_generic: bool = false,
6132-
addrspace_is_generic: bool = false,
6159+
align_is_generic: bool,
6160+
cc_is_generic: bool,
6161+
section_is_generic: bool,
6162+
addrspace_is_generic: bool,
61336163

61346164
pub fn paramIsComptime(self: @This(), i: usize) bool {
61356165
assert(i < self.param_types.len);

0 commit comments

Comments
 (0)