| author | |
| committer | |
| log | 03d0e296cb8a8afb2bd81c030b31e96e6e2940c7 |
| tree | f340a6c090dd562ec0d710573d66e1651ced5bd5 |
| parent | 5769592cdda3c14a37b8c381219343052609cbbc |
| parent | 6c1e306484530bfeaf26450fb83a70ff1c323bcd |
| signature |
Some improvements to the compiler's handling of function alignment9 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 | 26658 | if (val.isGenericPoison()) { |
| 26659 | 26659 | break :blk null; |
| 26660 | 26660 | } |
| 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)); | |
| 26664 | 26662 | } else if (extra.data.bits.has_align_ref) blk: { |
| 26665 | 26663 | const align_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); |
| 26666 | 26664 | extra_index += 1; |
| ... | ... | @@ -26678,9 +26676,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 26678 | 26676 | error.GenericPoison => break :blk null, |
| 26679 | 26677 | else => |e| return e, |
| 26680 | 26678 | }; |
| 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)); | |
| 26684 | 26680 | } else .none; |
| 26685 | 26681 | |
| 26686 | 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 | 1027 | }, |
| 1028 | 1028 | |
| 1029 | 1029 | // represents machine code; not a pointer |
| 1030 | .func_type => return .{ .scalar = target_util.defaultFunctionAlignment(target) }, | |
| 1030 | .func_type => return .{ .scalar = target_util.minFunctionAlignment(target) }, | |
| 1031 | 1031 | |
| 1032 | 1032 | .simple_type => |t| switch (t) { |
| 1033 | 1033 | .bool, |
src/codegen/llvm.zig+9-2| ... | ... | @@ -458,10 +458,15 @@ const DataLayoutBuilder = struct { |
| 458 | 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 interwork | |
| 461 | if (self.target.cpu.arch.isArmOrThumb()) | |
| 462 | try writer.writeAll("-Fi8") // for thumb interwork | |
| 462 | 463 | 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 | 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 | 470 | else if (self.target.cpu.arch.isPowerPC()) |
| 466 | 471 | try writer.writeAll("-Fn32"); |
| 467 | 472 | if (self.target.cpu.arch != .hexagon) { |
| ... | ... | @@ -574,6 +579,8 @@ const DataLayoutBuilder = struct { |
| 574 | 579 | self.target.os.tag == .uefi or self.target.os.tag == .windows or |
| 575 | 580 | self.target.cpu.arch == .riscv32) |
| 576 | 581 | try writer.print("-S{d}", .{stack_abi}); |
| 582 | if (self.target.cpu.arch.isAARCH64()) | |
| 583 | try writer.writeAll("-Fn32"); | |
| 577 | 584 | switch (self.target.cpu.arch) { |
| 578 | 585 | .hexagon, .ve => { |
| 579 | 586 | try self.typeAlignment(.vector, 32, 128, 128, true, writer); |
src/link/Coff.zig+5-3| ... | ... | @@ -1388,9 +1388,11 @@ fn updateNavCode( |
| 1388 | 1388 | |
| 1389 | 1389 | log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index }); |
| 1390 | 1390 | |
| 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 | }; | |
| 1394 | 1396 | |
| 1395 | 1397 | const nav_metadata = coff.navs.get(nav_index).?; |
| 1396 | 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 | 2372 | try wip_nav.infoAddrSym(sym_index, 0); |
| 2373 | 2373 | wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len); |
| 2374 | 2374 | 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().?); | |
| 2377 | 2380 | try diw.writeByte(@intFromBool(false)); |
| 2378 | 2381 | try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type)); |
| 2379 | 2382 |
src/link/Elf/ZigObject.zig+5-3| ... | ... | @@ -1271,9 +1271,11 @@ fn updateNavCode( |
| 1271 | 1271 | |
| 1272 | 1272 | log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index }); |
| 1273 | 1273 | |
| 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 | }; | |
| 1277 | 1279 | |
| 1278 | 1280 | const sym = self.symbol(sym_index); |
| 1279 | 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 | 962 | |
| 963 | 963 | log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index }); |
| 964 | 964 | |
| 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 | }; | |
| 968 | 970 | |
| 969 | 971 | const sect = &macho_file.sections.items(.header)[sect_index]; |
| 970 | 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 | 436 | } |
| 437 | 437 | } |
| 438 | 438 | |
| 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). | |
| 440 | 441 | pub fn defaultFunctionAlignment(target: std.Target) Alignment { |
| 442 | // Overrides of the minimum for performance. | |
| 441 | 443 | 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), | |
| 447 | 464 | }; |
| 448 | 465 | } |
| 449 | 466 | |
| 467 | /// This function returns 1 if function alignment is not observable or settable. | |
| 450 | 468 | pub fn minFunctionAlignment(target: std.Target) Alignment { |
| 451 | 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 | 482 | .arm, |
| 453 | 483 | .armeb, |
| 454 | 484 | .aarch64, |
| 455 | 485 | .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, | |
| 458 | 496 | .sparc, |
| 459 | 497 | .sparc64, |
| 460 | => .@"2", | |
| 498 | .xtensa, | |
| 499 | => .@"4", | |
| 500 | .bpfel, | |
| 501 | .bpfeb, | |
| 502 | .mips64, | |
| 503 | .mips64el, | |
| 504 | => .@"8", | |
| 505 | .ve, | |
| 506 | => .@"16", | |
| 461 | 507 | else => .@"1", |
| 462 | 508 | }; |
| 463 | 509 | } |
| 464 | 510 | |
| 465 | 511 | pub fn supportsFunctionAlignment(target: std.Target) bool { |
| 466 | 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 | 521 | else => true, |
| 469 | 522 | }; |
| 470 | 523 | } |
test/cases/compile_errors/function_alignment_on_unsupported_target.zig created+7| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | export 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 |