aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorAlex Rønne Petersen <alex@alexrp.com>2025-02-15 02:44:58 +0100
committerAlex Rønne Petersen <alex@alexrp.com>2025-02-22 04:12:46 +0100
commitfc7a0c4878dac2d721ec18cafe1b6bcff7faa771 (patch)
tree5b9e4ef2d18e3daaf4bee34ae1bfe5af97916e8a /src/Sema.zig
parentd31bda13cb1ece7dd2ba22339172a8704a84823c (diff)
downloadzig-fc7a0c4878dac2d721ec18cafe1b6bcff7faa771.tar.gz
zig-fc7a0c4878dac2d721ec18cafe1b6bcff7faa771.zip
Sema: Fix fnptr alignment safety checks to account for potential ISA tag.
As seen on e.g. Arm/Thumb and MIPS (MIPS16/microMIPS). Fixes #22888.
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig30
1 files changed, 24 insertions, 6 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index cbfeef6339..7e3ab51a29 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -23099,8 +23099,14 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
}
if (ptr_align.compare(.gt, .@"1")) {
const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1;
- const align_minus_1 = Air.internedToRef((try sema.splat(operand_ty, try pt.intValue(Type.usize, align_bytes_minus_1))).toIntern());
- const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1);
+ const align_mask = Air.internedToRef((try sema.splat(operand_ty, try pt.intValue(
+ Type.usize,
+ if (elem_ty.fnPtrMaskOrNull(zcu)) |mask|
+ align_bytes_minus_1 & mask
+ else
+ align_bytes_minus_1,
+ ))).toIntern());
+ const remainder = try block.addBinOp(.bit_and, operand_coerced, align_mask);
const is_aligned = if (is_vector) all_aligned: {
const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq);
@@ -23129,8 +23135,14 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
}
if (ptr_align.compare(.gt, .@"1")) {
const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1;
- const align_minus_1 = Air.internedToRef((try pt.intValue(Type.usize, align_bytes_minus_1)).toIntern());
- const remainder = try block.addBinOp(.bit_and, elem_coerced, align_minus_1);
+ const align_mask = Air.internedToRef((try pt.intValue(
+ Type.usize,
+ if (elem_ty.fnPtrMaskOrNull(zcu)) |mask|
+ align_bytes_minus_1 & mask
+ else
+ align_bytes_minus_1,
+ )).toIntern());
+ const remainder = try block.addBinOp(.bit_and, elem_coerced, align_mask);
const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);
try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);
}
@@ -23710,13 +23722,19 @@ fn ptrCastFull(
try Type.fromInterned(dest_info.child).hasRuntimeBitsSema(pt))
{
const align_bytes_minus_1 = dest_align.toByteUnits().? - 1;
- const align_minus_1 = Air.internedToRef((try pt.intValue(Type.usize, align_bytes_minus_1)).toIntern());
+ const align_mask = Air.internedToRef((try pt.intValue(
+ Type.usize,
+ if (Type.fromInterned(dest_info.child).fnPtrMaskOrNull(zcu)) |mask|
+ align_bytes_minus_1 & mask
+ else
+ align_bytes_minus_1,
+ )).toIntern());
const actual_ptr = if (src_info.flags.size == .slice)
try sema.analyzeSlicePtr(block, src, ptr, operand_ty)
else
ptr;
const ptr_int = try block.addBitCast(.usize, actual_ptr);
- const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1);
+ const remainder = try block.addBinOp(.bit_and, ptr_int, align_mask);
const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);
const ok = if (src_info.flags.size == .slice and dest_info.flags.size == .slice) ok: {
const len = try sema.analyzeSliceLen(block, operand_src, ptr);