Skip to content

Commit

Permalink
Merge pull request #21710 from alexrp/function-alignment
Browse files Browse the repository at this point in the history
Some improvements to the compiler's handling of function alignment
  • Loading branch information
alexrp authored Oct 25, 2024
2 parents 5769592 + 6c1e306 commit 03d0e29
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 30 deletions.
8 changes: 2 additions & 6 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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: {
Expand Down
2 changes: 1 addition & 1 deletion src/Type.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 9 additions & 2 deletions src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 5 additions & 3 deletions src/link/Coff.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 5 additions & 2 deletions src/link/Dwarf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down
8 changes: 5 additions & 3 deletions src/link/Elf/ZigObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
8 changes: 5 additions & 3 deletions src/link/MachO/ZigObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
73 changes: 63 additions & 10 deletions src/target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
.riscv32,
.riscv64,
=> 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,
.riscv32,
.riscv64,
.hexagon,
.lanai,
.loongarch32,
.loongarch64,
.mips,
.mipsel,
.powerpc,
.powerpcle,
.powerpc64,
.powerpc64le,
.sparc,
.sparc64,
=> .@"2",
.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,
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 03d0e29

Please sign in to comment.