mirror of
https://github.com/ziglang/zig.git
synced 2026-01-05 13:03:25 +00:00
Merge pull request #21710 from alexrp/function-alignment
Some improvements to the compiler's handling of function alignment
This commit is contained in:
commit
03d0e296cb
@ -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: {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user