stage1: add f80 type

This commit is contained in:
Veikka Tuominen
2022-01-19 12:26:30 +02:00
committed by Andrew Kelley
parent 0e6d2184ca
commit a31a749c42
15 changed files with 380 additions and 31 deletions

View File

@@ -142,15 +142,19 @@ include_directories(${CLANG_INCLUDE_DIRS})
# No patches have been applied to SoftFloat-3e
set(EMBEDDED_SOFTFLOAT_SOURCES
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/extF80M_isSignalingNaN.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToExtF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_extF80MToCommonNaN.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNExtF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_add.c"
@@ -170,6 +174,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f16.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f32.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f64.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_extF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32_r_minMag.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i64.c"
@@ -178,6 +183,20 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_add.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_div.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_eq.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_le.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_lt.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_mul.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_rem.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_roundToInt.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_sqrt.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_sub.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f16.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f32.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f64.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_add.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_div.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_eq.c"
@@ -188,9 +207,12 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_roundToInt.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sqrt.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sub.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_extF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f64.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_extF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_f128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_extF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f16.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/i32_to_f128M.c"
@@ -198,6 +220,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addCarryM.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addComplCarryM.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addF128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addExtF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addM.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF16.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF32.c"
@@ -208,12 +231,14 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_approxRecip_1Ks.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare96M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compareNonnormExtF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros16.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros32.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros64.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros8.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_eq128.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_invalidF128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_invalidExtF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_isNaNF128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_le128.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_lt128.c"
@@ -224,7 +249,9 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF32.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF64.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_negXM.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normExtF80SigM.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackMToF128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackMToExtF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF16.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF32.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF64.c"
@@ -235,6 +262,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_remStepMBy32.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToI64.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToUI64.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackMToExtF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackMToF128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF16.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF32.c"
@@ -263,11 +291,14 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF32.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF64.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNExtF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_mulAdd.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_mulAdd.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/softfloat_state.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_f128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_f128M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_extF80M.c"
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_extF80M.c"
)
add_library(embedded_softfloat STATIC ${EMBEDDED_SOFTFLOAT_SOURCES})
if(MSVC)

View File

