authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-21 19:20:48+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-21 20:30:45+03:00
log3981250b84b4eb4a34832e3fa5888aa3442e8a74
tree50066887b2f5d6b926e1b019fdec7843638ba346
parent9ae78a5890602b89113e53884039ba537c7ef6f9

aarch64 C ABI: return union instead of array of two enums

The result is much cleaner and the second element was unused most of the time.

2 files changed, 40 insertions(+), 48 deletions(-)

src/arch/aarch64/abi.zig+21-21
...@@ -5,42 +5,41 @@ const Register = bits.Register;...@@ -5,42 +5,41 @@ const Register = bits.Register;
5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
6const Type = @import("../../type.zig").Type;6const Type = @import("../../type.zig").Type;
77
8pub const Class = enum(u8) { memory, integer, none, float_array, _ };8pub const Class = union(enum) { memory, integer, double_integer, none, float_array: u8 };
99
10/// For `float_array` the second element will be the amount of floats.10/// For `float_array` the second element will be the amount of floats.
11pub fn classifyType(ty: Type, target: std.Target) [2]Class {11pub fn classifyType(ty: Type, target: std.Target) Class {
12 if (!ty.hasRuntimeBitsIgnoreComptime()) return .{ .none, .none };12 if (!ty.hasRuntimeBitsIgnoreComptime()) return .none;
13 var maybe_float_bits: ?u16 = null;13 var maybe_float_bits: ?u16 = null;
14 switch (ty.zigTypeTag()) {14 switch (ty.zigTypeTag()) {
15 .Struct => {15 .Struct => {
16 if (ty.containerLayout() == .Packed) return .{ .integer, .none };16 if (ty.containerLayout() == .Packed) return .integer;
17 const float_count = countFloats(ty, target, &maybe_float_bits);17 const float_count = countFloats(ty, target, &maybe_float_bits);
18 if (float_count <= sret_float_count) return .{ .float_array, @intToEnum(Class, float_count) };18 if (float_count <= sret_float_count) return .{ .float_array = float_count };
1919
20 const bit_size = ty.bitSize(target);20 const bit_size = ty.bitSize(target);
21 if (bit_size > 128) return .{ .memory, .none };21 if (bit_size > 128) return .memory;
22 if (bit_size > 64) return .{ .integer, .integer };22 if (bit_size > 64) return .double_integer;
23 return .{ .integer, .none };23 return .integer;
24 },24 },
25 .Union => {25 .Union => {
26 if (ty.containerLayout() == .Packed) return .{ .integer, .none };26 if (ty.containerLayout() == .Packed) return .integer;
27 const float_count = countFloats(ty, target, &maybe_float_bits);27 const float_count = countFloats(ty, target, &maybe_float_bits);
28 if (float_count <= sret_float_count) return .{ .float_array, @intToEnum(Class, float_count) };28 if (float_count <= sret_float_count) return .{ .float_array = float_count };
2929
30 const bit_size = ty.bitSize(target);30 const bit_size = ty.bitSize(target);
31 if (bit_size > 128) return .{ .memory, .none };31 if (bit_size > 128) return .memory;
32 if (bit_size > 64) return .{ .integer, .integer };32 if (bit_size > 64) return .double_integer;
33 return .{ .integer, .none };33 return .integer;
34 },34 },
35 .Int, .Enum, .ErrorSet, .Vector, .Float, .Bool => return .{ .integer, .none },35 .Int, .Enum, .ErrorSet, .Vector, .Float, .Bool => return .integer,
36 .Array => return .{ .memory, .none },
37 .Optional => {36 .Optional => {
38 std.debug.assert(ty.isPtrLikeOptional());37 std.debug.assert(ty.isPtrLikeOptional());
39 return .{ .integer, .none };38 return .integer;
40 },39 },
41 .Pointer => {40 .Pointer => {
42 std.debug.assert(!ty.isSlice());41 std.debug.assert(!ty.isSlice());
43 return .{ .integer, .none };42 return .integer;
44 },43 },
45 .ErrorUnion,44 .ErrorUnion,
46 .Frame,45 .Frame,
...@@ -56,17 +55,18 @@ pub fn classifyType(ty: Type, target: std.Target) [2]Class {...@@ -56,17 +55,18 @@ pub fn classifyType(ty: Type, target: std.Target) [2]Class {
56 .Fn,55 .Fn,
57 .Opaque,56 .Opaque,
58 .EnumLiteral,57 .EnumLiteral,
58 .Array,
59 => unreachable,59 => unreachable,
60 }60 }
61}61}
6262
63const sret_float_count = 4;63const sret_float_count = 4;
64fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 {64fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 {
65 const invalid = std.math.maxInt(u32);65 const invalid = std.math.maxInt(u8);
66 switch (ty.zigTypeTag()) {66 switch (ty.zigTypeTag()) {
67 .Union => {67 .Union => {
68 const fields = ty.unionFields();68 const fields = ty.unionFields();
69 var max_count: u32 = 0;69 var max_count: u8 = 0;
70 for (fields.values()) |field| {70 for (fields.values()) |field| {
71 const field_count = countFloats(field.ty, target, maybe_float_bits);71 const field_count = countFloats(field.ty, target, maybe_float_bits);
72 if (field_count == invalid) return invalid;72 if (field_count == invalid) return invalid;
...@@ -77,7 +77,7 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 {...@@ -77,7 +77,7 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 {
77 },77 },
78 .Struct => {78 .Struct => {
79 const fields_len = ty.structFieldCount();79 const fields_len = ty.structFieldCount();
80 var count: u32 = 0;80 var count: u8 = 0;
81 var i: u32 = 0;81 var i: u32 = 0;
82 while (i < fields_len) : (i += 1) {82 while (i < fields_len) : (i += 1) {
83 const field_ty = ty.structFieldType(i);83 const field_ty = ty.structFieldType(i);
src/codegen/llvm.zig+19-27
...@@ -10113,7 +10113,7 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool...@@ -10113,7 +10113,7 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool
10113 else => return x86_64_abi.classifySystemV(fn_info.return_type, target)[0] == .memory,10113 else => return x86_64_abi.classifySystemV(fn_info.return_type, target)[0] == .memory,
10114 },10114 },
10115 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, target)[0] == .indirect,10115 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, target)[0] == .indirect,
10116 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, target)[0] == .memory,10116 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, target) == .memory,
10117 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type, target)) {10117 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type, target)) {
10118 .memory, .i64_array => return true,10118 .memory, .i64_array => return true,
10119 .i32_array => |size| return size != 1,10119 .i32_array => |size| return size != 1,
...@@ -10232,19 +10232,15 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {...@@ -10232,19 +10232,15 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10232 if (is_scalar) {10232 if (is_scalar) {
10233 return dg.lowerType(fn_info.return_type);10233 return dg.lowerType(fn_info.return_type);
10234 }10234 }
10235 const classes = aarch64_c_abi.classifyType(fn_info.return_type, target);10235 switch (aarch64_c_abi.classifyType(fn_info.return_type, target)) {
10236 if (classes[0] == .memory or classes[0] == .none) {10236 .memory, .none => return dg.context.voidType(),
10237 return dg.context.voidType();10237 .float_array => return dg.lowerType(fn_info.return_type),
10238 }10238 .integer => {
10239 if (classes[0] == .float_array) {10239 const bit_size = fn_info.return_type.bitSize(target);
10240 return dg.lowerType(fn_info.return_type);10240 return dg.context.intType(@intCast(c_uint, bit_size));
10241 }10241 },
10242 if (classes[1] == .none) {10242 .double_integer => return dg.context.intType(64).arrayType(2),
10243 const bit_size = fn_info.return_type.bitSize(target);
10244 return dg.context.intType(@intCast(c_uint, bit_size));
10245 }10243 }
10246
10247 return dg.context.intType(64).arrayType(2);
10248 },10244 },
10249 .arm, .armeb => {10245 .arm, .armeb => {
10250 switch (arm_c_abi.classifyType(fn_info.return_type, target)) {10246 switch (arm_c_abi.classifyType(fn_info.return_type, target)) {
...@@ -10459,21 +10455,17 @@ const ParamTypeIterator = struct {...@@ -10459,21 +10455,17 @@ const ParamTypeIterator = struct {
10459 if (is_scalar) {10455 if (is_scalar) {
10460 return .byval;10456 return .byval;
10461 }10457 }
10462 const classes = aarch64_c_abi.classifyType(ty, it.target);10458 switch (aarch64_c_abi.classifyType(ty, it.target)) {
10463 if (classes[0] == .memory) {10459 .none => unreachable,
10464 return .byref;10460 .memory => return .byref,
10465 }10461 .float_array => |len| return Lowering{ .float_array = len },
10466 if (classes[0] == .float_array) {10462 .integer => {
10467 return Lowering{ .float_array = @enumToInt(classes[1]) };10463 it.llvm_types_len = 1;
10468 }10464 it.llvm_types_buffer[0] = 64;
10469 if (classes[1] == .none) {10465 return .multiple_llvm_ints;
10470 it.llvm_types_len = 1;10466 },
10471 } else {10467 .double_integer => return Lowering{ .i64_array = 2 },
10472 it.llvm_types_len = 2;
10473 }10468 }
10474 it.llvm_types_buffer[0] = 64;
10475 it.llvm_types_buffer[1] = 64;
10476 return .multiple_llvm_ints;
10477 },10469 },
10478 .arm, .armeb => {10470 .arm, .armeb => {
10479 it.zig_index += 1;10471 it.zig_index += 1;