| 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,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; |
| 26685 | 26681 | ||
| 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 | }, |
| 1028 | 1028 | ||
| 1029 | // represents machine code; not a pointer | 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 | .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 interwork | 461 | if (self.target.cpu.arch.isArmOrThumb()) |
| 462 | try writer.writeAll("-Fi8") // for thumb interwork | ||
| 462 | else if (self.target.cpu.arch == .powerpc64 and | 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 | 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 or | 579 | 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( |
| 1388 | 1388 | ||
| 1389 | log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index }); | 1389 | log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index }); |
| 1390 | 1390 | ||
| 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 | }; | ||
| 1394 | 1396 | ||
| 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() orelse | 2375 | 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)); |
| 2379 | 2382 |
src/link/Elf/ZigObject.zig+5-3| ... | @@ -1271,9 +1271,11 @@ fn updateNavCode( | ... | @@ -1271,9 +1271,11 @@ fn updateNavCode( |
| 1271 | 1271 | ||
| 1272 | log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index }); | 1272 | log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index }); |
| 1273 | 1273 | ||
| 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 | }; | ||
| 1277 | 1279 | ||
| 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( |
| 962 | 962 | ||
| 963 | log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index }); | 963 | log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index }); |
| 964 | 964 | ||
| 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 | }; | ||
| 968 | 970 | ||
| 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 | } |
| 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 | pub fn defaultFunctionAlignment(target: std.Target) Alignment { | 441 | pub 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 | } |
| 449 | 466 | ||
| 467 | /// This function returns 1 if function alignment is not observable or settable. | ||
| 450 | pub fn minFunctionAlignment(target: std.Target) Alignment { | 468 | pub 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 | } |
| 464 | 510 | ||
| 465 | pub fn supportsFunctionAlignment(target: std.Target) bool { | 511 | pub 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 @@ | ||
| 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 | ||