@@ -7723,6 +7723,7 @@ const primitives = std.ComptimeStringMap(Zir.Inst.Ref, .{
.{ "f16", .f16_type },
.{ "f32", .f32_type },
.{ "f64", .f64_type },
.{ "f80", .f80_type },
.{ "false", .bool_false },
.{ "i16", .i16_type },
.{ "i32", .i32_type },
@@ -8732,6 +8733,7 @@ fn rvalue(
as_ty | @enumToInt(Zir.Inst.Ref.f16_type),
as_ty | @enumToInt(Zir.Inst.Ref.f32_type),
as_ty | @enumToInt(Zir.Inst.Ref.f64_type),
as_ty | @enumToInt(Zir.Inst.Ref.f80_type),
as_ty | @enumToInt(Zir.Inst.Ref.f128_type),
as_ty | @enumToInt(Zir.Inst.Ref.anyopaque_type),
as_ty | @enumToInt(Zir.Inst.Ref.bool_type),

View File

@@ -16950,6 +16950,7 @@ pub fn typeHasOnePossibleValue(
.f16,
.f32,
.f64,
.f80,
.f128,
.c_longdouble,
.comptime_int,
@@ -17227,6 +17228,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
.f16 => return .f16_type,
.f32 => return .f32_type,
.f64 => return .f64_type,
.f80 => return .f80_type,
.f128 => return .f128_type,
.anyopaque => return .anyopaque_type,
.bool => return .bool_type,
@@ -17572,6 +17574,7 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C
.f16,
.f32,
.f64,
.f80,
.f128,
.anyopaque,
.bool,

View File

@@ -1639,6 +1639,7 @@ pub const Inst = struct {
f16_type,
f32_type,
f64_type,
f80_type,
f128_type,
anyopaque_type,
bool_type,
@@ -1809,6 +1810,10 @@ pub const Inst = struct {
.ty = Type.initTag(.type),
.val = Value.initTag(.f64_type),
},
.f80_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.f80_type),
},
.f128_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.f128_type),

View File

@@ -516,6 +516,7 @@ struct ZigValue {
float16_t x_f16;
float x_f32;
double x_f64;
extFloat80_t x_f80;
float128_t x_f128;
bool x_bool;
ConstBoundFnValue x_bound_fn;
@@ -2089,6 +2090,7 @@ struct CodeGen {
ZigType *entry_f16;
ZigType *entry_f32;
ZigType *entry_f64;
ZigType *entry_f80;
ZigType *entry_f128;
ZigType *entry_void;
ZigType *entry_unreachable;

View File

@@ -5647,6 +5647,9 @@ static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val) {
case 16: return hash_combine(hash_val, &const_val->data.x_f16);
case 32: return hash_combine(hash_val, &const_val->data.x_f32);
case 64: return hash_combine(hash_val, &const_val->data.x_f64);
case 80:
hash_val = hash_combine(hash_val, &const_val->data.x_f80.signExp);
return hash_combine(hash_val, &const_val->data.x_f80.signif);
case 128: return hash_combine(hash_val, &const_val->data.x_f128);
default: zig_unreachable();
}
@@ -6325,6 +6328,7 @@ void init_const_float(ZigValue *const_val, ZigType *type, double value) {
case 64:
const_val->data.x_f64 = value;
break;
case 80:
case 128:
// if we need this, we should add a function that accepts a float128_t param
zig_unreachable();
@@ -7218,6 +7222,8 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {
return a->data.x_f32 == b->data.x_f32;
case 64:
return a->data.x_f64 == b->data.x_f64;
case 80:
return extF80M_eq(&a->data.x_f80, &b->data.x_f80);
case 128:
return f128M_eq(&a->data.x_f128, &b->data.x_f128);
default:
@@ -7470,6 +7476,13 @@ void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) {
case 64:
buf_appendf(buf, "%f", const_val->data.x_f64);
return;
case 80: {
float64_t f64_value = extF80M_to_f64(&const_val->data.x_f80);
double double_value;
memcpy(&double_value, &f64_value, sizeof(double));
buf_appendf(buf, "%f", double_value);
return;
}
case 128:
{
const size_t extra_len = 100;

View File

@@ -7692,6 +7692,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n
return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f32);
case 64:
return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f64);
case 80: {
uint64_t buf[2];
memcpy(&buf, &const_val->data.x_f80, 16);
LLVMValueRef as_int = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2, buf);
return LLVMConstBitCast(as_int, get_llvm_type(g, type_entry));
}
case 128:
{
uint64_t buf[2];
@@ -8911,6 +8917,13 @@ static void define_builtin_types(CodeGen *g) {
add_fp_entry(g, "f64", 64, LLVMDoubleType(), &g->builtin_types.entry_f64);
add_fp_entry(g, "f128", 128, LLVMFP128Type(), &g->builtin_types.entry_f128);
if (target_has_f80(g->zig_target)) {
add_fp_entry(g, "f80", 80, LLVMX86FP80Type(), &g->builtin_types.entry_f80);
} else {
// use f128 for correct size and alignment
add_fp_entry(g, "f80", 128, LLVMFP128Type(), &g->builtin_types.entry_f80);
}
switch (g->zig_target->arch) {
case ZigLLVM_x86:
case ZigLLVM_x86_64:

View File

@@ -2688,6 +2688,12 @@ static bool float_has_fraction(ZigValue *const_val) {
return floorf(const_val->data.x_f32) != const_val->data.x_f32;
case 64:
return floor(const_val->data.x_f64) != const_val->data.x_f64;
case 80:
{
extFloat80_t floored;
extF80M_roundToInt(&const_val->data.x_f80, softfloat_round_minMag, false, &floored);
return !extF80M_eq(&floored, &const_val->data.x_f80);
}
case 128:
{
float128_t floored;
@@ -2716,6 +2722,15 @@ static void float_append_buf(Buf *buf, ZigValue *const_val) {
case 64:
buf_appendf(buf, "%f", const_val->data.x_f64);
break;
case 80:
{
float64_t f64_value = extF80M_to_f64(&const_val->data.x_f80);
double double_value;
memcpy(&double_value, &f64_value, sizeof(double));
buf_appendf(buf, "%f", const_val->data.x_f64);
break;
}
case 128:
{
// TODO actual implementation
@@ -2772,6 +2787,15 @@ static void float_init_bigint(BigInt *bigint, ZigValue *const_val) {
bigint->is_negative = true;
}
break;
case 80:
{
float128_t f128_value;
extF80M_to_f128M(&const_val->data.x_f80, &f128_value);
BigFloat tmp_float;
bigfloat_init_128(&tmp_float, f128_value);
bigint_init_bigfloat(bigint, &tmp_float);
}
break;
case 128:
{
BigFloat tmp_float;
@@ -2801,8 +2825,11 @@ static void float_init_bigfloat(ZigValue *dest_val, BigFloat *bigfloat) {
case 64:
dest_val->data.x_f64 = bigfloat_to_f64(bigfloat);
break;
case 80:
zig_panic("TODO: float_init_bigfloat c_longdouble");
case 80: {
float128_t f128_value = bigfloat_to_f128(bigfloat);
f128M_to_extF80M(&f128_value, &dest_val->data.x_f80);
break;
}
case 128:
dest_val->data.x_f128 = bigfloat_to_f128(bigfloat);
break;
@@ -2828,6 +2855,9 @@ static void float_init_f16(ZigValue *dest_val, float16_t x) {
case 64:
dest_val->data.x_f64 = zig_f16_to_double(x);
break;
case 80:
f16_to_extF80M(x, &dest_val->data.x_f80);
break;
case 128:
f16_to_f128M(x, &dest_val->data.x_f128);
break;
@@ -2853,6 +2883,12 @@ static void float_init_f32(ZigValue *dest_val, float x) {
case 64:
dest_val->data.x_f64 = x;
break;
case 80: {
float32_t x_f32;
memcpy(&x_f32, &x, sizeof(float));
f32_to_extF80M(x_f32, &dest_val->data.x_f80);
break;
}
case 128:
{
float32_t x_f32;
@@ -2882,6 +2918,12 @@ static void float_init_f64(ZigValue *dest_val, double x) {
case 64:
dest_val->data.x_f64 = x;
break;
case 80: {
float64_t x_f64;
memcpy(&x_f64, &x, sizeof(double));
f64_to_extF80M(x_f64, &dest_val->data.x_f80);
break;
}
case 128:
{
float64_t x_f64;
@@ -2917,6 +2959,9 @@ static void float_init_f128(ZigValue *dest_val, float128_t x) {
memcpy(&dest_val->data.x_f64, &f64_val, sizeof(double));
break;
}
case 80:
f128M_to_extF80M(&x, &dest_val->data.x_f80);
break;
case 128:
{
memcpy(&dest_val->data.x_f128, &x, sizeof(float128_t));
@@ -2944,6 +2989,12 @@ static void float_init_float(ZigValue *dest_val, ZigValue *src_val) {
case 64:
float_init_f64(dest_val, src_val->data.x_f64);
break;
case 80: {
float128_t f128_value;
extF80M_to_f128M(&src_val->data.x_f80, &f128_value);
float_init_f128(dest_val, f128_value);
break;
}
case 128:
float_init_f128(dest_val, src_val->data.x_f128);
break;
@@ -2966,6 +3017,8 @@ static bool float_is_nan(ZigValue *op) {
return op->data.x_f32 != op->data.x_f32;
case 64:
return op->data.x_f64 != op->data.x_f64;
case 80:
return zig_extF80_isNaN(&op->data.x_f80);
case 128:
return zig_f128_isNaN(&op->data.x_f128);
default:
@@ -3006,6 +3059,14 @@ static Cmp float_cmp(ZigValue *op1, ZigValue *op2) {
} else {
return CmpEQ;
}
case 80:
if (extF80M_lt(&op1->data.x_f80, &op2->data.x_f80)) {
return CmpLT;
} else if (extF80M_eq(&op1->data.x_f80, &op2->data.x_f80)) {
return CmpEQ;
} else {
return CmpGT;
}
case 128:
if (f128M_lt(&op1->data.x_f128, &op2->data.x_f128)) {
return CmpLT;
@@ -3061,7 +3122,18 @@ static Cmp float_cmp_zero(ZigValue *op) {
} else {
return CmpEQ;
}
case 128:
case 80: {
extFloat80_t zero_float;
ui32_to_extF80M(0, &zero_float);
if (extF80M_lt(&op->data.x_f80, &zero_float)) {
return CmpLT;
} else if (extF80M_eq(&op->data.x_f80, &zero_float)) {
return CmpEQ;
} else {
return CmpGT;
}
}
case 128: {
float128_t zero_float;
ui32_to_f128M(0, &zero_float);
if (f128M_lt(&op->data.x_f128, &zero_float)) {
@@ -3071,6 +3143,7 @@ static Cmp float_cmp_zero(ZigValue *op) {
} else {
return CmpGT;
}
}
default:
zig_unreachable();
}
@@ -3095,6 +3168,9 @@ static void float_add(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
case 64:
out_val->data.x_f64 = op1->data.x_f64 + op2->data.x_f64;
return;
case 80:
extF80M_add(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
return;
case 128:
f128M_add(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
return;
@@ -3122,6 +3198,9 @@ static void float_sub(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
case 64:
out_val->data.x_f64 = op1->data.x_f64 - op2->data.x_f64;
return;
case 80:
extF80M_sub(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
return;
case 128:
f128M_sub(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
return;
@@ -3149,6 +3228,9 @@ static void float_mul(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
case 64:
out_val->data.x_f64 = op1->data.x_f64 * op2->data.x_f64;
return;
case 80:
extF80M_mul(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
return;
case 128:
f128M_mul(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
return;
@@ -3176,6 +3258,9 @@ static void float_div(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
case 64:
out_val->data.x_f64 = op1->data.x_f64 / op2->data.x_f64;
return;
case 80:
extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
return;
case 128:
f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
return;
@@ -3204,6 +3289,10 @@ static void float_div_trunc(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
case 64:
out_val->data.x_f64 = trunc(op1->data.x_f64 / op2->data.x_f64);
return;
case 80:
extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
extF80M_roundToInt(&out_val->data.x_f80, softfloat_round_minMag, false, &out_val->data.x_f80);
return;
case 128:
f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
f128M_roundToInt(&out_val->data.x_f128, softfloat_round_minMag, false, &out_val->data.x_f128);
@@ -3233,6 +3322,10 @@ static void float_div_floor(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
case 64:
out_val->data.x_f64 = floor(op1->data.x_f64 / op2->data.x_f64);
return;
case 80:
extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
extF80M_roundToInt(&out_val->data.x_f80, softfloat_round_min, false, &out_val->data.x_f80);
return;
case 128:
f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
f128M_roundToInt(&out_val->data.x_f128, softfloat_round_min, false, &out_val->data.x_f128);
@@ -3261,6 +3354,9 @@ static void float_rem(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
case 64:
out_val->data.x_f64 = fmod(op1->data.x_f64, op2->data.x_f64);
return;
case 80:
extF80M_rem(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
return;
case 128:
f128M_rem(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
return;
@@ -3290,6 +3386,14 @@ static void zig_f128M_mod(const float128_t* a, const float128_t* b, float128_t*
f128M_sub(a, c, c);
}
// c = a - b * trunc(a / b)
static void zig_extF80M_mod(const extFloat80_t* a, const extFloat80_t* b, extFloat80_t* c) {
extF80M_div(a, b, c);
extF80M_roundToInt(c, softfloat_round_min, true, c);
extF80M_mul(b, c, c);
extF80M_sub(a, c, c);
}
static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
assert(op1->type == op2->type);
out_val->type = op1->type;
@@ -3306,6 +3410,9 @@ static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
case 64:
out_val->data.x_f64 = fmod(fmod(op1->data.x_f64, op2->data.x_f64) + op2->data.x_f64, op2->data.x_f64);
return;
case 80:
zig_extF80M_mod(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
return;
case 128:
zig_f128M_mod(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
return;
@@ -3351,6 +3458,15 @@ static void float_max(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
out_val->data.x_f64 = op1->data.x_f64 > op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64;
}
return;
case 80:
if (zig_extF80_isNaN(&op1->data.x_f80)) {
out_val->data.x_f80 = op2->data.x_f80;
} else if (zig_extF80_isNaN(&op2->data.x_f80)) {
out_val->data.x_f80 = op1->data.x_f80;
} else {
out_val->data.x_f80 = extF80M_lt(&op1->data.x_f80, &op2->data.x_f80) ? op2->data.x_f80 : op1->data.x_f80;
}
return;
case 128:
if (zig_f128_isNaN(&op1->data.x_f128)) {
out_val->data.x_f128 = op2->data.x_f128;
@@ -3402,6 +3518,15 @@ static void float_min(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
out_val->data.x_f64 = op1->data.x_f32 < op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64;
}
return;
case 80:
if (zig_extF80_isNaN(&op1->data.x_f80)) {
out_val->data.x_f80 = op2->data.x_f80;
} else if (zig_extF80_isNaN(&op2->data.x_f80)) {
out_val->data.x_f80 = op1->data.x_f80;
} else {
out_val->data.x_f80 = extF80M_lt(&op1->data.x_f80, &op2->data.x_f80) ? op1->data.x_f80 : op2->data.x_f80;
}
return;
case 128:
if (zig_f128_isNaN(&op1->data.x_f128)) {
out_val->data.x_f128 = op2->data.x_f128;
@@ -3434,6 +3559,9 @@ static void float_negate(ZigValue *out_val, ZigValue *op) {
case 64:
out_val->data.x_f64 = -op->data.x_f64;
return;
case 80:
extF80M_neg(&op->data.x_f80, &out_val->data.x_f80);
return;
case 128:
f128M_neg(&op->data.x_f128, &out_val->data.x_f128);
return;
@@ -3462,6 +3590,9 @@ void float_write_ieee597(ZigValue *op, uint8_t *buf, bool target_is_big_endian)
case 64:
memcpy(buf, &op->data.x_f64, 8);
break;
case 80:
memcpy(buf, &op->data.x_f80, 16);
break;
case 128:
memcpy(buf, &op->data.x_f128, 16);
break;
@@ -3511,6 +3642,9 @@ void float_read_ieee597(ZigValue *val, uint8_t *buf, bool target_is_big_endian)
case 64:
memcpy(&val->data.x_f64, ptr, 8);
return;
case 80:
memcpy(&val->data.x_f80, ptr, 16);
return;
case 128:
memcpy(&val->data.x_f128, ptr, 16);
return;
@@ -3538,8 +3672,12 @@ static void value_to_bigfloat(BigFloat *out, ZigValue *val) {
case 64:
bigfloat_init_64(out, val->data.x_f64);
return;
case 80:
zig_panic("TODO: value_to_bigfloat c_longdouble");
case 80: {
float128_t f128_value;
extF80M_to_f128M(&val->data.x_f80, &f128_value);
bigfloat_init_128(out, f128_value);
return;
}
case 128:
bigfloat_init_128(out, val->data.x_f128);
return;
@@ -3628,8 +3766,14 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc
bigfloat_init_64(&orig_bf, tmp);
break;
}
case 80:
zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble");
case 80: {
float128_t tmp = bigfloat_to_f128(&tmp_bf);
extFloat80_t tmp80;
f128M_to_extF80M(&tmp, &tmp80);
extF80M_to_f128M(&tmp80, &tmp);
bigfloat_init_128(&orig_bf, tmp);
break;
}
case 128: {
float128_t tmp = bigfloat_to_f128(&tmp_bf);
bigfloat_init_128(&orig_bf, tmp);
@@ -3673,8 +3817,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc
}
break;
}
case 80:
zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble");
case 80: {
float16_t tmp = extF80M_to_f16(&const_val->data.x_f80);
extFloat80_t orig;
f16_to_extF80M(tmp, &orig);
if (extF80M_eq(&orig, &const_val->data.x_f80)) {
return true;
}
break;
}
case 128: {
float16_t tmp = f128M_to_f16(&const_val->data.x_f128);
float128_t orig;
@@ -3698,8 +3849,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc
}
break;
}
case 80:
zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble");
case 80: {
float32_t tmp = extF80M_to_f32(&const_val->data.x_f80);
extFloat80_t orig;
f32_to_extF80M(tmp, &orig);
if (extF80M_eq(&orig, &const_val->data.x_f80)) {
return true;
}
break;
}
case 128: {
float32_t tmp = f128M_to_f32(&const_val->data.x_f128);
float128_t orig;
@@ -3715,8 +3873,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc
break;
case 64:
switch (const_val->type->data.floating.bit_count) {
case 80:
zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble");
case 80: {
float64_t tmp = extF80M_to_f64(&const_val->data.x_f80);
extFloat80_t orig;
f64_to_extF80M(tmp, &orig);
if (extF80M_eq(&orig, &const_val->data.x_f80)) {
return true;
}
break;
}
case 128: {
float64_t tmp = f128M_to_f64(&const_val->data.x_f128);
float128_t orig;
@@ -3730,9 +3895,17 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc
zig_unreachable();
}
break;
case 80:
case 80: {
assert(const_val->type->data.floating.bit_count == 128);
zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble");
extFloat80_t tmp;
f128M_to_extF80M(&const_val->data.x_f128, &tmp);
float128_t orig;
extF80M_to_f128M(&tmp, &orig);
if (f128M_eq(&orig, &const_val->data.x_f128)) {
return true;
}
break;
}
case 128:
return true;
default:
@@ -5143,8 +5316,11 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, Scope *scope, AstNode
case 64:
const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat);
break;
case 80:
zig_panic("TODO: eval_const_expr_implicit_cast c_longdouble");
case 80: {
float128_t tmp = bigfloat_to_f128(&other_val->data.x_bigfloat);
f128M_to_extF80M(&tmp, &const_val->data.x_f80);
break;
}
case 128:
const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat);
break;
@@ -5172,8 +5348,11 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, Scope *scope, AstNode
case 64:
const_val->data.x_f64 = bigfloat_to_f64(&bigfloat);
break;
case 80:
zig_panic("TODO: eval_const_expr_implicit_cast c_longdouble");
case 80: {
float128_t tmp = bigfloat_to_f128(&other_val->data.x_bigfloat);
f128M_to_extF80M(&tmp, &const_val->data.x_f80);
break;
}
case 128:
const_val->data.x_f128 = bigfloat_to_f128(&bigfloat);
break;
@@ -18960,6 +19139,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
case 16: return ira->codegen->builtin_types.entry_f16;
case 32: return ira->codegen->builtin_types.entry_f32;
case 64: return ira->codegen->builtin_types.entry_f64;
case 80: return ira->codegen->builtin_types.entry_f80;
case 128: return ira->codegen->builtin_types.entry_f128;
}
ir_add_error_node(ira, source_node, buf_sprintf("%d-bit float unsupported", bits));
@@ -21943,6 +22123,8 @@ static void ir_eval_mul_add(IrAnalyze *ira, ZigType *float_type,
case 64:
out_val->data.x_f64 = fma(op1->data.x_f64, op2->data.x_f64, op3->data.x_f64);
break;
case 80:
zig_panic("compiler bug: TODO: implement 'mulAdd' for type 'f80'. See https://github.com/ziglang/zig/issues/4026");
case 128:
f128M_mulAdd(&op1->data.x_f128, &op2->data.x_f128, &op3->data.x_f128, &out_val->data.x_f128);
break;
@@ -24156,10 +24338,44 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_
}
break;
}
case 80:
return ir_add_error_node(ira, source_node,
buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026",
float_op_to_name(fop), buf_ptr(&float_type->name)));
case 80: {
extFloat80_t *out = &out_val->data.x_f80;
extFloat80_t *in = &op->data.x_f80;
switch (fop) {
case BuiltinFnIdSqrt:
extF80M_sqrt(in, out);
break;
case BuiltinFnIdFabs:
extF80M_abs(in, out);
break;
case BuiltinFnIdFloor:
extF80M_roundToInt(in, softfloat_round_min, false, out);
break;
case BuiltinFnIdCeil:
extF80M_roundToInt(in, softfloat_round_max, false, out);
break;
case BuiltinFnIdTrunc:
extF80M_trunc(in, out);
break;
case BuiltinFnIdRound:
extF80M_roundToInt(in, softfloat_round_near_maxMag, false, out);
break;
case BuiltinFnIdNearbyInt:
case BuiltinFnIdSin:
case BuiltinFnIdCos:
case BuiltinFnIdExp:
case BuiltinFnIdExp2:
case BuiltinFnIdLog:
case BuiltinFnIdLog10:
case BuiltinFnIdLog2:
return ir_add_error_node(ira, source_node,
buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026",
float_op_to_name(fop), buf_ptr(&float_type->name)));
default:
zig_unreachable();
}
break;
}
case 128: {
float128_t *out, *in;
if (float_type->id == ZigTypeIdComptimeFloat) {

View File

@@ -56,4 +56,8 @@ static inline bool zig_f128_isNaN(float128_t *aPtr) {
|| ((absA64 == UINT64_C(0x7FFF000000000000)) && lo);
}
static inline bool zig_extF80_isNaN(extFloat80_t *aPtr) {
return aPtr->signExp & 0x7FFF && aPtr->signif;
}
#endif

View File

@@ -28,13 +28,6 @@ void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) {
}
}
float16_t f16_neg(const float16_t a) {
union { uint16_t ui; float16_t f; } uA;
// Toggle the sign bit.
uA.ui = a.v ^ (UINT16_C(1) << 15);
return uA.f;
}
void f128M_neg(const float128_t *aPtr, float128_t *zPtr) {
// Toggle the sign bit.
#if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
@@ -46,4 +39,33 @@ void f128M_neg(const float128_t *aPtr, float128_t *zPtr) {
#else
#error Unsupported endian
#endif
}
}
void extF80M_abs(const extFloat80_t *aPtr, extFloat80_t *zPtr) {
// Clear the sign bit.
zPtr->signExp = aPtr->signExp & UINT16_C(0x7FFF);
zPtr->signif = aPtr->signif;
}
void extF80M_trunc(const extFloat80_t *aPtr, extFloat80_t *zPtr) {
extFloat80_t zero_float;
ui32_to_extF80M(0, &zero_float);
if (extF80M_lt(aPtr, &zero_float)) {
extF80M_roundToInt(aPtr, softfloat_round_max, false, zPtr);
} else {
extF80M_roundToInt(aPtr, softfloat_round_min, false, zPtr);
}
}
void extF80M_neg(const extFloat80_t *aPtr, extFloat80_t *zPtr) {
// Toggle the sign bit.
zPtr->signExp = aPtr->signExp ^ UINT16_C(0x8000);
zPtr->signif = aPtr->signif;
}
float16_t f16_neg(const float16_t a) {
union { uint16_t ui; float16_t f; } uA;
// Toggle the sign bit.
uA.ui = a.v ^ (UINT16_C(1) << 15);
return uA.f;
}

View File

@@ -7,6 +7,10 @@ void f128M_abs(const float128_t *aPtr, float128_t *zPtr);
void f128M_trunc(const float128_t *aPtr, float128_t *zPtr);
void f128M_neg(const float128_t *aPtr, float128_t *zPtr);
void extF80M_abs(const extFloat80_t *aPtr, extFloat80_t *zPtr);
void extF80M_trunc(const extFloat80_t *aPtr, extFloat80_t *zPtr);
void extF80M_neg(const extFloat80_t *aPtr, extFloat80_t *zPtr);
float16_t f16_neg(const float16_t a);
#endif

View File

@@ -1019,6 +1019,17 @@ bool target_long_double_is_f128(const ZigTarget *target) {
}
}
bool target_has_f80(const ZigTarget *target) {
switch (target->arch) {
case ZigLLVM_x86:
case ZigLLVM_x86_64:
return true;
default:
return false;
}
}
bool target_is_riscv(const ZigTarget *target) {
return target->arch == ZigLLVM_riscv32 || target->arch == ZigLLVM_riscv64;
}

View File

@@ -81,6 +81,7 @@ bool target_is_sparc(const ZigTarget *target);
bool target_is_android(const ZigTarget *target);
bool target_has_debug_info(const ZigTarget *target);
bool target_long_double_is_f128(const ZigTarget *target);
bool target_has_f80(const ZigTarget *target);
uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);
uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch);

View File

@@ -58,6 +58,7 @@ pub const Type = extern union {
.f16,
.f32,
.f64,
.f80,
.f128,
.c_longdouble,
=> return .Float,
@@ -833,6 +834,7 @@ pub const Type = extern union {
.f16,
.f32,
.f64,
.f80,
.f128,
.bool,
.void,
@@ -1053,6 +1055,7 @@ pub const Type = extern union {
.f16,
.f32,
.f64,
.f80,
.f128,
.bool,
.void,
@@ -1371,6 +1374,7 @@ pub const Type = extern union {
.f16,
.f32,
.f64,
.f80,
.f128,
.bool,
.void,
@@ -1473,6 +1477,7 @@ pub const Type = extern union {
.f16 => return Value.initTag(.f16_type),
.f32 => return Value.initTag(.f32_type),
.f64 => return Value.initTag(.f64_type),
.f80 => return Value.initTag(.f80_type),
.f128 => return Value.initTag(.f128_type),
.bool => return Value.initTag(.bool_type),
.void => return Value.initTag(.void_type),
@@ -1543,6 +1548,7 @@ pub const Type = extern union {
.f16,
.f32,
.f64,
.f80,
.f128,
.bool,
.anyerror,
@@ -1858,6 +1864,7 @@ pub const Type = extern union {
.f16 => return 2,
.f32 => return 4,
.f64 => return 8,
.f80 => return 16,
.f128 => return 16,
.c_longdouble => return 16,
@@ -2138,6 +2145,7 @@ pub const Type = extern union {
.f16 => return 2,
.f32 => return 4,
.f64 => return 8,
.f80 => return 16,
.f128 => return 16,
.c_longdouble => return 16,
@@ -2277,6 +2285,7 @@ pub const Type = extern union {
.i16, .u16, .f16 => 16,
.i32, .u32, .f32 => 32,
.i64, .u64, .f64 => 64,
.f80 => 80,
.u128, .i128, .f128 => 128,
.isize,
@@ -3170,6 +3179,7 @@ pub const Type = extern union {
.f16,
.f32,
.f64,
.f80,
.f128,
.c_longdouble,
=> true,
@@ -3184,6 +3194,7 @@ pub const Type = extern union {
.f16,
.f32,
.f64,
.f80,
.f128,
.c_longdouble,
.comptime_float,
@@ -3200,6 +3211,7 @@ pub const Type = extern union {
.f16 => 16,
.f32 => 32,
.f64 => 64,
.f80 => 80,
.f128, .comptime_float => 128,
.c_longdouble => CType.longdouble.sizeInBits(target),
@@ -3340,6 +3352,7 @@ pub const Type = extern union {
.f16,
.f32,
.f64,
.f80,
.f128,
.c_longdouble,
.comptime_int,
@@ -3381,6 +3394,7 @@ pub const Type = extern union {
.f16,
.f32,
.f64,
.f80,
.f128,
.c_longdouble,
.comptime_int,
@@ -3579,6 +3593,7 @@ pub const Type = extern union {
.f16,
.f32,
.f64,
.f80,
.f128,
.anyopaque,
.bool,
@@ -4334,6 +4349,7 @@ pub const Type = extern union {
f16,
f32,
f64,
f80,
f128,
anyopaque,
bool,
@@ -4453,6 +4469,7 @@ pub const Type = extern union {
.f16,
.f32,
.f64,
.f80,
.f128,
.anyopaque,
.bool,

View File

@@ -47,6 +47,7 @@ pub const Value = extern union {
f16_type,
f32_type,
f64_type,
f80_type,
f128_type,
anyopaque_type,
bool_type,
@@ -205,6 +206,7 @@ pub const Value = extern union {
.f16_type,
.f32_type,
.f64_type,
.f80_type,
.f128_type,
.anyopaque_type,
.bool_type,
@@ -398,6 +400,7 @@ pub const Value = extern union {
.f16_type,
.f32_type,
.f64_type,
.f80_type,
.f128_type,
.anyopaque_type,
.bool_type,
@@ -630,6 +633,7 @@ pub const Value = extern union {
.f16_type => return out_stream.writeAll("f16"),
.f32_type => return out_stream.writeAll("f32"),
.f64_type => return out_stream.writeAll("f64"),
.f80_type => return out_stream.writeAll("f80"),
.f128_type => return out_stream.writeAll("f128"),
.anyopaque_type => return out_stream.writeAll("anyopaque"),
.bool_type => return out_stream.writeAll("bool"),
@@ -824,6 +828,7 @@ pub const Value = extern union {
.f16_type => Type.initTag(.f16),
.f32_type => Type.initTag(.f32),
.f64_type => Type.initTag(.f64),
.f80_type => Type.initTag(.f80),
.f128_type => Type.initTag(.f128),
.anyopaque_type => Type.initTag(.anyopaque),
.bool_type => Type.initTag(.bool),