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
2665826658 if (val.isGenericPoison()) {
2665926659 break :blk null;
2666026660 }
26661 const alignment = 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;
26661 break :blk try sema.validateAlignAllowZero(block, align_src, try val.toUnsignedIntSema(pt));
2666426662 } else if (extra.data.bits.has_align_ref) blk: {
2666526663 const align_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
2666626664 extra_index += 1;
......@@ -26678,9 +26676,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2667826676 error.GenericPoison => break :blk null,
2667926677 else => |e| return e,
2668026678 };
26681 const alignment = 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;
26679 break :blk try sema.validateAlignAllowZero(block, align_src, try align_val.toUnsignedIntSema(pt));
2668426680 } else .none;
2668526681
2668626682 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(
10271027 },
10281028
10291029 // 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
10321032 .simple_type => |t| switch (t) {
10331033 .bool,
src/codegen/llvm.zig+9-2
......@@ -458,10 +458,15 @@ const DataLayoutBuilder = struct {
458458 if (idx != size) try writer.print(":{d}", .{idx});
459459 }
460460 }
461 if (self.target.cpu.arch.isArmOrThumb()) try writer.writeAll("-Fi8") // for thumb interwork
461 if (self.target.cpu.arch.isArmOrThumb())
462 try writer.writeAll("-Fi8") // for thumb interwork
462463 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())
464467 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")
465470 else if (self.target.cpu.arch.isPowerPC())
466471 try writer.writeAll("-Fn32");
467472 if (self.target.cpu.arch != .hexagon) {
......@@ -574,6 +579,8 @@ const DataLayoutBuilder = struct {
574579 self.target.os.tag == .uefi or self.target.os.tag == .windows or
575580 self.target.cpu.arch == .riscv32)
576581 try writer.print("-S{d}", .{stack_abi});
582 if (self.target.cpu.arch.isAARCH64())
583 try writer.writeAll("-Fn32");
577584 switch (self.target.cpu.arch) {
578585 .hexagon, .ve => {
579586 try self.typeAlignment(.vector, 32, 128, 128, true, writer);
src/link/Coff.zig+5-3
......@@ -1388,9 +1388,11 @@ fn updateNavCode(
13881388
13891389 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
13901390
1391 const required_alignment = pt.navAlignment(nav_index).max(
1392 target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result),
1393 );
1391 const target = zcu.navFileScope(nav_index).mod.resolved_target.result;
1392 const required_alignment = switch (pt.navAlignment(nav_index)) {
1393 .none => target_util.defaultFunctionAlignment(target),
1394 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
1395 };
13941396
13951397 const nav_metadata = coff.navs.get(nav_index).?;
13961398 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
23722372 try wip_nav.infoAddrSym(sym_index, 0);
23732373 wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len);
23742374 try diw.writeInt(u32, 0, dwarf.endian);
2375 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse
2376 target_info.defaultFunctionAlignment(file.mod.resolved_target.result).toByteUnits().?);
2375 const target = file.mod.resolved_target.result;
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().?);
23772380 try diw.writeByte(@intFromBool(false));
23782381 try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type));
23792382
src/link/Elf/ZigObject.zig+5-3
......@@ -1271,9 +1271,11 @@ fn updateNavCode(
12711271
12721272 log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index });
12731273
1274 const required_alignment = pt.navAlignment(nav_index).max(
1275 target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result),
1276 );
1274 const target = zcu.navFileScope(nav_index).mod.resolved_target.result;
1275 const required_alignment = switch (pt.navAlignment(nav_index)) {
1276 .none => target_util.defaultFunctionAlignment(target),
1277 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
1278 };
12771279
12781280 const sym = self.symbol(sym_index);
12791281 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
src/link/MachO/ZigObject.zig+5-3
......@@ -962,9 +962,11 @@ fn updateNavCode(
962962
963963 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
964964
965 const required_alignment = pt.navAlignment(nav_index).max(
966 target_util.minFunctionAlignment(zcu.navFileScope(nav_index).mod.resolved_target.result),
967 );
965 const target = zcu.navFileScope(nav_index).mod.resolved_target.result;
966 const required_alignment = switch (pt.navAlignment(nav_index)) {
967 .none => target_util.defaultFunctionAlignment(target),
968 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
969 };
968970
969971 const sect = &macho_file.sections.items(.header)[sect_index];
970972 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 {
436436 }
437437}
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).
440441pub fn defaultFunctionAlignment(target: std.Target) Alignment {
442 // Overrides of the minimum for performance.
441443 return switch (target.cpu.arch) {
442 .arm, .armeb => .@"4",
443 .aarch64, .aarch64_be => .@"4",
444 .sparc, .sparc64 => .@"4",
445 .riscv64 => .@"2",
446 else => .@"1",
444 .csky,
445 .thumb,
446 .thumbeb,
447 .xcore,
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),
447464 };
448465}
449466
467/// This function returns 1 if function alignment is not observable or settable.
450468pub fn minFunctionAlignment(target: std.Target) Alignment {
451469 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,
452482 .arm,
453483 .armeb,
454484 .aarch64,
455485 .aarch64_be,
456 .riscv32,
457 .riscv64,
486 .hexagon,
487 .lanai,
488 .loongarch32,
489 .loongarch64,
490 .mips,
491 .mipsel,
492 .powerpc,
493 .powerpcle,
494 .powerpc64,
495 .powerpc64le,
458496 .sparc,
459497 .sparc64,
460 => .@"2",
498 .xtensa,
499 => .@"4",
500 .bpfel,
501 .bpfeb,
502 .mips64,
503 .mips64el,
504 => .@"8",
505 .ve,
506 => .@"16",
461507 else => .@"1",
462508 };
463509}
464510
465511pub fn supportsFunctionAlignment(target: std.Target) bool {
466512 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,
468521 else => true,
469522 };
470523}
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