authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-25 11:10:28+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-10-25 11:10:28+02:00
log03d0e296cb8a8afb2bd81c030b31e96e6e2940c7
treef340a6c090dd562ec0d710573d66e1651ced5bd5
parent5769592cdda3c14a37b8c381219343052609cbbc
parent6c1e306484530bfeaf26450fb83a70ff1c323bcd
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21710 from alexrp/function-alignment

Some improvements to the compiler's handling of function alignment

9 files changed, 102 insertions(+), 30 deletions(-)

src/Sema.zig+2-6
...@@ -26658,9 +26658,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26658,9 +26658,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26658 if (val.isGenericPoison()) {26658 if (val.isGenericPoison()) {
26659 break :blk null;26659 break :blk null;
26660 }26660 }
26661 const alignment = try sema.validateAlignAllowZero(block, align_src, try val.toUnsignedIntSema(pt));26661 break :blk try sema.validateAlignAllowZero(block, align_src, try val.toUnsignedIntSema(pt));
26662 const default = target_util.defaultFunctionAlignment(target);
26663 break :blk if (alignment == default) .none else alignment;
26664 } else if (extra.data.bits.has_align_ref) blk: {26662 } else if (extra.data.bits.has_align_ref) blk: {
26665 const align_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);26663 const align_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
26666 extra_index += 1;26664 extra_index += 1;
...@@ -26678,9 +26676,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26678,9 +26676,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26678 error.GenericPoison => break :blk null,26676 error.GenericPoison => break :blk null,
26679 else => |e| return e,26677 else => |e| return e,
26680 };26678 };
26681 const alignment = try sema.validateAlignAllowZero(block, align_src, try align_val.toUnsignedIntSema(pt));26679 break :blk try sema.validateAlignAllowZero(block, align_src, try align_val.toUnsignedIntSema(pt));
26682 const default = target_util.defaultFunctionAlignment(target);
26683 break :blk if (alignment == default) .none else alignment;
26684 } else .none;26680 } else .none;
2668526681
26686 const @"addrspace": ?std.builtin.AddressSpace = if (extra.data.bits.has_addrspace_body) blk: {26682 const @"addrspace": ?std.builtin.AddressSpace = if (extra.data.bits.has_addrspace_body) blk: {
src/Type.zig+1-1
...@@ -1027,7 +1027,7 @@ pub fn abiAlignmentInner(...@@ -1027,7 +1027,7 @@ pub fn abiAlignmentInner(
1027 },1027 },
10281028
1029 // represents machine code; not a pointer1029 // represents machine code; not a pointer
1030 .func_type => return .{ .scalar = target_util.defaultFunctionAlignment(target) },1030 .func_type => return .{ .scalar = target_util.minFunctionAlignment(target) },
10311031
1032 .simple_type => |t| switch (t) {1032 .simple_type => |t| switch (t) {
1033 .bool,1033 .bool,
src/codegen/llvm.zig+9-2
...@@ -458,10 +458,15 @@ const DataLayoutBuilder = struct {...@@ -458,10 +458,15 @@ const DataLayoutBuilder = struct {
458 if (idx != size) try writer.print(":{d}", .{idx});458 if (idx != size) try writer.print(":{d}", .{idx});
459 }459 }
460 }460 }
461 if (self.target.cpu.arch.isArmOrThumb()) try writer.writeAll("-Fi8") // for thumb interwork461 if (self.target.cpu.arch.isArmOrThumb())
462 try writer.writeAll("-Fi8") // for thumb interwork
462 else if (self.target.cpu.arch == .powerpc64 and463 else if (self.target.cpu.arch == .powerpc64 and
463 self.target.os.tag != .freebsd and self.target.abi != .musl)464 self.target.os.tag != .freebsd and
465 self.target.os.tag != .openbsd and
466 !self.target.abi.isMusl())
464 try writer.writeAll("-Fi64")467 try writer.writeAll("-Fi64")
468 else if (self.target.cpu.arch.isPowerPC() and self.target.os.tag == .aix)
469 try writer.writeAll(if (self.target.cpu.arch.isPowerPC64()) "-Fi64" else "-Fi32")
465 else if (self.target.cpu.arch.isPowerPC())470 else if (self.target.cpu.arch.isPowerPC())
466 try writer.writeAll("-Fn32");471 try writer.writeAll("-Fn32");
467 if (self.target.cpu.arch != .hexagon) {472 if (self.target.cpu.arch != .hexagon) {
...@@ -574,6 +579,8 @@ const DataLayoutBuilder = struct {...@@ -574,6 +579,8 @@ const DataLayoutBuilder = struct {
574 self.target.os.tag == .uefi or self.target.os.tag == .windows or579 self.target.os.tag == .uefi or self.target.os.tag == .windows or
575 self.target.cpu.arch == .riscv32)580 self.target.cpu.arch == .riscv32)
576 try writer.print("-S{d}", .{stack_abi});581 try writer.print("-S{d}", .{stack_abi});
582 if (self.target.cpu.arch.isAARCH64())
583 try writer.writeAll("-Fn32");
577 switch (self.target.cpu.arch) {584 switch (self.target.cpu.arch) {
578 .hexagon, .ve => {585 .hexagon, .ve => {
579 try self.typeAlignment(.vector, 32, 128, 128, true, writer);586 try self.typeAlignment(.vector, 32, 128, 128, true, writer);
src/link/Coff.zig+5-3
...@@ -1388,9 +1388,11 @@ fn updateNavCode(...@@ -1388,9 +1388,11 @@ fn updateNavCode(
13881388
1389 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });1389 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
13901390
1391 const required_alignment = pt.navAlignment(nav_index).max(1391 const target = zcu.navFileScope(nav_index).mod.resolved_target.result;
1392 target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result),1392 const required_alignment = switch (pt.navAlignment(nav_index)) {
1393 );1393 .none => target_util.defaultFunctionAlignment(target),
1394 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
1395 };
13941396
1395 const nav_metadata = coff.navs.get(nav_index).?;1397 const nav_metadata = coff.navs.get(nav_index).?;
1396 const atom_index = nav_metadata.atom;1398 const atom_index = nav_metadata.atom;
src/link/Dwarf.zig+5-2
...@@ -2372,8 +2372,11 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -2372,8 +2372,11 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
2372 try wip_nav.infoAddrSym(sym_index, 0);2372 try wip_nav.infoAddrSym(sym_index, 0);
2373 wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len);2373 wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len);
2374 try diw.writeInt(u32, 0, dwarf.endian);2374 try diw.writeInt(u32, 0, dwarf.endian);
2375 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse2375 const target = file.mod.resolved_target.result;
2376 target_info.defaultFunctionAlignment(file.mod.resolved_target.result).toByteUnits().?);2376 try uleb128(diw, switch (nav.status.resolved.alignment) {
2377 .none => target_info.defaultFunctionAlignment(target),
2378 else => |a| a.maxStrict(target_info.minFunctionAlignment(target)),
2379 }.toByteUnits().?);
2377 try diw.writeByte(@intFromBool(false));2380 try diw.writeByte(@intFromBool(false));
2378 try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type));2381 try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type));
23792382
src/link/Elf/ZigObject.zig+5-3
...@@ -1271,9 +1271,11 @@ fn updateNavCode(...@@ -1271,9 +1271,11 @@ fn updateNavCode(
12711271
1272 log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index });1272 log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index });
12731273
1274 const required_alignment = pt.navAlignment(nav_index).max(1274 const target = zcu.navFileScope(nav_index).mod.resolved_target.result;
1275 target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result),1275 const required_alignment = switch (pt.navAlignment(nav_index)) {
1276 );1276 .none => target_util.defaultFunctionAlignment(target),
1277 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
1278 };
12771279
1278 const sym = self.symbol(sym_index);1280 const sym = self.symbol(sym_index);
1279 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];1281 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
src/link/MachO/ZigObject.zig+5-3
...@@ -962,9 +962,11 @@ fn updateNavCode(...@@ -962,9 +962,11 @@ fn updateNavCode(
962962
963 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });963 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
964964
965 const required_alignment = pt.navAlignment(nav_index).max(965 const target = zcu.navFileScope(nav_index).mod.resolved_target.result;
966 target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result),966 const required_alignment = switch (pt.navAlignment(nav_index)) {
967 );967 .none => target_util.defaultFunctionAlignment(target),
968 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
969 };
968970
969 const sect = &macho_file.sections.items(.header)[sect_index];971 const sect = &macho_file.sections.items(.header)[sect_index];
970 const sym = &self.symbols.items[sym_index];972 const sym = &self.symbols.items[sym_index];
src/target.zig+63-10
...@@ -436,35 +436,88 @@ pub fn llvmMachineAbi(target: std.Target) ?[:0]const u8 {...@@ -436,35 +436,88 @@ pub fn llvmMachineAbi(target: std.Target) ?[:0]const u8 {
436 }436 }
437}437}
438438
439/// This function returns 1 if function alignment is not observable or settable.439/// This function returns 1 if function alignment is not observable or settable. Note that this
440/// value will not necessarily match the backend's default function alignment (e.g. for LLVM).
440pub fn defaultFunctionAlignment(target: std.Target) Alignment {441pub fn defaultFunctionAlignment(target: std.Target) Alignment {
442 // Overrides of the minimum for performance.
441 return switch (target.cpu.arch) {443 return switch (target.cpu.arch) {
442 .arm, .armeb => .@"4",444 .csky,
443 .aarch64, .aarch64_be => .@"4",445 .thumb,
444 .sparc, .sparc64 => .@"4",446 .thumbeb,
445 .riscv64 => .@"2",447 .xcore,
446 else => .@"1",448 => .@"4",
449 .aarch64,
450 .aarch64_be,
451 .hexagon,
452 .powerpc,
453 .powerpcle,
454 .powerpc64,
455 .powerpc64le,
456 .s390x,
457 .x86,
458 .x86_64,
459 => .@"16",
460 .loongarch32,
461 .loongarch64,
462 => .@"32",
463 else => minFunctionAlignment(target),
447 };464 };
448}465}
449466
467/// This function returns 1 if function alignment is not observable or settable.
450pub fn minFunctionAlignment(target: std.Target) Alignment {468pub fn minFunctionAlignment(target: std.Target) Alignment {
451 return switch (target.cpu.arch) {469 return switch (target.cpu.arch) {
470 .riscv32,
471 .riscv64,
472 => if (std.Target.riscv.featureSetHasAny(target.cpu.features, .{ .c, .zca })) .@"2" else .@"4",
473 .thumb,
474 .thumbeb,
475 .csky,
476 .m68k,
477 .msp430,
478 .s390x,
479 .xcore,
480 => .@"2",
481 .arc,
452 .arm,482 .arm,
453 .armeb,483 .armeb,
454 .aarch64,484 .aarch64,
455 .aarch64_be,485 .aarch64_be,
456 .riscv32,486 .hexagon,
457 .riscv64,487 .lanai,
488 .loongarch32,
489 .loongarch64,
490 .mips,
491 .mipsel,
492 .powerpc,
493 .powerpcle,
494 .powerpc64,
495 .powerpc64le,
458 .sparc,496 .sparc,
459 .sparc64,497 .sparc64,
460 => .@"2",498 .xtensa,
499 => .@"4",
500 .bpfel,
501 .bpfeb,
502 .mips64,
503 .mips64el,
504 => .@"8",
505 .ve,
506 => .@"16",
461 else => .@"1",507 else => .@"1",
462 };508 };
463}509}
464510
465pub fn supportsFunctionAlignment(target: std.Target) bool {511pub fn supportsFunctionAlignment(target: std.Target) bool {
466 return switch (target.cpu.arch) {512 return switch (target.cpu.arch) {
467 .wasm32, .wasm64 => false,513 .nvptx,
514 .nvptx64,
515 .spirv,
516 .spirv32,
517 .spirv64,
518 .wasm32,
519 .wasm64,
520 => false,
468 else => true,521 else => true,
469 };522 };
470}523}
test/cases/compile_errors/function_alignment_on_unsupported_target.zig created+7
...@@ -0,0 +1,7 @@
1export fn entry() align(0) void {}
2
3// error
4// backend=stage2
5// target=nvptx-cuda,nvptx64-cuda,spirv-vulkan,spirv32-opencl,spirv64-opencl,wasm32-freestanding,wasm64-freestanding
6//
7// :1:25: error: target does not support function alignment