Skip to content

Commit 1c35e73

Browse files
alexrpandrewrk
authored andcommitted
llvm: Don't emit safety memset() for stores of undef in Debug with safety off.
Before, this code: @setRuntimeSafety(false); var arr: [38]elf.Addr = undefined; would emit a call to memset() in the output code in Debug mode, while in all the release modes, LLVM optimized the memset() out as expected. Emitting the call in Debug mode is problematic in some contexts, e.g. in std.os.linux.start_pie where we are not yet ready to correctly perform calls because relocations haven't been applied yet, or in the early stages of a dynamic linker, etc.
1 parent 81a172a commit 1c35e73

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed

src/codegen/llvm.zig

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8997,6 +8997,21 @@ pub const FuncGen = struct {
89978997

89988998
const val_is_undef = if (try self.air.value(bin_op.rhs, pt)) |val| val.isUndefDeep(mod) else false;
89998999
if (val_is_undef) {
9000+
const owner_mod = self.dg.ownerModule();
9001+
9002+
// Even if safety is disabled, we still emit a memset to undefined since it conveys
9003+
// extra information to LLVM, and LLVM will optimize it out. Safety makes the difference
9004+
// between using 0xaa or actual undefined for the fill byte.
9005+
//
9006+
// However, for Debug builds specifically, we avoid emitting the memset because LLVM
9007+
// will neither use the information nor get rid of the memset, thus leaving an
9008+
// unexpected call in the user's code. This is problematic if the code in question is
9009+
// not ready to correctly make calls yet, such as in our early PIE startup code, or in
9010+
// the early stages of a dynamic linker, etc.
9011+
if (!safety and owner_mod.optimize_mode == .Debug) {
9012+
return .none;
9013+
}
9014+
90009015
const ptr_info = ptr_ty.ptrInfo(mod);
90019016
const needs_bitmask = (ptr_info.packed_offset.host_size != 0);
90029017
if (needs_bitmask) {
@@ -9006,9 +9021,6 @@ pub const FuncGen = struct {
90069021
return .none;
90079022
}
90089023

9009-
// Even if safety is disabled, we still emit a memset to undefined since it conveys
9010-
// extra information to LLVM. However, safety makes the difference between using
9011-
// 0xaa or actual undefined for the fill byte.
90129024
const len = try o.builder.intValue(try o.lowerType(Type.usize), operand_ty.abiSize(pt));
90139025
_ = try self.wip.callMemSet(
90149026
dest_ptr,
@@ -9017,7 +9029,6 @@ pub const FuncGen = struct {
90179029
len,
90189030
if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal,
90199031
);
9020-
const owner_mod = self.dg.ownerModule();
90219032
if (safety and owner_mod.valgrind) {
90229033
try self.valgrindMarkUndef(dest_ptr, len);
90239034
}

0 commit comments

Comments
 (0)