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:
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),