authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-06 20:23:40-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-06 20:23:40-07:00
log65b6faa0485253b284f7a63601dc7d0f5858515a
tree33e527cab9dc08c381046ec6199424fc3a6e24dd
parent3bcce5f6d1f48e20dd177a7e440ddea1c451e779

Sema: avoid `@intToFloat` for f80 which breaks on non-x86 targets

Currently Zig lowers `@intToFloat` for f80 incorrectly on non-x86 targets: ``` broken LLVM module found: UIToFP result must be FP or FP vector %62 = uitofp i64 %61 to i128 SIToFP result must be FP or FP vector %66 = sitofp i64 %65 to i128 ``` This happens because on such targets, we use i128 instead of x86_fp80 in order to avoid "LLVM ERROR: Cannot select". `@intToFloat` must be lowered differently to account for this difference as well.

2 files changed, 22 insertions(+), 7 deletions(-)

src/stage1/codegen.cpp+5-2
...@@ -9432,11 +9432,14 @@ static void define_builtin_types(CodeGen *g) {...@@ -9432,11 +9432,14 @@ static void define_builtin_types(CodeGen *g) {
9432 if (target_has_f80(g->zig_target)) {9432 if (target_has_f80(g->zig_target)) {
9433 entry->llvm_type = LLVMX86FP80Type();9433 entry->llvm_type = LLVMX86FP80Type();
9434 } else {9434 } else {
9435 // We use i128 here instead of x86_fp80 because on targets such as arm,
9436 // LLVM will give "ERROR: Cannot select" for any instructions involving
9437 // the x86_fp80 type.
9435 entry->llvm_type = get_int_type(g, false, 128)->llvm_type;9438 entry->llvm_type = get_int_type(g, false, 128)->llvm_type;
9436 }9439 }
9437 entry->size_in_bits = 8 * 16;9440 entry->size_in_bits = 8 * 16;
9438 entry->abi_size = 16;9441 entry->abi_size = 16; // matches LLVMABISizeOfType(LLVMX86FP80Type())
9439 entry->abi_align = 16;9442 entry->abi_align = 16; // matches LLVMABIAlignmentOfType(LLVMX86FP80Type())
9440 buf_init_from_str(&entry->name, "f80");9443 buf_init_from_str(&entry->name, "f80");
9441 entry->data.floating.bit_count = 80;9444 entry->data.floating.bit_count = 80;
94429445
src/value.zig+17-5
...@@ -1120,8 +1120,8 @@ pub const Value = extern union {...@@ -1120,8 +1120,8 @@ pub const Value = extern union {
1120 fn floatReadFromMemory(comptime F: type, target: Target, buffer: []const u8) F {1120 fn floatReadFromMemory(comptime F: type, target: Target, buffer: []const u8) F {
1121 if (F == f80) {1121 if (F == f80) {
1122 // TODO: use std.math.F80Repr?1122 // TODO: use std.math.F80Repr?
1123 const big_int = std.mem.readInt(u128, buffer[0..16], target.cpu.arch.endian());1123 const int = std.mem.readInt(u128, buffer[0..16], target.cpu.arch.endian());
1124 const int = @truncate(u80, big_int);1124 // TODO shouldn't this be a bitcast from u80 to f80 instead of u128 to f80?
1125 return @bitCast(F, int);1125 return @bitCast(F, int);
1126 }1126 }
1127 const Int = @Type(.{ .Int = .{1127 const Int = @Type(.{ .Int = .{
...@@ -1143,8 +1143,18 @@ pub const Value = extern union {...@@ -1143,8 +1143,18 @@ pub const Value = extern union {
11431143
1144 .zero => 0,1144 .zero => 0,
1145 .one => 1,1145 .one => 1,
1146 .int_u64 => @intToFloat(T, val.castTag(.int_u64).?.data),1146 .int_u64 => {
1147 .int_i64 => @intToFloat(T, val.castTag(.int_i64).?.data),1147 if (T == f80) {
1148 @panic("TODO we can't lower this properly on non-x86 llvm backend yet");
1149 }
1150 return @intToFloat(T, val.castTag(.int_u64).?.data);
1151 },
1152 .int_i64 => {
1153 if (T == f80) {
1154 @panic("TODO we can't lower this properly on non-x86 llvm backend yet");
1155 }
1156 return @intToFloat(T, val.castTag(.int_i64).?.data);
1157 },
11481158
1149 .int_big_positive => @floatCast(T, bigIntToFloat(val.castTag(.int_big_positive).?.data, true)),1159 .int_big_positive => @floatCast(T, bigIntToFloat(val.castTag(.int_big_positive).?.data, true)),
1150 .int_big_negative => @floatCast(T, bigIntToFloat(val.castTag(.int_big_negative).?.data, false)),1160 .int_big_negative => @floatCast(T, bigIntToFloat(val.castTag(.int_big_negative).?.data, false)),
...@@ -2202,7 +2212,9 @@ pub const Value = extern union {...@@ -2202,7 +2212,9 @@ pub const Value = extern union {
2202 16 => return Value.Tag.float_16.create(arena, @intToFloat(f16, x)),2212 16 => return Value.Tag.float_16.create(arena, @intToFloat(f16, x)),
2203 32 => return Value.Tag.float_32.create(arena, @intToFloat(f32, x)),2213 32 => return Value.Tag.float_32.create(arena, @intToFloat(f32, x)),
2204 64 => return Value.Tag.float_64.create(arena, @intToFloat(f64, x)),2214 64 => return Value.Tag.float_64.create(arena, @intToFloat(f64, x)),
2205 80 => return Value.Tag.float_80.create(arena, @intToFloat(f80, x)),2215 // We can't lower this properly on non-x86 llvm backends yet
2216 //80 => return Value.Tag.float_80.create(arena, @intToFloat(f80, x)),
2217 80 => @panic("TODO f80 intToFloat"),
2206 128 => return Value.Tag.float_128.create(arena, @intToFloat(f128, x)),2218 128 => return Value.Tag.float_128.create(arena, @intToFloat(f128, x)),
2207 else => unreachable,2219 else => unreachable,
2208 }2220 }