authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-21 23:50:50-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-22 13:07:02-07:00
log25198810c88d474c63ff537e3647f12e7df6297c
treef92e3b6dcf75aa653df9786fb6c17360291a8e4c
parent7930efc60becd7624471419b8fd49800512d4e10

add new builtin: `@disableInstrumentation`

This is needed to ensure that start code does not try to access thread local storage before it has set up thread local storage.

8 files changed, 72 insertions(+), 15 deletions(-)

lib/std/zig/AstGen.zig+8-6
...@@ -2817,6 +2817,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2817,6 +2817,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
28172817
2818 .extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) {2818 .extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) {
2819 .breakpoint,2819 .breakpoint,
2820 .disable_instrumentation,
2820 .fence,2821 .fence,
2821 .set_float_mode,2822 .set_float_mode,
2822 .set_align_stack,2823 .set_align_stack,
...@@ -9305,12 +9306,13 @@ fn builtinCall(...@@ -9305,12 +9306,13 @@ fn builtinCall(
9305 },9306 },
93069307
9307 // zig fmt: off9308 // zig fmt: off
9308 .This => return rvalue(gz, ri, try gz.addNodeExtended(.this, node), node),9309 .This => return rvalue(gz, ri, try gz.addNodeExtended(.this, node), node),
9309 .return_address => return rvalue(gz, ri, try gz.addNodeExtended(.ret_addr, node), node),9310 .return_address => return rvalue(gz, ri, try gz.addNodeExtended(.ret_addr, node), node),
9310 .error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node),9311 .error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node),
9311 .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node),9312 .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node),
9312 .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node),9313 .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node),
9313 .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node),9314 .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node),
9315 .disable_instrumentation => return rvalue(gz, ri, try gz.addNodeExtended(.disable_instrumentation, node), node),
93149316
9315 .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info),9317 .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info),
9316 .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of),9318 .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of),
lib/std/zig/AstRlAnnotate.zig+1
...@@ -877,6 +877,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -877,6 +877,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
877 .error_return_trace,877 .error_return_trace,
878 .frame,878 .frame,
879 .breakpoint,879 .breakpoint,
880 .disable_instrumentation,
880 .in_comptime,881 .in_comptime,
881 .panic,882 .panic,
882 .trap,883 .trap,
lib/std/zig/BuiltinFn.zig+9
...@@ -15,6 +15,7 @@ pub const Tag = enum {...@@ -15,6 +15,7 @@ pub const Tag = enum {
15 int_from_bool,15 int_from_bool,
16 bit_size_of,16 bit_size_of,
17 breakpoint,17 breakpoint,
18 disable_instrumentation,
18 mul_add,19 mul_add,
19 byte_swap,20 byte_swap,
20 bit_reverse,21 bit_reverse,
...@@ -263,6 +264,14 @@ pub const list = list: {...@@ -263,6 +264,14 @@ pub const list = list: {
263 .illegal_outside_function = true,264 .illegal_outside_function = true,
264 },265 },
265 },266 },
267 .{
268 "@disableInstrumentation",
269 .{
270 .tag = .disable_instrumentation,
271 .param_count = 0,
272 .illegal_outside_function = true,
273 },
274 },
266 .{275 .{
267 "@mulAdd",276 "@mulAdd",
268 .{277 .{
lib/std/zig/Zir.zig+3-1
...@@ -1553,7 +1553,7 @@ pub const Inst = struct {...@@ -1553,7 +1553,7 @@ pub const Inst = struct {
1553 => false,1553 => false,
15541554
1555 .extended => switch (data.extended.opcode) {1555 .extended => switch (data.extended.opcode) {
1556 .fence, .set_cold, .breakpoint => true,1556 .fence, .set_cold, .breakpoint, .disable_instrumentation => true,
1557 else => false,1557 else => false,
1558 },1558 },
1559 };1559 };
...@@ -1973,6 +1973,8 @@ pub const Inst = struct {...@@ -1973,6 +1973,8 @@ pub const Inst = struct {
1973 /// Implements `@breakpoint`.1973 /// Implements `@breakpoint`.
1974 /// `operand` is `src_node: i32`.1974 /// `operand` is `src_node: i32`.
1975 breakpoint,1975 breakpoint,
1976 /// Implement builtin `@disableInstrumentation`. `operand` is `src_node: i32`.
1977 disable_instrumentation,
1976 /// Implements the `@select` builtin.1978 /// Implements the `@select` builtin.
1977 /// `operand` is payload index to `Select`.1979 /// `operand` is payload index to `Select`.
1978 select,1980 select,
src/InternPool.zig+18-2
...@@ -5184,11 +5184,11 @@ pub const FuncAnalysis = packed struct(u32) {...@@ -5184,11 +5184,11 @@ pub const FuncAnalysis = packed struct(u32) {
5184 is_noinline: bool,5184 is_noinline: bool,
5185 calls_or_awaits_errorable_fn: bool,5185 calls_or_awaits_errorable_fn: bool,
5186 stack_alignment: Alignment,5186 stack_alignment: Alignment,
5187
5188 /// True if this function has an inferred error set.5187 /// True if this function has an inferred error set.
5189 inferred_error_set: bool,5188 inferred_error_set: bool,
5189 disable_instrumentation: bool,
51905190
5191 _: u14 = 0,5191 _: u13 = 0,
51925192
5193 pub const State = enum(u8) {5193 pub const State = enum(u8) {
5194 /// This function has not yet undergone analysis, because we have not5194 /// This function has not yet undergone analysis, because we have not
...@@ -8111,6 +8111,7 @@ pub fn getFuncDecl(...@@ -8111,6 +8111,7 @@ pub fn getFuncDecl(
8111 .calls_or_awaits_errorable_fn = false,8111 .calls_or_awaits_errorable_fn = false,
8112 .stack_alignment = .none,8112 .stack_alignment = .none,
8113 .inferred_error_set = false,8113 .inferred_error_set = false,
8114 .disable_instrumentation = false,
8114 },8115 },
8115 .owner_decl = key.owner_decl,8116 .owner_decl = key.owner_decl,
8116 .ty = key.ty,8117 .ty = key.ty,
...@@ -8214,6 +8215,7 @@ pub fn getFuncDeclIes(...@@ -8214,6 +8215,7 @@ pub fn getFuncDeclIes(
8214 .calls_or_awaits_errorable_fn = false,8215 .calls_or_awaits_errorable_fn = false,
8215 .stack_alignment = .none,8216 .stack_alignment = .none,
8216 .inferred_error_set = true,8217 .inferred_error_set = true,
8218 .disable_instrumentation = false,
8217 },8219 },
8218 .owner_decl = key.owner_decl,8220 .owner_decl = key.owner_decl,
8219 .ty = func_ty,8221 .ty = func_ty,
...@@ -8405,6 +8407,7 @@ pub fn getFuncInstance(...@@ -8405,6 +8407,7 @@ pub fn getFuncInstance(
8405 .calls_or_awaits_errorable_fn = false,8407 .calls_or_awaits_errorable_fn = false,
8406 .stack_alignment = .none,8408 .stack_alignment = .none,
8407 .inferred_error_set = false,8409 .inferred_error_set = false,
8410 .disable_instrumentation = false,
8408 },8411 },
8409 // This is populated after we create the Decl below. It is not read8412 // This is populated after we create the Decl below. It is not read
8410 // by equality or hashing functions.8413 // by equality or hashing functions.
...@@ -8504,6 +8507,7 @@ pub fn getFuncInstanceIes(...@@ -8504,6 +8507,7 @@ pub fn getFuncInstanceIes(
8504 .calls_or_awaits_errorable_fn = false,8507 .calls_or_awaits_errorable_fn = false,
8505 .stack_alignment = .none,8508 .stack_alignment = .none,
8506 .inferred_error_set = true,8509 .inferred_error_set = true,
8510 .disable_instrumentation = false,
8507 },8511 },
8508 // This is populated after we create the Decl below. It is not read8512 // This is populated after we create the Decl below. It is not read
8509 // by equality or hashing functions.8513 // by equality or hashing functions.
...@@ -11225,6 +11229,18 @@ pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {...@@ -11225,6 +11229,18 @@ pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {
11225 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);11229 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
11226}11230}
1122711231
11232pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void {
11233 const unwrapped_func = func.unwrap(ip);
11234 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
11235 extra_mutex.lock();
11236 defer extra_mutex.unlock();
11237
11238 const analysis_ptr = ip.funcAnalysisPtr(func);
11239 var analysis = analysis_ptr.*;
11240 analysis.disable_instrumentation = true;
11241 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
11242}
11243
11228pub fn funcSetCold(ip: *InternPool, func: Index, is_cold: bool) void {11244pub fn funcSetCold(ip: *InternPool, func: Index, is_cold: bool) void {
11229 const unwrapped_func = func.unwrap(ip);11245 const unwrapped_func = func.unwrap(ip);
11230 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;11246 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
src/Sema.zig+13
...@@ -1316,6 +1316,11 @@ fn analyzeBodyInner(...@@ -1316,6 +1316,11 @@ fn analyzeBodyInner(
1316 i += 1;1316 i += 1;
1317 continue;1317 continue;
1318 },1318 },
1319 .disable_instrumentation => {
1320 try sema.zirDisableInstrumentation();
1321 i += 1;
1322 continue;
1323 },
1319 .restore_err_ret_index => {1324 .restore_err_ret_index => {
1320 try sema.zirRestoreErrRetIndex(block, extended);1325 try sema.zirRestoreErrRetIndex(block, extended);
1321 i += 1;1326 i += 1;
...@@ -6576,6 +6581,14 @@ fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)...@@ -6576,6 +6581,14 @@ fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)
6576 ip.funcSetCold(sema.func_index, is_cold);6581 ip.funcSetCold(sema.func_index, is_cold);
6577}6582}
65786583
6584fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
6585 const pt = sema.pt;
6586 const mod = pt.zcu;
6587 const ip = &mod.intern_pool;
6588 if (sema.func_index == .none) return; // does nothing outside a function
6589 ip.funcSetDisableInstrumentation(sema.func_index);
6590}
6591
6579fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {6592fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
6580 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;6593 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
6581 const src = block.builtinCallArgSrc(extra.node, 0);6594 const src = block.builtinCallArgSrc(extra.node, 0);
src/codegen/llvm.zig+19-6
...@@ -1383,6 +1383,25 @@ pub const Object = struct {...@@ -1383,6 +1383,25 @@ pub const Object = struct {
1383 _ = try attributes.removeFnAttr(.cold);1383 _ = try attributes.removeFnAttr(.cold);
1384 }1384 }
13851385
1386 if (owner_mod.sanitize_thread and !func_analysis.disable_instrumentation) {
1387 try attributes.addFnAttr(.sanitize_thread, &o.builder);
1388 } else {
1389 _ = try attributes.removeFnAttr(.sanitize_thread);
1390 }
1391 if (owner_mod.fuzz and !func_analysis.disable_instrumentation) {
1392 try attributes.addFnAttr(.optforfuzzing, &o.builder);
1393 if (comp.config.any_fuzz) {
1394 _ = try attributes.removeFnAttr(.skipprofile);
1395 _ = try attributes.removeFnAttr(.nosanitize_coverage);
1396 }
1397 } else {
1398 _ = try attributes.removeFnAttr(.optforfuzzing);
1399 if (comp.config.any_fuzz) {
1400 try attributes.addFnAttr(.skipprofile, &o.builder);
1401 try attributes.addFnAttr(.nosanitize_coverage, &o.builder);
1402 }
1403 }
1404
1386 // TODO: disable this if safety is off for the function scope1405 // TODO: disable this if safety is off for the function scope
1387 const ssp_buf_size = owner_mod.stack_protector;1406 const ssp_buf_size = owner_mod.stack_protector;
1388 if (ssp_buf_size != 0) {1407 if (ssp_buf_size != 0) {
...@@ -2982,12 +3001,6 @@ pub const Object = struct {...@@ -2982,12 +3001,6 @@ pub const Object = struct {
2982 try attributes.addFnAttr(.minsize, &o.builder);3001 try attributes.addFnAttr(.minsize, &o.builder);
2983 try attributes.addFnAttr(.optsize, &o.builder);3002 try attributes.addFnAttr(.optsize, &o.builder);
2984 }3003 }
2985 if (owner_mod.sanitize_thread) {
2986 try attributes.addFnAttr(.sanitize_thread, &o.builder);
2987 }
2988 if (owner_mod.fuzz) {
2989 try attributes.addFnAttr(.optforfuzzing, &o.builder);
2990 }
2991 const target = owner_mod.resolved_target.result;3004 const target = owner_mod.resolved_target.result;
2992 if (target.cpu.model.llvm_name) |s| {3005 if (target.cpu.model.llvm_name) |s| {
2993 try attributes.addFnAttr(.{ .string = .{3006 try attributes.addFnAttr(.{ .string = .{
src/print_zir.zig+1
...@@ -524,6 +524,7 @@ const Writer = struct {...@@ -524,6 +524,7 @@ const Writer = struct {
524 .frame,524 .frame,
525 .frame_address,525 .frame_address,
526 .breakpoint,526 .breakpoint,
527 .disable_instrumentation,
527 .c_va_start,528 .c_va_start,
528 .in_comptime,529 .in_comptime,
529 .value_placeholder,530 .value_placeholder,