Skip to content

Commit bc04cb8

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

File tree

8 files changed

+73
-14
lines changed

8 files changed

+73
-14
lines changed

lib/std/zig/AstGen.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2907,6 +2907,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
29072907
.extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) {
29082908
.breakpoint,
29092909
.disable_instrumentation,
2910+
.disable_intrinsics,
29102911
.set_float_mode,
29112912
.branch_hint,
29122913
=> break :b true,
@@ -9447,6 +9448,7 @@ fn builtinCall(
94479448
.frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node),
94489449
.breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node),
94499450
.disable_instrumentation => return rvalue(gz, ri, try gz.addNodeExtended(.disable_instrumentation, node), node),
9451+
.disable_intrinsics => return rvalue(gz, ri, try gz.addNodeExtended(.disable_intrinsics, node), node),
94509452

94519453
.type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info),
94529454
.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
@@ -1575,7 +1575,11 @@ pub const Inst = struct {
15751575
=> false,
15761576

15771577
.extended => switch (data.extended.opcode) {
1578-
.branch_hint, .breakpoint, .disable_instrumentation => true,
1578+
.branch_hint,
1579+
.breakpoint,
1580+
.disable_instrumentation,
1581+
.disable_intrinsics,
1582+
=> true,
15791583
else => false,
15801584
},
15811585
};
@@ -1996,6 +2000,8 @@ pub const Inst = struct {
19962000
breakpoint,
19972001
/// Implement builtin `@disableInstrumentation`. `operand` is `src_node: i32`.
19982002
disable_instrumentation,
2003+
/// Implement builtin `@disableIntrinsics`. `operand` is `src_node: i32`.
2004+
disable_intrinsics,
19992005
/// Implements the `@select` builtin.
20002006
/// `operand` is payload index to `Select`.
20012007
select,
@@ -4042,6 +4048,7 @@ fn findDeclsInner(
40424048
.await_nosuspend,
40434049
.breakpoint,
40444050
.disable_instrumentation,
4051+
.disable_intrinsics,
40454052
.select,
40464053
.int_from_error,
40474054
.error_from_int,

src/InternPool.zig

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5562,8 +5562,9 @@ pub const FuncAnalysis = packed struct(u32) {
55625562
/// True if this function has an inferred error set.
55635563
inferred_error_set: bool,
55645564
disable_instrumentation: bool,
5565+
disable_intrinsics: bool,
55655566

5566-
_: u23 = 0,
5567+
_: u22 = 0,
55675568

55685569
pub const State = enum(u2) {
55695570
/// The runtime function has never been referenced.
@@ -8597,6 +8598,7 @@ pub fn getFuncDecl(
85978598
.calls_or_awaits_errorable_fn = false,
85988599
.inferred_error_set = false,
85998600
.disable_instrumentation = false,
8601+
.disable_intrinsics = false,
86008602
},
86018603
.owner_nav = key.owner_nav,
86028604
.ty = key.ty,
@@ -8700,6 +8702,7 @@ pub fn getFuncDeclIes(
87008702
.calls_or_awaits_errorable_fn = false,
87018703
.inferred_error_set = true,
87028704
.disable_instrumentation = false,
8705+
.disable_intrinsics = false,
87038706
},
87048707
.owner_nav = key.owner_nav,
87058708
.ty = func_ty,
@@ -8891,6 +8894,7 @@ pub fn getFuncInstance(
88918894
.calls_or_awaits_errorable_fn = false,
88928895
.inferred_error_set = false,
88938896
.disable_instrumentation = false,
8897+
.disable_intrinsics = false,
88948898
},
88958899
// This is populated after we create the Nav below. It is not read
88968900
// by equality or hashing functions.
@@ -8990,6 +8994,7 @@ pub fn getFuncInstanceIes(
89908994
.calls_or_awaits_errorable_fn = false,
89918995
.inferred_error_set = true,
89928996
.disable_instrumentation = false,
8997+
.disable_intrinsics = false,
89938998
},
89948999
// This is populated after we create the Nav below. It is not read
89959000
// by equality or hashing functions.
@@ -11780,6 +11785,18 @@ pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void {
1178011785
@atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
1178111786
}
1178211787

11788+
pub fn funcSetDisableIntrinsics(ip: *InternPool, func: Index) void {
11789+
const unwrapped_func = func.unwrap(ip);
11790+
const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
11791+
extra_mutex.lock();
11792+
defer extra_mutex.unlock();
11793+
11794+
const analysis_ptr = ip.funcAnalysisPtr(func);
11795+
var analysis = analysis_ptr.*;
11796+
analysis.disable_intrinsics = true;
11797+
@atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
11798+
}
11799+
1178311800
pub fn funcZirBodyInst(ip: *const InternPool, func: Index) TrackedInst.Index {
1178411801
const unwrapped_func = func.unwrap(ip);
1178511802
const item = unwrapped_func.getItem(ip);

src/Sema.zig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,6 +1341,11 @@ fn analyzeBodyInner(
13411341
i += 1;
13421342
continue;
13431343
},
1344+
.disable_intrinsics => {
1345+
try sema.zirDisableIntrinsics();
1346+
i += 1;
1347+
continue;
1348+
},
13441349
.restore_err_ret_index => {
13451350
try sema.zirRestoreErrRetIndex(block, extended);
13461351
i += 1;
@@ -6551,6 +6556,18 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
65516556
sema.allow_memoize = false;
65526557
}
65536558

6559+
fn zirDisableIntrinsics(sema: *Sema) CompileError!void {
6560+
const pt = sema.pt;
6561+
const zcu = pt.zcu;
6562+
const ip = &zcu.intern_pool;
6563+
const func = switch (sema.owner.unwrap()) {
6564+
.func => |func| func,
6565+
.cau => return, // does nothing outside a function
6566+
};
6567+
ip.funcSetDisableIntrinsics(func);
6568+
sema.allow_memoize = false;
6569+
}
6570+
65546571
fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
65556572
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
65566573
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
@@ -1552,6 +1552,19 @@ pub const Object = struct {
15521552
try attributes.addFnAttr(.nosanitize_coverage, &o.builder);
15531553
}
15541554

1555+
const disable_intrinsics = func_analysis.disable_intrinsics or owner_mod.no_builtin;
1556+
if (disable_intrinsics) {
1557+
// The intent here is for compiler-rt and libc functions to not generate
1558+
// infinite recursion. For example, if we are compiling the memcpy function,
1559+
// and llvm detects that the body is equivalent to memcpy, it may replace the
1560+
// body of memcpy with a call to memcpy, which would then cause a stack
1561+
// overflow instead of performing memcpy.
1562+
try attributes.addFnAttr(.{ .string = .{
1563+
.kind = try o.builder.string("no-builtins"),
1564+
.value = .empty,
1565+
} }, &o.builder);
1566+
}
1567+
15551568
// TODO: disable this if safety is off for the function scope
15561569
const ssp_buf_size = owner_mod.stack_protector;
15571570
if (ssp_buf_size != 0) {
@@ -1856,6 +1869,7 @@ pub const Object = struct {
18561869
.prev_dbg_line = 0,
18571870
.prev_dbg_column = 0,
18581871
.err_ret_trace = err_ret_trace,
1872+
.disable_intrinsics = disable_intrinsics,
18591873
};
18601874
defer fg.deinit();
18611875
deinit_wip = false;
@@ -3243,17 +3257,6 @@ pub const Object = struct {
32433257
if (owner_mod.unwind_tables) {
32443258
try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
32453259
}
3246-
if (owner_mod.no_builtin) {
3247-
// The intent here is for compiler-rt and libc functions to not generate
3248-
// infinite recursion. For example, if we are compiling the memcpy function,
3249-
// and llvm detects that the body is equivalent to memcpy, it may replace the
3250-
// body of memcpy with a call to memcpy, which would then cause a stack
3251-
// overflow instead of performing memcpy.
3252-
try attributes.addFnAttr(.{ .string = .{
3253-
.kind = try o.builder.string("no-builtins"),
3254-
.value = .empty,
3255-
} }, &o.builder);
3256-
}
32573260
if (owner_mod.optimize_mode == .ReleaseSmall) {
32583261
try attributes.addFnAttr(.minsize, &o.builder);
32593262
try attributes.addFnAttr(.optsize, &o.builder);
@@ -5042,6 +5045,8 @@ pub const FuncGen = struct {
50425045

50435046
sync_scope: Builder.SyncScope,
50445047

5048+
disable_intrinsics: bool,
5049+
50455050
const Fuzz = struct {
50465051
counters_variable: Builder.Variable.Index,
50475052
pcs: std.ArrayListUnmanaged(Builder.Constant),
@@ -5580,7 +5585,7 @@ pub const FuncGen = struct {
55805585
var attributes: Builder.FunctionAttributes.Wip = .{};
55815586
defer attributes.deinit(&o.builder);
55825587

5583-
if (self.ng.ownerModule().no_builtin) {
5588+
if (self.disable_intrinsics) {
55845589
try attributes.addFnAttr(.nobuiltin, &o.builder);
55855590
}
55865591

src/print_zir.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ const Writer = struct {
529529
.frame_address,
530530
.breakpoint,
531531
.disable_instrumentation,
532+
.disable_intrinsics,
532533
.c_va_start,
533534
.in_comptime,
534535
.value_placeholder,

0 commit comments

Comments
 (0)