| author | |
| committer | |
| log | 5ae2428d52da3211ee7b1577fe01894dc10f0619 |
| tree | 1cafa007289566834d110de803788c5c9cb8a908 |
| parent | a13f0d40eb0109e993d37ef4be9107a57e821bc9 |
8 files changed, 175 insertions(+), 203 deletions(-)
CMakeLists.txt-28| ... | ... | @@ -549,34 +549,6 @@ set(ZIG_STAGE2_SOURCES |
| 549 | 549 | src/Value.zig |
| 550 | 550 | src/Zcu.zig |
| 551 | 551 | 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 | |
| 580 | 552 | src/clang.zig |
| 581 | 553 | src/clang_options.zig |
| 582 | 554 | src/clang_options_data.zig |
src/arch/mips/abi.zig deleted-84| ... | ... | @@ -1,84 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const Type = @import("../../Type.zig"); | |
| 3 | const Zcu = @import("../../Zcu.zig"); | |
| 4 | const assert = std.debug.assert; | |
| 5 | ||
| 6 | pub const Class = union(enum) { | |
| 7 | memory, | |
| 8 | byval, | |
| 9 | i32_array: u8, | |
| 10 | }; | |
| 11 | ||
| 12 | pub const Context = enum { ret, arg }; | |
| 13 | ||
| 14 | pub 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"); |
| 17 | 17 | const link = @import("../../link.zig"); |
| 18 | 18 | const Air = @import("../../Air.zig"); |
| 19 | 19 | const Mir = @import("Mir.zig"); |
| 20 | const abi = @import("abi.zig"); | |
| 20 | const abi = @import("../../codegen/wasm/abi.zig"); | |
| 21 | 21 | const Alignment = InternPool.Alignment; |
| 22 | 22 | const errUnionPayloadOffset = codegen.errUnionPayloadOffset; |
| 23 | 23 | const 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 | ||
| 7 | const std = @import("std"); | |
| 8 | const Target = std.Target; | |
| 9 | const assert = std.debug.assert; | |
| 10 | ||
| 11 | const Type = @import("../../Type.zig"); | |
| 12 | const 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. | |
| 16 | pub 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. | |
| 23 | pub 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 | ||
| 85 | pub 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"); |
| 21 | 21 | const Value = @import("../Value.zig"); |
| 22 | 22 | const Type = @import("../Type.zig"); |
| 23 | 23 | const x86_64_abi = @import("../arch/x86_64/abi.zig"); |
| 24 | const wasm_c_abi = @import("../arch/wasm/abi.zig"); | |
| 24 | const wasm_c_abi = @import("wasm/abi.zig"); | |
| 25 | 25 | const aarch64_c_abi = @import("aarch64/abi.zig"); |
| 26 | 26 | const arm_c_abi = @import("arm/abi.zig"); |
| 27 | 27 | const riscv_c_abi = @import("../arch/riscv64/abi.zig"); |
| 28 | const mips_c_abi = @import("../arch/mips/abi.zig"); | |
| 28 | const mips_c_abi = @import("mips/abi.zig"); | |
| 29 | 29 | const dev = @import("../dev.zig"); |
| 30 | 30 | |
| 31 | 31 | const target_util = @import("../target.zig"); |
src/codegen/mips/abi.zig created+84| ... | ... | @@ -0,0 +1,84 @@ |
| 1 | const std = @import("std"); | |
| 2 | const Type = @import("../../Type.zig"); | |
| 3 | const Zcu = @import("../../Zcu.zig"); | |
| 4 | const assert = std.debug.assert; | |
| 5 | ||
| 6 | pub const Class = union(enum) { | |
| 7 | memory, | |
| 8 | byval, | |
| 9 | i32_array: u8, | |
| 10 | }; | |
| 11 | ||
| 12 | pub const Context = enum { ret, arg }; | |
| 13 | ||
| 14 | pub 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 | ||
| 7 | const std = @import("std"); | |
| 8 | const Target = std.Target; | |
| 9 | const assert = std.debug.assert; | |
| 10 | ||
| 11 | const Type = @import("../../Type.zig"); | |
| 12 | const 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. | |
| 16 | pub 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. | |
| 23 | pub 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 | ||
| 85 | pub 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; |
| 31 | 31 | |
| 32 | 32 | const Mir = @import("../arch/wasm/Mir.zig"); |
| 33 | 33 | const CodeGen = @import("../arch/wasm/CodeGen.zig"); |
| 34 | const abi = @import("../arch/wasm/abi.zig"); | |
| 34 | const abi = @import("../codegen/wasm/abi.zig"); | |
| 35 | 35 | const Compilation = @import("../Compilation.zig"); |
| 36 | 36 | const Dwarf = @import("Dwarf.zig"); |
| 37 | 37 | const InternPool = @import("../InternPool.zig"); |