diff --git a/src/Sema.zig b/src/Sema.zig index 9912a610ff6d4667fbf5d7eed70e68a0c798b5b2..24e64cbc46e21c573836ac17c3406ca524872753 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -26658,9 +26658,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A if (val.isGenericPoison()) { break :blk null; } - const alignment = try sema.validateAlignAllowZero(block, align_src, try val.toUnsignedIntSema(pt)); - const default = target_util.defaultFunctionAlignment(target); - break :blk if (alignment == default) .none else alignment; + break :blk try sema.validateAlignAllowZero(block, align_src, try val.toUnsignedIntSema(pt)); } else if (extra.data.bits.has_align_ref) blk: { const align_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); extra_index += 1; @@ -26678,9 +26676,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A error.GenericPoison => break :blk null, else => |e| return e, }; - const alignment = try sema.validateAlignAllowZero(block, align_src, try align_val.toUnsignedIntSema(pt)); - const default = target_util.defaultFunctionAlignment(target); - break :blk if (alignment == default) .none else alignment; + break :blk try sema.validateAlignAllowZero(block, align_src, try align_val.toUnsignedIntSema(pt)); } else .none; const @"addrspace": ?std.builtin.AddressSpace = if (extra.data.bits.has_addrspace_body) blk: { diff --git a/src/Type.zig b/src/Type.zig index 62997d2d93675719e3f1fa31946af0fef3844c74..1fa526a3046ff32179e315c4fcfcb46296bbcd8d 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -1027,7 +1027,7 @@ pub fn abiAlignmentInner( }, // represents machine code; not a pointer - .func_type => return .{ .scalar = target_util.defaultFunctionAlignment(target) }, + .func_type => return .{ .scalar = target_util.minFunctionAlignment(target) }, .simple_type => |t| switch (t) { .bool, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index f19577cac88bd1d7458c26fe898841b3779a7cf7..88711288a05d473cd0c3a7db5f72f5edf307ba38 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -458,10 +458,15 @@ const DataLayoutBuilder = struct { if (idx != size) try writer.print(":{d}", .{idx}); } } - if (self.target.cpu.arch.isArmOrThumb()) try writer.writeAll("-Fi8") // for thumb interwork + if (self.target.cpu.arch.isArmOrThumb()) + try writer.writeAll("-Fi8") // for thumb interwork else if (self.target.cpu.arch == .powerpc64 and - self.target.os.tag != .freebsd and self.target.abi != .musl) + self.target.os.tag != .freebsd and + self.target.os.tag != .openbsd and + !self.target.abi.isMusl()) try writer.writeAll("-Fi64") + else if (self.target.cpu.arch.isPowerPC() and self.target.os.tag == .aix) + try writer.writeAll(if (self.target.cpu.arch.isPowerPC64()) "-Fi64" else "-Fi32") else if (self.target.cpu.arch.isPowerPC()) try writer.writeAll("-Fn32"); if (self.target.cpu.arch != .hexagon) { @@ -574,6 +579,8 @@ const DataLayoutBuilder = struct { self.target.os.tag == .uefi or self.target.os.tag == .windows or self.target.cpu.arch == .riscv32) try writer.print("-S{d}", .{stack_abi}); + if (self.target.cpu.arch.isAARCH64()) + try writer.writeAll("-Fn32"); switch (self.target.cpu.arch) { .hexagon, .ve => { try self.typeAlignment(.vector, 32, 128, 128, true, writer); diff --git a/src/link/Coff.zig b/src/link/Coff.zig index f687c7393b263dbbca90c3d357091fc42f67a9d0..bc88f5fc4c77db6c30517b27d4781a39f20faf46 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1388,9 +1388,11 @@ fn updateNavCode( log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index }); - const required_alignment = pt.navAlignment(nav_index).max( - target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result), - ); + const target = zcu.navFileScope(nav_index).mod.resolved_target.result; + const required_alignment = switch (pt.navAlignment(nav_index)) { + .none => target_util.defaultFunctionAlignment(target), + else => |a| a.maxStrict(target_util.minFunctionAlignment(target)), + }; const nav_metadata = coff.navs.get(nav_index).?; const atom_index = nav_metadata.atom; diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index da92f5a03de0b63045858817fd8d86d767ab6639..d428377c3b651af30e75689204bfa23a3e8c3a4a 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -2372,8 +2372,11 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In try wip_nav.infoAddrSym(sym_index, 0); wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len); try diw.writeInt(u32, 0, dwarf.endian); - try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse - target_info.defaultFunctionAlignment(file.mod.resolved_target.result).toByteUnits().?); + const target = file.mod.resolved_target.result; + try uleb128(diw, switch (nav.status.resolved.alignment) { + .none => target_info.defaultFunctionAlignment(target), + else => |a| a.maxStrict(target_info.minFunctionAlignment(target)), + }.toByteUnits().?); try diw.writeByte(@intFromBool(false)); try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type)); diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 114a862fb634fcffcf003f997de3cfb38e106cf6..84b54aabcd57cba00ea36582c9c51ed74d16714a 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -1271,9 +1271,11 @@ fn updateNavCode( log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index }); - const required_alignment = pt.navAlignment(nav_index).max( - target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result), - ); + const target = zcu.navFileScope(nav_index).mod.resolved_target.result; + const required_alignment = switch (pt.navAlignment(nav_index)) { + .none => target_util.defaultFunctionAlignment(target), + else => |a| a.maxStrict(target_util.minFunctionAlignment(target)), + }; const sym = self.symbol(sym_index); const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 666a73f6007ea369d031bbdf1edc649dead826e3..097be1bc709ed0863d4ee85364739398d03d20d3 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -962,9 +962,11 @@ fn updateNavCode( log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index }); - const required_alignment = pt.navAlignment(nav_index).max( - target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result), - ); + const target = zcu.navFileScope(nav_index).mod.resolved_target.result; + const required_alignment = switch (pt.navAlignment(nav_index)) { + .none => target_util.defaultFunctionAlignment(target), + else => |a| a.maxStrict(target_util.minFunctionAlignment(target)), + }; const sect = &macho_file.sections.items(.header)[sect_index]; const sym = &self.symbols.items[sym_index]; diff --git a/src/target.zig b/src/target.zig index ec34a23f0d7572badf73acaa74eb0b6b2a767798..1f8a567f03c95f1f9268fd611c8507fae406e025 100644 --- a/src/target.zig +++ b/src/target.zig @@ -436,35 +436,88 @@ pub fn llvmMachineAbi(target: std.Target) ?[:0]const u8 { } } -/// This function returns 1 if function alignment is not observable or settable. +/// This function returns 1 if function alignment is not observable or settable. Note that this +/// value will not necessarily match the backend's default function alignment (e.g. for LLVM). pub fn defaultFunctionAlignment(target: std.Target) Alignment { + // Overrides of the minimum for performance. return switch (target.cpu.arch) { - .arm, .armeb => .@"4", - .aarch64, .aarch64_be => .@"4", - .sparc, .sparc64 => .@"4", - .riscv64 => .@"2", - else => .@"1", + .csky, + .thumb, + .thumbeb, + .xcore, + => .@"4", + .aarch64, + .aarch64_be, + .hexagon, + .powerpc, + .powerpcle, + .powerpc64, + .powerpc64le, + .s390x, + .x86, + .x86_64, + => .@"16", + .loongarch32, + .loongarch64, + => .@"32", + else => minFunctionAlignment(target), }; } +/// This function returns 1 if function alignment is not observable or settable. pub fn minFunctionAlignment(target: std.Target) Alignment { return switch (target.cpu.arch) { - .arm, - .armeb, - .aarch64, - .aarch64_be, .riscv32, .riscv64, - .sparc, - .sparc64, + => if (std.Target.riscv.featureSetHasAny(target.cpu.features, .{ .c, .zca })) .@"2" else .@"4", + .thumb, + .thumbeb, + .csky, + .m68k, + .msp430, + .s390x, + .xcore, => .@"2", + .arc, + .arm, + .armeb, + .aarch64, + .aarch64_be, + .hexagon, + .lanai, + .loongarch32, + .loongarch64, + .mips, + .mipsel, + .powerpc, + .powerpcle, + .powerpc64, + .powerpc64le, + .sparc, + .sparc64, + .xtensa, + => .@"4", + .bpfel, + .bpfeb, + .mips64, + .mips64el, + => .@"8", + .ve, + => .@"16", else => .@"1", }; } pub fn supportsFunctionAlignment(target: std.Target) bool { return switch (target.cpu.arch) { - .wasm32, .wasm64 => false, + .nvptx, + .nvptx64, + .spirv, + .spirv32, + .spirv64, + .wasm32, + .wasm64, + => false, else => true, }; } diff --git a/test/cases/compile_errors/function_alignment_on_unsupported_target.zig b/test/cases/compile_errors/function_alignment_on_unsupported_target.zig new file mode 100644 index 0000000000000000000000000000000000000000..7b033e0f60a8990b0686329197f4ee50fc08a41b --- /dev/null +++ b/test/cases/compile_errors/function_alignment_on_unsupported_target.zig @@ -0,0 +1,7 @@ +export fn entry() align(0) void {} + +// error +// backend=stage2 +// target=nvptx-cuda,nvptx64-cuda,spirv-vulkan,spirv32-opencl,spirv64-opencl,wasm32-freestanding,wasm64-freestanding +// +// :1:25: error: target does not support function alignment