Commit b1b155feac

Jacob Young <jacobly0@users.noreply.github.com>
2023-08-14 05:09:55
llvm: update riscv floating-point c abi for LLVM 17
1 parent d7daf7c
Changed files (2)
src
arch
riscv64
codegen
src/arch/riscv64/abi.zig
@@ -5,7 +5,7 @@ const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
 const Type = @import("../../type.zig").Type;
 const Module = @import("../../Module.zig");
 
-pub const Class = enum { memory, byval, integer, double_integer };
+pub const Class = enum { memory, byval, integer, double_integer, fields };
 
 pub fn classifyType(ty: Type, mod: *Module) Class {
     const target = mod.getTarget();
@@ -19,6 +19,24 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
                 if (bit_size > max_byval_size) return .memory;
                 return .byval;
             }
+
+            if (std.Target.riscv.featureSetHas(target.cpu.features, .d)) fields: {
+                var any_fp = false;
+                var field_count: usize = 0;
+                for (0..ty.structFieldCount(mod)) |field_index| {
+                    const field_ty = ty.structFieldType(field_index, mod);
+                    if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                    if (field_ty.isRuntimeFloat())
+                        any_fp = true
+                    else if (!field_ty.isAbiInt(mod))
+                        break :fields;
+                    field_count += 1;
+                    if (field_count > 2) break :fields;
+                }
+                std.debug.assert(field_count > 0 and field_count <= 2);
+                if (any_fp) return .fields;
+            }
+
             // TODO this doesn't exactly match what clang produces but its better than nothing
             if (bit_size > max_byval_size) return .memory;
             if (bit_size > max_byval_size / 2) return .double_integer;
src/codegen/llvm.zig
@@ -10674,6 +10674,17 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu
                             return o.builder.structType(.normal, &.{ .i64, .i64 });
                         },
                         .byval => return o.lowerType(return_type),
+                        .fields => {
+                            var types_len: usize = 0;
+                            var types: [8]Builder.Type = undefined;
+                            for (0..return_type.structFieldCount(mod)) |field_index| {
+                                const field_ty = return_type.structFieldType(field_index, mod);
+                                if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                types[types_len] = try o.lowerType(field_ty);
+                                types_len += 1;
+                            }
+                            return o.builder.structType(.normal, types[0..types_len]);
+                        },
                     }
                 },
                 // TODO investigate C ABI for other architectures
@@ -10887,14 +10898,24 @@ const ParamTypeIterator = struct {
                     .riscv32, .riscv64 => {
                         it.zig_index += 1;
                         it.llvm_index += 1;
-                        if (ty.toIntern() == .f16_type) {
-                            return .as_u16;
-                        }
+                        if (ty.toIntern() == .f16_type and
+                            !std.Target.riscv.featureSetHas(target.cpu.features, .d)) return .as_u16;
                         switch (riscv_c_abi.classifyType(ty, mod)) {
                             .memory => return .byref_mut,
                             .byval => return .byval,
                             .integer => return .abi_sized_int,
                             .double_integer => return Lowering{ .i64_array = 2 },
+                            .fields => {
+                                it.types_len = 0;
+                                for (0..ty.structFieldCount(mod)) |field_index| {
+                                    const field_ty = ty.structFieldType(field_index, mod);
+                                    if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                    it.types_buffer[it.types_len] = try it.object.lowerType(field_ty);
+                                    it.types_len += 1;
+                                }
+                                it.llvm_index += it.types_len - 1;
+                                return .multiple_llvm_types;
+                            },
                         }
                     },
                     // TODO investigate C ABI for other architectures