| ... | @@ -8997,6 +8997,21 @@ pub const FuncGen = struct { | ... | @@ -8997,6 +8997,21 @@ pub const FuncGen = struct { |
| 8997 | | 8997 | |
| 8998 | const val_is_undef = if (try self.air.value(bin_op.rhs, pt)) |val| val.isUndefDeep(mod) else false; | 8998 | const val_is_undef = if (try self.air.value(bin_op.rhs, pt)) |val| val.isUndefDeep(mod) else false; |
| 8999 | if (val_is_undef) { | 8999 | 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 | |
| 9000 | const ptr_info = ptr_ty.ptrInfo(mod); | 9015 | const ptr_info = ptr_ty.ptrInfo(mod); |
| 9001 | const needs_bitmask = (ptr_info.packed_offset.host_size != 0); | 9016 | const needs_bitmask = (ptr_info.packed_offset.host_size != 0); |
| 9002 | if (needs_bitmask) { | 9017 | if (needs_bitmask) { |
| ... | @@ -9006,9 +9021,6 @@ pub const FuncGen = struct { | ... | @@ -9006,9 +9021,6 @@ pub const FuncGen = struct { |
| 9006 | return .none; | 9021 | return .none; |
| 9007 | } | 9022 | } |
| 9008 | | 9023 | |
| 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. | | |
| 9012 | const len = try o.builder.intValue(try o.lowerType(Type.usize), operand_ty.abiSize(pt)); | 9024 | const len = try o.builder.intValue(try o.lowerType(Type.usize), operand_ty.abiSize(pt)); |
| 9013 | _ = try self.wip.callMemSet( | 9025 | _ = try self.wip.callMemSet( |
| 9014 | dest_ptr, | 9026 | dest_ptr, |
| ... | @@ -9017,7 +9029,6 @@ pub const FuncGen = struct { | ... | @@ -9017,7 +9029,6 @@ pub const FuncGen = struct { |
| 9017 | len, | 9029 | len, |
| 9018 | if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal, | 9030 | if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal, |
| 9019 | ); | 9031 | ); |
| 9020 | const owner_mod = self.dg.ownerModule(); | | |
| 9021 | if (safety and owner_mod.valgrind) { | 9032 | if (safety and owner_mod.valgrind) { |
| 9022 | try self.valgrindMarkUndef(dest_ptr, len); | 9033 | try self.valgrindMarkUndef(dest_ptr, len); |
| 9023 | } | 9034 | } |