authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-02 15:01:50-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-02 15:01:50-07:00
log5ae2428d52da3211ee7b1577fe01894dc10f0619
tree1cafa007289566834d110de803788c5c9cb8a908
parenta13f0d40eb0109e993d37ef4be9107a57e821bc9

compiler: change canonical path for backend ABI source files


8 files changed, 175 insertions(+), 203 deletions(-)

CMakeLists.txt-28
......@@ -549,34 +549,6 @@ set(ZIG_STAGE2_SOURCES
549549 src/Value.zig
550550 src/Zcu.zig
551551 src/Zcu/PerThread.zig
552 src/arch/riscv64/abi.zig
553 src/arch/riscv64/bits.zig
554 src/arch/riscv64/CodeGen.zig
555 src/arch/riscv64/Emit.zig
556 src/arch/riscv64/encoding.zig
557 src/arch/riscv64/Lower.zig
558 src/arch/riscv64/Mir.zig
559 src/arch/riscv64/mnem.zig
560 src/arch/sparc64/CodeGen.zig
561 src/arch/sparc64/Emit.zig
562 src/arch/sparc64/Mir.zig
563 src/arch/sparc64/abi.zig
564 src/arch/sparc64/bits.zig
565 src/arch/wasm/CodeGen.zig
566 src/arch/wasm/Emit.zig
567 src/arch/wasm/Mir.zig
568 src/arch/wasm/abi.zig
569 src/arch/x86/bits.zig
570 src/arch/x86_64/CodeGen.zig
571 src/arch/x86_64/Disassembler.zig
572 src/arch/x86_64/Emit.zig
573 src/arch/x86_64/Encoding.zig
574 src/arch/x86_64/Lower.zig
575 src/arch/x86_64/Mir.zig
576 src/arch/x86_64/abi.zig
577 src/arch/x86_64/bits.zig
578 src/arch/x86_64/encoder.zig
579 src/arch/x86_64/encodings.zon
580552 src/clang.zig
581553 src/clang_options.zig
582554 src/clang_options_data.zig
src/arch/mips/abi.zig deleted-84
......@@ -1,84 +0,0 @@
1const std = @import("std");
2const Type = @import("../../Type.zig");
3const Zcu = @import("../../Zcu.zig");
4const assert = std.debug.assert;
5
6pub const Class = union(enum) {
7 memory,
8 byval,
9 i32_array: u8,
10};
11
12pub const Context = enum { ret, arg };
13
14pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
15 const target = zcu.getTarget();
16 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
17
18 const max_direct_size = target.ptrBitWidth() * 2;
19 switch (ty.zigTypeTag(zcu)) {
20 .@"struct" => {
21 const bit_size = ty.bitSize(zcu);
22 if (ty.containerLayout(zcu) == .@"packed") {
23 if (bit_size > max_direct_size) return .memory;
24 return .byval;
25 }
26 if (bit_size > max_direct_size) return .memory;
27 // TODO: for bit_size <= 32 using byval is more correct, but that needs inreg argument attribute
28 const count = @as(u8, @intCast(std.mem.alignForward(u64, bit_size, 32) / 32));
29 return .{ .i32_array = count };
30 },
31 .@"union" => {
32 const bit_size = ty.bitSize(zcu);
33 if (ty.containerLayout(zcu) == .@"packed") {
34 if (bit_size > max_direct_size) return .memory;
35 return .byval;
36 }
37 if (bit_size > max_direct_size) return .memory;
38
39 return .byval;
40 },
41 .bool => return .byval,
42 .float => return .byval,
43 .int, .@"enum", .error_set => {
44 return .byval;
45 },
46 .vector => {
47 const elem_type = ty.elemType2(zcu);
48 switch (elem_type.zigTypeTag(zcu)) {
49 .bool, .int => {
50 const bit_size = ty.bitSize(zcu);
51 if (ctx == .ret and bit_size > 128) return .memory;
52 if (bit_size > 512) return .memory;
53 // TODO: byval vector arguments with non power of 2 size need inreg attribute
54 return .byval;
55 },
56 .float => return .memory,
57 else => unreachable,
58 }
59 },
60 .optional => {
61 std.debug.assert(ty.isPtrLikeOptional(zcu));
62 return .byval;
63 },
64 .pointer => {
65 std.debug.assert(!ty.isSlice(zcu));
66 return .byval;
67 },
68 .error_union,
69 .frame,
70 .@"anyframe",
71 .noreturn,
72 .void,
73 .type,
74 .comptime_float,
75 .comptime_int,
76 .undefined,
77 .null,
78 .@"fn",
79 .@"opaque",
80 .enum_literal,
81 .array,
82 => unreachable,
83 }
84}
src/arch/wasm/CodeGen.zig+1-1
......@@ -17,7 +17,7 @@ const Compilation = @import("../../Compilation.zig");
1717const link = @import("../../link.zig");
1818const Air = @import("../../Air.zig");
1919const Mir = @import("Mir.zig");
20const abi = @import("abi.zig");
20const abi = @import("../../codegen/wasm/abi.zig");
2121const Alignment = InternPool.Alignment;
2222const errUnionPayloadOffset = codegen.errUnionPayloadOffset;
2323const errUnionErrorOffset = codegen.errUnionErrorOffset;
src/arch/wasm/abi.zig deleted-87
......@@ -1,87 +0,0 @@
1//! Classifies Zig types to follow the C-ABI for Wasm.
2//! The convention for Wasm's C-ABI can be found at the tool-conventions repo:
3//! https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md
4//! When not targeting the C-ABI, Zig is allowed to do derail from this convention.
5//! Note: Above mentioned document is not an official specification, therefore called a convention.
6
7const std = @import("std");
8const Target = std.Target;
9const assert = std.debug.assert;
10
11const Type = @import("../../Type.zig");
12const Zcu = @import("../../Zcu.zig");
13
14/// Defines how to pass a type as part of a function signature,
15/// both for parameters as well as return values.
16pub const Class = union(enum) {
17 direct: Type,
18 indirect,
19};
20
21/// Classifies a given Zig type to determine how they must be passed
22/// or returned as value within a wasm function.
23pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
24 const ip = &zcu.intern_pool;
25 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
26 switch (ty.zigTypeTag(zcu)) {
27 .int, .@"enum", .error_set => return .{ .direct = ty },
28 .float => return .{ .direct = ty },
29 .bool => return .{ .direct = ty },
30 .vector => return .{ .direct = ty },
31 .array => return .indirect,
32 .optional => {
33 assert(ty.isPtrLikeOptional(zcu));
34 return .{ .direct = ty };
35 },
36 .pointer => {
37 assert(!ty.isSlice(zcu));
38 return .{ .direct = ty };
39 },
40 .@"struct" => {
41 const struct_type = zcu.typeToStruct(ty).?;
42 if (struct_type.layout == .@"packed") {
43 return .{ .direct = ty };
44 }
45 if (struct_type.field_types.len > 1) {
46 // The struct type is non-scalar.
47 return .indirect;
48 }
49 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[0]);
50 const explicit_align = struct_type.fieldAlign(ip, 0);
51 if (explicit_align != .none) {
52 if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))
53 return .indirect;
54 }
55 return classifyType(field_ty, zcu);
56 },
57 .@"union" => {
58 const union_obj = zcu.typeToUnion(ty).?;
59 if (union_obj.flagsUnordered(ip).layout == .@"packed") {
60 return .{ .direct = ty };
61 }
62 const layout = ty.unionGetLayout(zcu);
63 assert(layout.tag_size == 0);
64 if (union_obj.field_types.len > 1) return .indirect;
65 const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
66 return classifyType(first_field_ty, zcu);
67 },
68 .error_union,
69 .frame,
70 .@"anyframe",
71 .noreturn,
72 .void,
73 .type,
74 .comptime_float,
75 .comptime_int,
76 .undefined,
77 .null,
78 .@"fn",
79 .@"opaque",
80 .enum_literal,
81 => unreachable,
82 }
83}
84
85pub fn lowerAsDoubleI64(scalar_ty: Type, zcu: *const Zcu) bool {
86 return scalar_ty.bitSize(zcu) > 64;
87}
src/codegen/llvm.zig+2-2
......@@ -21,11 +21,11 @@ const Air = @import("../Air.zig");
2121const Value = @import("../Value.zig");
2222const Type = @import("../Type.zig");
2323const x86_64_abi = @import("../arch/x86_64/abi.zig");
24const wasm_c_abi = @import("../arch/wasm/abi.zig");
24const wasm_c_abi = @import("wasm/abi.zig");
2525const aarch64_c_abi = @import("aarch64/abi.zig");
2626const arm_c_abi = @import("arm/abi.zig");
2727const riscv_c_abi = @import("../arch/riscv64/abi.zig");
28const mips_c_abi = @import("../arch/mips/abi.zig");
28const mips_c_abi = @import("mips/abi.zig");
2929const dev = @import("../dev.zig");
3030
3131const target_util = @import("../target.zig");
src/codegen/mips/abi.zig created+84
......@@ -0,0 +1,84 @@
1const std = @import("std");
2const Type = @import("../../Type.zig");
3const Zcu = @import("../../Zcu.zig");
4const assert = std.debug.assert;
5
6pub const Class = union(enum) {
7 memory,
8 byval,
9 i32_array: u8,
10};
11
12pub const Context = enum { ret, arg };
13
14pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
15 const target = zcu.getTarget();
16 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
17
18 const max_direct_size = target.ptrBitWidth() * 2;
19 switch (ty.zigTypeTag(zcu)) {
20 .@"struct" => {
21 const bit_size = ty.bitSize(zcu);
22 if (ty.containerLayout(zcu) == .@"packed") {
23 if (bit_size > max_direct_size) return .memory;
24 return .byval;
25 }
26 if (bit_size > max_direct_size) return .memory;
27 // TODO: for bit_size <= 32 using byval is more correct, but that needs inreg argument attribute
28 const count = @as(u8, @intCast(std.mem.alignForward(u64, bit_size, 32) / 32));
29 return .{ .i32_array = count };
30 },
31 .@"union" => {
32 const bit_size = ty.bitSize(zcu);
33 if (ty.containerLayout(zcu) == .@"packed") {
34 if (bit_size > max_direct_size) return .memory;
35 return .byval;
36 }
37 if (bit_size > max_direct_size) return .memory;
38
39 return .byval;
40 },
41 .bool => return .byval,
42 .float => return .byval,
43 .int, .@"enum", .error_set => {
44 return .byval;
45 },
46 .vector => {
47 const elem_type = ty.elemType2(zcu);
48 switch (elem_type.zigTypeTag(zcu)) {
49 .bool, .int => {
50 const bit_size = ty.bitSize(zcu);
51 if (ctx == .ret and bit_size > 128) return .memory;
52 if (bit_size > 512) return .memory;
53 // TODO: byval vector arguments with non power of 2 size need inreg attribute
54 return .byval;
55 },
56 .float => return .memory,
57 else => unreachable,
58 }
59 },
60 .optional => {
61 std.debug.assert(ty.isPtrLikeOptional(zcu));
62 return .byval;
63 },
64 .pointer => {
65 std.debug.assert(!ty.isSlice(zcu));
66 return .byval;
67 },
68 .error_union,
69 .frame,
70 .@"anyframe",
71 .noreturn,
72 .void,
73 .type,
74 .comptime_float,
75 .comptime_int,
76 .undefined,
77 .null,
78 .@"fn",
79 .@"opaque",
80 .enum_literal,
81 .array,
82 => unreachable,
83 }
84}
src/codegen/wasm/abi.zig created+87
......@@ -0,0 +1,87 @@
1//! Classifies Zig types to follow the C-ABI for Wasm.
2//! The convention for Wasm's C-ABI can be found at the tool-conventions repo:
3//! https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md
4//! When not targeting the C-ABI, Zig is allowed to do derail from this convention.
5//! Note: Above mentioned document is not an official specification, therefore called a convention.
6
7const std = @import("std");
8const Target = std.Target;
9const assert = std.debug.assert;
10
11const Type = @import("../../Type.zig");
12const Zcu = @import("../../Zcu.zig");
13
14/// Defines how to pass a type as part of a function signature,
15/// both for parameters as well as return values.
16pub const Class = union(enum) {
17 direct: Type,
18 indirect,
19};
20
21/// Classifies a given Zig type to determine how they must be passed
22/// or returned as value within a wasm function.
23pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
24 const ip = &zcu.intern_pool;
25 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
26 switch (ty.zigTypeTag(zcu)) {
27 .int, .@"enum", .error_set => return .{ .direct = ty },
28 .float => return .{ .direct = ty },
29 .bool => return .{ .direct = ty },
30 .vector => return .{ .direct = ty },
31 .array => return .indirect,
32 .optional => {
33 assert(ty.isPtrLikeOptional(zcu));
34 return .{ .direct = ty };
35 },
36 .pointer => {
37 assert(!ty.isSlice(zcu));
38 return .{ .direct = ty };
39 },
40 .@"struct" => {
41 const struct_type = zcu.typeToStruct(ty).?;
42 if (struct_type.layout == .@"packed") {
43 return .{ .direct = ty };
44 }
45 if (struct_type.field_types.len > 1) {
46 // The struct type is non-scalar.
47 return .indirect;
48 }
49 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[0]);
50 const explicit_align = struct_type.fieldAlign(ip, 0);
51 if (explicit_align != .none) {
52 if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))
53 return .indirect;
54 }
55 return classifyType(field_ty, zcu);
56 },
57 .@"union" => {
58 const union_obj = zcu.typeToUnion(ty).?;
59 if (union_obj.flagsUnordered(ip).layout == .@"packed") {
60 return .{ .direct = ty };
61 }
62 const layout = ty.unionGetLayout(zcu);
63 assert(layout.tag_size == 0);
64 if (union_obj.field_types.len > 1) return .indirect;
65 const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
66 return classifyType(first_field_ty, zcu);
67 },
68 .error_union,
69 .frame,
70 .@"anyframe",
71 .noreturn,
72 .void,
73 .type,
74 .comptime_float,
75 .comptime_int,
76 .undefined,
77 .null,
78 .@"fn",
79 .@"opaque",
80 .enum_literal,
81 => unreachable,
82 }
83}
84
85pub fn lowerAsDoubleI64(scalar_ty: Type, zcu: *const Zcu) bool {
86 return scalar_ty.bitSize(zcu) > 64;
87}
src/link/Wasm.zig+1-1
......@@ -31,7 +31,7 @@ const mem = std.mem;
3131
3232const Mir = @import("../arch/wasm/Mir.zig");
3333const CodeGen = @import("../arch/wasm/CodeGen.zig");
34const abi = @import("../arch/wasm/abi.zig");
34const abi = @import("../codegen/wasm/abi.zig");
3535const Compilation = @import("../Compilation.zig");
3636const Dwarf = @import("Dwarf.zig");
3737const InternPool = @import("../InternPool.zig");