llvm: update riscv floating-point c abi for LLVM 17

This commit is contained in:
Jacob Young 2023-08-13 23:09:55 -04:00 committed by Andrew Kelley
parent d7daf7c203
commit b1b155feac
2 changed files with 43 additions and 4 deletions

View File

@ -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;

View File

@ -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