| author | |
| committer | |
| log | 25198810c88d474c63ff537e3647f12e7df6297c |
| tree | f92e3b6dcf75aa653df9786fb6c17360291a8e4c |
| parent | 7930efc60becd7624471419b8fd49800512d4e10 |
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 | 2817 | |
| 2818 | 2818 | .extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) { |
| 2819 | 2819 | .breakpoint, |
| 2820 | .disable_instrumentation, | |
| 2820 | 2821 | .fence, |
| 2821 | 2822 | .set_float_mode, |
| 2822 | 2823 | .set_align_stack, |
| ... | ... | @@ -9305,12 +9306,13 @@ fn builtinCall( |
| 9305 | 9306 | }, |
| 9306 | 9307 | |
| 9307 | 9308 | // zig fmt: off |
| 9308 | .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 | .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_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node), | |
| 9313 | .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node), | |
| 9309 | .This => return rvalue(gz, ri, try gz.addNodeExtended(.this, node), node), | |
| 9310 | .return_address => return rvalue(gz, ri, try gz.addNodeExtended(.ret_addr, node), node), | |
| 9311 | .error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node), | |
| 9312 | .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node), | |
| 9313 | .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, 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), | |
| 9314 | 9316 | |
| 9315 | 9317 | .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info), |
| 9316 | 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 | 877 | .error_return_trace, |
| 878 | 878 | .frame, |
| 879 | 879 | .breakpoint, |
| 880 | .disable_instrumentation, | |
| 880 | 881 | .in_comptime, |
| 881 | 882 | .panic, |
| 882 | 883 | .trap, |
lib/std/zig/BuiltinFn.zig+9| ... | ... | @@ -15,6 +15,7 @@ pub const Tag = enum { |
| 15 | 15 | int_from_bool, |
| 16 | 16 | bit_size_of, |
| 17 | 17 | breakpoint, |
| 18 | disable_instrumentation, | |
| 18 | 19 | mul_add, |
| 19 | 20 | byte_swap, |
| 20 | 21 | bit_reverse, |
| ... | ... | @@ -263,6 +264,14 @@ pub const list = list: { |
| 263 | 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 | 276 | "@mulAdd", |
| 268 | 277 | .{ |
lib/std/zig/Zir.zig+3-1| ... | ... | @@ -1553,7 +1553,7 @@ pub const Inst = struct { |
| 1553 | 1553 | => false, |
| 1554 | 1554 | |
| 1555 | 1555 | .extended => switch (data.extended.opcode) { |
| 1556 | .fence, .set_cold, .breakpoint => true, | |
| 1556 | .fence, .set_cold, .breakpoint, .disable_instrumentation => true, | |
| 1557 | 1557 | else => false, |
| 1558 | 1558 | }, |
| 1559 | 1559 | }; |
| ... | ... | @@ -1973,6 +1973,8 @@ pub const Inst = struct { |
| 1973 | 1973 | /// Implements `@breakpoint`. |
| 1974 | 1974 | /// `operand` is `src_node: i32`. |
| 1975 | 1975 | breakpoint, |
| 1976 | /// Implement builtin `@disableInstrumentation`. `operand` is `src_node: i32`. | |
| 1977 | disable_instrumentation, | |
| 1976 | 1978 | /// Implements the `@select` builtin. |
| 1977 | 1979 | /// `operand` is payload index to `Select`. |
| 1978 | 1980 | select, |
src/InternPool.zig+18-2| ... | ... | @@ -5184,11 +5184,11 @@ pub const FuncAnalysis = packed struct(u32) { |
| 5184 | 5184 | is_noinline: bool, |
| 5185 | 5185 | calls_or_awaits_errorable_fn: bool, |
| 5186 | 5186 | stack_alignment: Alignment, |
| 5187 | ||
| 5188 | 5187 | /// True if this function has an inferred error set. |
| 5189 | 5188 | inferred_error_set: bool, |
| 5189 | disable_instrumentation: bool, | |
| 5190 | 5190 | |
| 5191 | _: u14 = 0, | |
| 5191 | _: u13 = 0, | |
| 5192 | 5192 | |
| 5193 | 5193 | pub const State = enum(u8) { |
| 5194 | 5194 | /// This function has not yet undergone analysis, because we have not |
| ... | ... | @@ -8111,6 +8111,7 @@ pub fn getFuncDecl( |
| 8111 | 8111 | .calls_or_awaits_errorable_fn = false, |
| 8112 | 8112 | .stack_alignment = .none, |
| 8113 | 8113 | .inferred_error_set = false, |
| 8114 | .disable_instrumentation = false, | |
| 8114 | 8115 | }, |
| 8115 | 8116 | .owner_decl = key.owner_decl, |
| 8116 | 8117 | .ty = key.ty, |
| ... | ... | @@ -8214,6 +8215,7 @@ pub fn getFuncDeclIes( |
| 8214 | 8215 | .calls_or_awaits_errorable_fn = false, |
| 8215 | 8216 | .stack_alignment = .none, |
| 8216 | 8217 | .inferred_error_set = true, |
| 8218 | .disable_instrumentation = false, | |
| 8217 | 8219 | }, |
| 8218 | 8220 | .owner_decl = key.owner_decl, |
| 8219 | 8221 | .ty = func_ty, |
| ... | ... | @@ -8405,6 +8407,7 @@ pub fn getFuncInstance( |
| 8405 | 8407 | .calls_or_awaits_errorable_fn = false, |
| 8406 | 8408 | .stack_alignment = .none, |
| 8407 | 8409 | .inferred_error_set = false, |
| 8410 | .disable_instrumentation = false, | |
| 8408 | 8411 | }, |
| 8409 | 8412 | // This is populated after we create the Decl below. It is not read |
| 8410 | 8413 | // by equality or hashing functions. |
| ... | ... | @@ -8504,6 +8507,7 @@ pub fn getFuncInstanceIes( |
| 8504 | 8507 | .calls_or_awaits_errorable_fn = false, |
| 8505 | 8508 | .stack_alignment = .none, |
| 8506 | 8509 | .inferred_error_set = true, |
| 8510 | .disable_instrumentation = false, | |
| 8507 | 8511 | }, |
| 8508 | 8512 | // This is populated after we create the Decl below. It is not read |
| 8509 | 8513 | // by equality or hashing functions. |
| ... | ... | @@ -11225,6 +11229,18 @@ pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void { |
| 11225 | 11229 | @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); |
| 11226 | 11230 | } |
| 11227 | 11231 | |
| 11232 | pub 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 | ||
| 11228 | 11244 | pub fn funcSetCold(ip: *InternPool, func: Index, is_cold: bool) void { |
| 11229 | 11245 | const unwrapped_func = func.unwrap(ip); |
| 11230 | 11246 | const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; |
src/Sema.zig+13| ... | ... | @@ -1316,6 +1316,11 @@ fn analyzeBodyInner( |
| 1316 | 1316 | i += 1; |
| 1317 | 1317 | continue; |
| 1318 | 1318 | }, |
| 1319 | .disable_instrumentation => { | |
| 1320 | try sema.zirDisableInstrumentation(); | |
| 1321 | i += 1; | |
| 1322 | continue; | |
| 1323 | }, | |
| 1319 | 1324 | .restore_err_ret_index => { |
| 1320 | 1325 | try sema.zirRestoreErrRetIndex(block, extended); |
| 1321 | 1326 | i += 1; |
| ... | ... | @@ -6576,6 +6581,14 @@ fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) |
| 6576 | 6581 | ip.funcSetCold(sema.func_index, is_cold); |
| 6577 | 6582 | } |
| 6578 | 6583 | |
| 6584 | fn 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 | ||
| 6579 | 6592 | fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| 6580 | 6593 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 6581 | 6594 | const src = block.builtinCallArgSrc(extra.node, 0); |
src/codegen/llvm.zig+19-6| ... | ... | @@ -1383,6 +1383,25 @@ pub const Object = struct { |
| 1383 | 1383 | _ = try attributes.removeFnAttr(.cold); |
| 1384 | 1384 | } |
| 1385 | 1385 | |
| 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 | 1405 | // TODO: disable this if safety is off for the function scope |
| 1387 | 1406 | const ssp_buf_size = owner_mod.stack_protector; |
| 1388 | 1407 | if (ssp_buf_size != 0) { |
| ... | ... | @@ -2982,12 +3001,6 @@ pub const Object = struct { |
| 2982 | 3001 | try attributes.addFnAttr(.minsize, &o.builder); |
| 2983 | 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 | 3004 | const target = owner_mod.resolved_target.result; |
| 2992 | 3005 | if (target.cpu.model.llvm_name) |s| { |
| 2993 | 3006 | try attributes.addFnAttr(.{ .string = .{ |
src/print_zir.zig+1| ... | ... | @@ -524,6 +524,7 @@ const Writer = struct { |
| 524 | 524 | .frame, |
| 525 | 525 | .frame_address, |
| 526 | 526 | .breakpoint, |
| 527 | .disable_instrumentation, | |
| 527 | 528 | .c_va_start, |
| 528 | 529 | .in_comptime, |
| 529 | 530 | .value_placeholder, |