zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit b92e1ab8ccf4e450467dfd5ee8ff9ea87c148c26 (tree)
parent d72f832b1ebab0db106e64bc9f59eba90c414311
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Thu, 10 Feb 2022 23:51:09 -0700

stage1: override f80 alignment for i386-windows

Comment reproduced here:

Note the following u64 alignments:
  x86-linux:   4
  x86-windows: 8
LLVM makes x86_fp80 have the following alignment and sizes regardless
of operating system:
  x86_64: size=16, align=16
  x86:    size=12, align=4
However in Zig we override x86-windows to have size=16, align=16
in order for the property to hold that u80 and f80 have the same ABI size.

Fixes "error: destination type 'f80' has size 12 but source type 'u80'
has size 16" when trying to bitcast between f80 and u80 on i386-windows.

Diffstat:
Msrc/stage1/codegen.cpp | 47+++++++++++++++++++++++++++++------------------
1 file changed, 29 insertions(+), 18 deletions(-)

diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp @@ -9432,29 +9432,40 @@ static void define_builtin_types(CodeGen *g) { buf_init_from_str(&entry->name, "f80"); entry->data.floating.bit_count = 80; - switch (g->zig_target->arch) { - case ZigLLVM_x86_64: - entry->llvm_type = LLVMX86FP80Type(); + if (target_has_f80(g->zig_target)) { + entry->llvm_type = LLVMX86FP80Type(); + + // Note the following u64 alignments: + // x86-linux: 4 + // x86-windows: 8 + // LLVM makes x86_fp80 have the following alignment and sizes regardless + // of operating system: + // x86_64: size=16, align=16 + // x86: size=12, align=4 + // However in Zig we override x86-windows to have size=16, align=16 + // in order for the property to hold that u80 and f80 have the same ABI size. + unsigned u64_alignment = LLVMABIAlignmentOfType(g->target_data_ref, LLVMInt64Type()); + + if (u64_alignment >= 8) { entry->abi_size = 16; entry->abi_align = 16; - break; - case ZigLLVM_x86: - entry->llvm_type = LLVMX86FP80Type(); + } else if (u64_alignment >= 4) { entry->abi_size = 12; entry->abi_align = 4; - break; - default: { - // We use an int here instead of x86_fp80 because on targets such as arm, - // LLVM will give "ERROR: Cannot select" for any instructions involving - // the x86_fp80 type. - ZigType *u80_ty = get_int_type(g, false, 80); - assert(!target_has_f80(g->zig_target)); - assert(u80_ty->size_in_bits == entry->size_in_bits); - entry->llvm_type = get_llvm_type(g, u80_ty); - entry->abi_size = u80_ty->abi_size; - entry->abi_align = u80_ty->abi_align; - break; + } else { + entry->abi_size = 10; + entry->abi_align = u64_alignment; } + } else { + // We use an int here instead of x86_fp80 because on targets such as arm, + // LLVM will give "ERROR: Cannot select" for any instructions involving + // the x86_fp80 type. + ZigType *u80_ty = get_int_type(g, false, 80); + assert(!target_has_f80(g->zig_target)); + assert(u80_ty->size_in_bits == entry->size_in_bits); + entry->llvm_type = get_llvm_type(g, u80_ty); + entry->abi_size = u80_ty->abi_size; + entry->abi_align = u80_ty->abi_align; } entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),