diff options
| author | Veikka Tuominen <git@vexu.eu> | 2023-01-14 21:42:29 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-14 21:42:29 +0200 |
| commit | bb15e4057c9c8bb22084990de475ab10a44592c0 (patch) | |
| tree | c1dcacddfc3ff184bd924405db0759ae2625280f /src | |
| parent | 18191b80b6381eb41adb4354a243190865801212 (diff) | |
| parent | 0013042cbd539cf7eb463483633e9f7aa2fa8067 (diff) | |
| download | zig-bb15e4057c9c8bb22084990de475ab10a44592c0.tar.gz zig-bb15e4057c9c8bb22084990de475ab10a44592c0.zip | |
Merge pull request #14271 from Vexu/c-abi
float related C ABI fixes
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86_64/abi.zig | 39 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 42 |
2 files changed, 63 insertions, 18 deletions
diff --git a/src/arch/x86_64/abi.zig b/src/arch/x86_64/abi.zig index 54c08e4aa9..35ac3dcb55 100644 --- a/src/arch/x86_64/abi.zig +++ b/src/arch/x86_64/abi.zig @@ -5,7 +5,19 @@ const assert = std.debug.assert; const Register = @import("bits.zig").Register; const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; -pub const Class = enum { integer, sse, sseup, x87, x87up, complex_x87, memory, none, win_i128 }; +pub const Class = enum { + integer, + sse, + sseup, + x87, + x87up, + complex_x87, + memory, + none, + win_i128, + float, + float_combine, +}; pub fn classifyWindows(ty: Type, target: Target) Class { // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017 @@ -112,7 +124,20 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { return result; }, .Float => switch (ty.floatBits(target)) { - 16, 32, 64 => { + 16 => { + if (ctx == .other) { + result[0] = .memory; + } else { + // TODO clang doesn't allow __fp16 as .ret or .arg + result[0] = .sse; + } + return result; + }, + 32 => { + result[0] = .float; + return result; + }, + 64 => { result[0] = .sse; return result; }, @@ -120,11 +145,15 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { // "Arguments of types__float128, _Decimal128 and__m128 are // split into two halves. The least significant ones belong // to class SSE, the most significant one to class SSEUP." + if (ctx == .other) { + result[0] = .memory; + return result; + } result[0] = .sse; result[1] = .sseup; return result; }, - else => { + 80 => { // "The 64-bit mantissa of arguments of type long double // belongs to classX87, the 16-bit exponent plus 6 bytes // of padding belongs to class X87UP." @@ -132,6 +161,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { result[1] = .x87up; return result; }, + else => unreachable, }, .Vector => { const elem_ty = ty.childType(); @@ -238,6 +268,9 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { combine: { // "If both classes are equal, this is the resulting class." if (result[result_i] == field_class[0]) { + if (result[result_i] == .float) { + result[result_i] = .float_combine; + } break :combine; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index bca116f18f..8604c7d7f6 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -10395,7 +10395,12 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool .mips, .mipsel => return false, .x86_64 => switch (target.os.tag) { .windows => return x86_64_abi.classifyWindows(fn_info.return_type, target) == .memory, - else => return x86_64_abi.classifySystemV(fn_info.return_type, target, .ret)[0] == .memory, + else => { + const class = x86_64_abi.classifySystemV(fn_info.return_type, target, .ret); + if (class[0] == .memory) return true; + if (class[0] == .x87 and class[2] != .none) return true; + return false; + }, }, .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, target)[0] == .indirect, .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, target) == .memory, @@ -10469,22 +10474,26 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type { llvm_types_buffer[llvm_types_index] = dg.context.intType(64); llvm_types_index += 1; }, - .sse => { + .sse, .sseup => { llvm_types_buffer[llvm_types_index] = dg.context.doubleType(); llvm_types_index += 1; }, - .sseup => { - llvm_types_buffer[llvm_types_index] = dg.context.doubleType(); + .float => { + llvm_types_buffer[llvm_types_index] = dg.context.floatType(); llvm_types_index += 1; }, - .x87 => { - llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type(); + .float_combine => { + llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2); llvm_types_index += 1; }, - .x87up => { + .x87 => { + if (llvm_types_index != 0 or classes[2] != .none) { + return dg.context.voidType(); + } llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type(); llvm_types_index += 1; }, + .x87up => continue, .complex_x87 => { @panic("TODO"); }, @@ -10689,22 +10698,25 @@ const ParamTypeIterator = struct { llvm_types_buffer[llvm_types_index] = dg.context.intType(64); llvm_types_index += 1; }, - .sse => { + .sse, .sseup => { llvm_types_buffer[llvm_types_index] = dg.context.doubleType(); llvm_types_index += 1; }, - .sseup => { - llvm_types_buffer[llvm_types_index] = dg.context.doubleType(); + .float => { + llvm_types_buffer[llvm_types_index] = dg.context.floatType(); llvm_types_index += 1; }, - .x87 => { - llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type(); + .float_combine => { + llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2); llvm_types_index += 1; }, - .x87up => { - llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type(); - llvm_types_index += 1; + .x87 => { + it.zig_index += 1; + it.llvm_index += 1; + it.byval_attr = true; + return .byref; }, + .x87up => unreachable, .complex_x87 => { @panic("TODO"); }, |
