| 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,34 +549,6 @@ set(ZIG_STAGE2_SOURCES |
| 549 | src/Value.zig | 549 | src/Value.zig |
| 550 | src/Zcu.zig | 550 | src/Zcu.zig |
| 551 | src/Zcu/PerThread.zig | 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 | src/clang.zig | 552 | src/clang.zig |
| 581 | src/clang_options.zig | 553 | src/clang_options.zig |
| 582 | src/clang_options_data.zig | 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,7 +17,7 @@ const Compilation = @import("../../Compilation.zig"); |
| 17 | const link = @import("../../link.zig"); | 17 | const link = @import("../../link.zig"); |
| 18 | const Air = @import("../../Air.zig"); | 18 | const Air = @import("../../Air.zig"); |
| 19 | const Mir = @import("Mir.zig"); | 19 | const Mir = @import("Mir.zig"); |
| 20 | const abi = @import("abi.zig"); | 20 | const abi = @import("../../codegen/wasm/abi.zig"); |
| 21 | const Alignment = InternPool.Alignment; | 21 | const Alignment = InternPool.Alignment; |
| 22 | const errUnionPayloadOffset = codegen.errUnionPayloadOffset; | 22 | const errUnionPayloadOffset = codegen.errUnionPayloadOffset; |
| 23 | const errUnionErrorOffset = codegen.errUnionErrorOffset; | 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,11 +21,11 @@ const Air = @import("../Air.zig"); |
| 21 | const Value = @import("../Value.zig"); | 21 | const Value = @import("../Value.zig"); |
| 22 | const Type = @import("../Type.zig"); | 22 | const Type = @import("../Type.zig"); |
| 23 | const x86_64_abi = @import("../arch/x86_64/abi.zig"); | 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 | const aarch64_c_abi = @import("aarch64/abi.zig"); | 25 | const aarch64_c_abi = @import("aarch64/abi.zig"); |
| 26 | const arm_c_abi = @import("arm/abi.zig"); | 26 | const arm_c_abi = @import("arm/abi.zig"); |
| 27 | const riscv_c_abi = @import("../arch/riscv64/abi.zig"); | 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 | const dev = @import("../dev.zig"); | 29 | const dev = @import("../dev.zig"); |
| 30 | 30 | ||
| 31 | const target_util = @import("../target.zig"); | 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,7 +31,7 @@ const mem = std.mem; |
| 31 | 31 | ||
| 32 | const Mir = @import("../arch/wasm/Mir.zig"); | 32 | const Mir = @import("../arch/wasm/Mir.zig"); |
| 33 | const CodeGen = @import("../arch/wasm/CodeGen.zig"); | 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 | const Compilation = @import("../Compilation.zig"); | 35 | const Compilation = @import("../Compilation.zig"); |
| 36 | const Dwarf = @import("Dwarf.zig"); | 36 | const Dwarf = @import("Dwarf.zig"); |
| 37 | const InternPool = @import("../InternPool.zig"); | 37 | const InternPool = @import("../InternPool.zig"); |