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;
55const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
66const 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
1010/// For `float_array` the second element will be the amount of floats.
11pub fn classifyType(ty: Type, target: std.Target) [2]Class {
12 if (!ty.hasRuntimeBitsIgnoreComptime()) return .{ .none, .none };
11pub fn classifyType(ty: Type, target: std.Target) Class {
12 if (!ty.hasRuntimeBitsIgnoreComptime()) return .none;
1313 var maybe_float_bits: ?u16 = null;
1414 switch (ty.zigTypeTag()) {
1515 .Struct => {
16 if (ty.containerLayout() == .Packed) return .{ .integer, .none };
16 if (ty.containerLayout() == .Packed) return .integer;
1717 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
2020 const bit_size = ty.bitSize(target);
21 if (bit_size > 128) return .{ .memory, .none };
22 if (bit_size > 64) return .{ .integer, .integer };
23 return .{ .integer, .none };
21 if (bit_size > 128) return .memory;
22 if (bit_size > 64) return .double_integer;
23 return .integer;
2424 },
2525 .Union => {
26 if (ty.containerLayout() == .Packed) return .{ .integer, .none };
26 if (ty.containerLayout() == .Packed) return .integer;
2727 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
3030 const bit_size = ty.bitSize(target);
31 if (bit_size > 128) return .{ .memory, .none };
32 if (bit_size > 64) return .{ .integer, .integer };
33 return .{ .integer, .none };
31 if (bit_size > 128) return .memory;
32 if (bit_size > 64) return .double_integer;
33 return .integer;
3434 },
35 .Int, .Enum, .ErrorSet, .Vector, .Float, .Bool => return .{ .integer, .none },
36 .Array => return .{ .memory, .none },
35 .Int, .Enum, .ErrorSet, .Vector, .Float, .Bool => return .integer,
3736 .Optional => {
3837 std.debug.assert(ty.isPtrLikeOptional());
39 return .{ .integer, .none };
38 return .integer;
4039 },
4140 .Pointer => {
4241 std.debug.assert(!ty.isSlice());
43 return .{ .integer, .none };
42 return .integer;
4443 },
4544 .ErrorUnion,
4645 .Frame,
......@@ -56,17 +55,18 @@ pub fn classifyType(ty: Type, target: std.Target) [2]Class {
5655 .Fn,
5756 .Opaque,
5857 .EnumLiteral,
58 .Array,
5959 => unreachable,
6060 }
6161}
6262
6363const sret_float_count = 4;
64fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 {
65 const invalid = std.math.maxInt(u32);
64fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 {
65 const invalid = std.math.maxInt(u8);
6666 switch (ty.zigTypeTag()) {
6767 .Union => {
6868 const fields = ty.unionFields();
69 var max_count: u32 = 0;
69 var max_count: u8 = 0;
7070 for (fields.values()) |field| {
7171 const field_count = countFloats(field.ty, target, maybe_float_bits);
7272 if (field_count == invalid) return invalid;
......@@ -77,7 +77,7 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 {
7777 },
7878 .Struct => {
7979 const fields_len = ty.structFieldCount();
80 var count: u32 = 0;
80 var count: u8 = 0;
8181 var i: u32 = 0;
8282 while (i < fields_len) : (i += 1) {
8383 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
1011310113 else => return x86_64_abi.classifySystemV(fn_info.return_type, target)[0] == .memory,
1011410114 },
1011510115 .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,
1011710117 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type, target)) {
1011810118 .memory, .i64_array => return true,
1011910119 .i32_array => |size| return size != 1,
......@@ -10232,19 +10232,15 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
1023210232 if (is_scalar) {
1023310233 return dg.lowerType(fn_info.return_type);
1023410234 }
10235 const classes = aarch64_c_abi.classifyType(fn_info.return_type, target);
10236 if (classes[0] == .memory or classes[0] == .none) {
10237 return dg.context.voidType();
10238 }
10239 if (classes[0] == .float_array) {
10240 return dg.lowerType(fn_info.return_type);
10241 }
10242 if (classes[1] == .none) {
10243 const bit_size = fn_info.return_type.bitSize(target);
10244 return dg.context.intType(@intCast(c_uint, bit_size));
10235 switch (aarch64_c_abi.classifyType(fn_info.return_type, target)) {
10236 .memory, .none => return dg.context.voidType(),
10237 .float_array => return dg.lowerType(fn_info.return_type),
10238 .integer => {
10239 const bit_size = fn_info.return_type.bitSize(target);
10240 return dg.context.intType(@intCast(c_uint, bit_size));
10241 },
10242 .double_integer => return dg.context.intType(64).arrayType(2),
1024510243 }
10246
10247 return dg.context.intType(64).arrayType(2);
1024810244 },
1024910245 .arm, .armeb => {
1025010246 switch (arm_c_abi.classifyType(fn_info.return_type, target)) {
......@@ -10459,21 +10455,17 @@ const ParamTypeIterator = struct {
1045910455 if (is_scalar) {
1046010456 return .byval;
1046110457 }
10462 const classes = aarch64_c_abi.classifyType(ty, it.target);
10463 if (classes[0] == .memory) {
10464 return .byref;
10465 }
10466 if (classes[0] == .float_array) {
10467 return Lowering{ .float_array = @enumToInt(classes[1]) };
10468 }
10469 if (classes[1] == .none) {
10470 it.llvm_types_len = 1;
10471 } else {
10472 it.llvm_types_len = 2;
10458 switch (aarch64_c_abi.classifyType(ty, it.target)) {
10459 .none => unreachable,
10460 .memory => return .byref,
10461 .float_array => |len| return Lowering{ .float_array = len },
10462 .integer => {
10463 it.llvm_types_len = 1;
10464 it.llvm_types_buffer[0] = 64;
10465 return .multiple_llvm_ints;
10466 },
10467 .double_integer => return Lowering{ .i64_array = 2 },
1047310468 }
10474 it.llvm_types_buffer[0] = 64;
10475 it.llvm_types_buffer[1] = 64;
10476 return .multiple_llvm_ints;
1047710469 },
1047810470 .arm, .armeb => {
1047910471 it.zig_index += 1;