Skip to content

Commit ffd741c

Browse files
committed
compiler: Implement @disableIntrinsics() builtin function.
Closes #21833. Closes #22110.
1 parent d916954 commit ffd741c

File tree

8 files changed

+87
-15
lines changed

8 files changed

+87
-15
lines changed

lib/std/zig/AstGen.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2952,6 +2952,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
29522952
.extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) {
29532953
.breakpoint,
29542954
.disable_instrumentation,
2955+
.disable_intrinsics,
29552956
.set_float_mode,
29562957
.branch_hint,
29572958
=> break :b true,
@@ -9557,6 +9558,7 @@ fn builtinCall(
95579558
.frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node),
95589559
.breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node),
95599560
.disable_instrumentation => return rvalue(gz, ri, try gz.addNodeExtended(.disable_instrumentation, node), node),
9561+
.disable_intrinsics => return rvalue(gz, ri, try gz.addNodeExtended(.disable_intrinsics, node), node),
95609562

95619563
.type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info),
95629564
.size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of),

lib/std/zig/AstRlAnnotate.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
882882
.frame,
883883
.breakpoint,
884884
.disable_instrumentation,
885+
.disable_intrinsics,
885886
.in_comptime,
886887
.panic,
887888
.trap,

lib/std/zig/BuiltinFn.zig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub const Tag = enum {
1515
branch_hint,
1616
breakpoint,
1717
disable_instrumentation,
18+
disable_intrinsics,
1819
mul_add,
1920
byte_swap,
2021
bit_reverse,
@@ -262,6 +263,14 @@ pub const list = list: {
262263
.illegal_outside_function = true,
263264
},
264265
},
266+
.{
267+
"@disableIntrinsics",
268+
.{
269+
.tag = .disable_intrinsics,
270+
.param_count = 0,
271+
.illegal_outside_function = true,
272+
},
273+
},
265274
.{
266275
"@mulAdd",
267276
.{

lib/std/zig/Zir.zig

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1593,7 +1593,11 @@ pub const Inst = struct {
15931593
=> false,
15941594

15951595
.extended => switch (data.extended.opcode) {
1596-
.branch_hint, .breakpoint, .disable_instrumentation => true,
1596+
.branch_hint,
1597+
.breakpoint,
1598+
.disable_instrumentation,
1599+
.disable_intrinsics,
1600+
=> true,
15971601
else => false,
15981602
},
15991603
};
@@ -2011,6 +2015,8 @@ pub const Inst = struct {
20112015
breakpoint,
20122016
/// Implement builtin `@disableInstrumentation`. `operand` is `src_node: i32`.
20132017
disable_instrumentation,
2018+
/// Implement builtin `@disableIntrinsics`. `operand` is `src_node: i32`.
2019+
disable_intrinsics,
20142020
/// Implements the `@select` builtin.
20152021
/// `operand` is payload index to `Select`.
20162022
select,
@@ -4310,6 +4316,7 @@ fn findTrackableInner(
43104316
.await_nosuspend,
43114317
.breakpoint,
43124318
.disable_instrumentation,
4319+
.disable_intrinsics,
43134320
.select,
43144321
.int_from_error,
43154322
.error_from_int,

src/InternPool.zig

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5968,8 +5968,22 @@ pub const FuncAnalysis = packed struct(u32) {
59685968
/// True if this function has an inferred error set.
59695969
inferred_error_set: bool,
59705970
disable_instrumentation: bool,
5971-
5972-
_: u24 = 0,
5971+
disable_intrinsics: bool,
5972+
5973+
_: u23 = 0,
5974+
5975+
pub const State = enum(u2) {
5976+
/// The runtime function has never been referenced.
5977+
/// As such, it has never been analyzed, nor is it queued for analysis.
5978+
unreferenced,
5979+
/// The runtime function has been referenced, but has not yet been analyzed.
5980+
/// Its semantic analysis is queued.
5981+
queued,
5982+
/// The runtime function has been (or is currently being) semantically analyzed.
5983+
/// To know if analysis succeeded, consult `zcu.[transitive_]failed_analysis`.
5984+
/// To know if analysis is up-to-date, consult `zcu.[potentially_]outdated`.
5985+
analyzed,
5986+
};
59735987
};
59745988

59755989
pub const Bytes = struct {
@@ -8999,6 +9013,7 @@ pub fn getFuncDecl(
89999013
.has_error_trace = false,
90009014
.inferred_error_set = false,
90019015
.disable_instrumentation = false,
9016+
.disable_intrinsics = false,
90029017
},
90039018
.owner_nav = key.owner_nav,
90049019
.ty = key.ty,
@@ -9108,6 +9123,7 @@ pub fn getFuncDeclIes(
91089123
.has_error_trace = false,
91099124
.inferred_error_set = true,
91109125
.disable_instrumentation = false,
9126+
.disable_intrinsics = false,
91119127
},
91129128
.owner_nav = key.owner_nav,
91139129
.ty = func_ty,
@@ -9304,6 +9320,7 @@ pub fn getFuncInstance(
93049320
.has_error_trace = false,
93059321
.inferred_error_set = false,
93069322
.disable_instrumentation = false,
9323+
.disable_intrinsics = false,
93079324
},
93089325
// This is populated after we create the Nav below. It is not read
93099326
// by equality or hashing functions.
@@ -9402,6 +9419,7 @@ pub fn getFuncInstanceIes(
94029419
.has_error_trace = false,
94039420
.inferred_error_set = true,
94049421
.disable_instrumentation = false,
9422+
.disable_intrinsics = false,
94059423
},
94069424
// This is populated after we create the Nav below. It is not read
94079425
// by equality or hashing functions.
@@ -12187,6 +12205,18 @@ pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void {
1218712205
@atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
1218812206
}
1218912207

12208+
pub fn funcSetDisableIntrinsics(ip: *InternPool, func: Index) void {
12209+
const unwrapped_func = func.unwrap(ip);
12210+
const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
12211+
extra_mutex.lock();
12212+
defer extra_mutex.unlock();
12213+
12214+
const analysis_ptr = ip.funcAnalysisPtr(func);
12215+
var analysis = analysis_ptr.*;
12216+
analysis.disable_intrinsics = true;
12217+
@atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
12218+
}
12219+
1219012220
pub fn funcZirBodyInst(ip: *const InternPool, func: Index) TrackedInst.Index {
1219112221
const unwrapped_func = func.unwrap(ip);
1219212222
const item = unwrapped_func.getItem(ip);

src/Sema.zig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,11 @@ fn analyzeBodyInner(
13991399
i += 1;
14001400
continue;
14011401
},
1402+
.disable_intrinsics => {
1403+
try sema.zirDisableIntrinsics();
1404+
i += 1;
1405+
continue;
1406+
},
14021407
.restore_err_ret_index => {
14031408
try sema.zirRestoreErrRetIndex(block, extended);
14041409
i += 1;
@@ -6627,6 +6632,18 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
66276632
sema.allow_memoize = false;
66286633
}
66296634

6635+
fn zirDisableIntrinsics(sema: *Sema) CompileError!void {
6636+
const pt = sema.pt;
6637+
const zcu = pt.zcu;
6638+
const ip = &zcu.intern_pool;
6639+
const func = switch (sema.owner.unwrap()) {
6640+
.func => |func| func,
6641+
.cau => return, // does nothing outside a function
6642+
};
6643+
ip.funcSetDisableIntrinsics(func);
6644+
sema.allow_memoize = false;
6645+
}
6646+
66306647
fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
66316648
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
66326649
const src = block.builtinCallArgSrc(extra.node, 0);

src/codegen/llvm.zig

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,19 @@ pub const Object = struct {
14481448
try attributes.addFnAttr(.nosanitize_coverage, &o.builder);
14491449
}
14501450

1451+
const disable_intrinsics = func_analysis.disable_intrinsics or owner_mod.no_builtin;
1452+
if (disable_intrinsics) {
1453+
// The intent here is for compiler-rt and libc functions to not generate
1454+
// infinite recursion. For example, if we are compiling the memcpy function,
1455+
// and llvm detects that the body is equivalent to memcpy, it may replace the
1456+
// body of memcpy with a call to memcpy, which would then cause a stack
1457+
// overflow instead of performing memcpy.
1458+
try attributes.addFnAttr(.{ .string = .{
1459+
.kind = try o.builder.string("no-builtins"),
1460+
.value = .empty,
1461+
} }, &o.builder);
1462+
}
1463+
14511464
// TODO: disable this if safety is off for the function scope
14521465
const ssp_buf_size = owner_mod.stack_protector;
14531466
if (ssp_buf_size != 0) {
@@ -1751,6 +1764,7 @@ pub const Object = struct {
17511764
.prev_dbg_line = 0,
17521765
.prev_dbg_column = 0,
17531766
.err_ret_trace = err_ret_trace,
1767+
.disable_intrinsics = disable_intrinsics,
17541768
};
17551769
defer fg.deinit();
17561770
deinit_wip = false;
@@ -3130,17 +3144,6 @@ pub const Object = struct {
31303144
&o.builder,
31313145
);
31323146
}
3133-
if (owner_mod.no_builtin) {
3134-
// The intent here is for compiler-rt and libc functions to not generate
3135-
// infinite recursion. For example, if we are compiling the memcpy function,
3136-
// and llvm detects that the body is equivalent to memcpy, it may replace the
3137-
// body of memcpy with a call to memcpy, which would then cause a stack
3138-
// overflow instead of performing memcpy.
3139-
try attributes.addFnAttr(.{ .string = .{
3140-
.kind = try o.builder.string("no-builtins"),
3141-
.value = .empty,
3142-
} }, &o.builder);
3143-
}
31443147
if (owner_mod.optimize_mode == .ReleaseSmall) {
31453148
try attributes.addFnAttr(.minsize, &o.builder);
31463149
try attributes.addFnAttr(.optsize, &o.builder);
@@ -4919,6 +4922,8 @@ pub const FuncGen = struct {
49194922

49204923
sync_scope: Builder.SyncScope,
49214924

4925+
disable_intrinsics: bool,
4926+
49224927
const Fuzz = struct {
49234928
counters_variable: Builder.Variable.Index,
49244929
pcs: std.ArrayListUnmanaged(Builder.Constant),
@@ -5457,7 +5462,7 @@ pub const FuncGen = struct {
54575462
var attributes: Builder.FunctionAttributes.Wip = .{};
54585463
defer attributes.deinit(&o.builder);
54595464

5460-
if (self.ng.ownerModule().no_builtin) {
5465+
if (self.disable_intrinsics) {
54615466
try attributes.addFnAttr(.nobuiltin, &o.builder);
54625467
}
54635468

src/print_zir.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ const Writer = struct {
531531
.frame_address,
532532
.breakpoint,
533533
.disable_instrumentation,
534+
.disable_intrinsics,
534535
.c_va_start,
535536
.in_comptime,
536537
.value_placeholder,

0 commit comments

Comments
 (0)