compile-time f32, f64 operations are now correctly lossy

previously we used the bigfloat abstraction to do all
compile-time float math. but runtime code and comptime code
are supposed to get the same result. so now if you add a
f32 to a f32 at compile time it does it with f32 math
instead of the bigfloat. float literals still get the
bigfloat math.

closes #424
This commit is contained in:
Andrew Kelley
2017-08-20 00:33:05 -04:00
parent c73a0c92d0
commit 09bd4a9a86
14 changed files with 808 additions and 110 deletions

View File

@@ -1243,10 +1243,6 @@ static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) {
}
}
static LLVMValueRef bigfloat_to_llvm_const(LLVMTypeRef type_ref, BigFloat *bigfloat) {
return LLVMConstReal(type_ref, bigfloat_to_double(bigfloat));
}
static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_math,
LLVMValueRef val1, LLVMValueRef val2,
TypeTableEntry *type_entry, DivKind div_kind)
@@ -3455,7 +3451,23 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref,
const_val->data.x_pure_err->value, false);
case TypeTableEntryIdFloat:
return bigfloat_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigfloat);
switch (type_entry->data.floating.bit_count) {
case 32:
return LLVMConstReal(type_entry->type_ref, const_val->data.x_f32);
case 64:
return LLVMConstReal(type_entry->type_ref, const_val->data.x_f64);
case 128:
{
// TODO make sure this is correct on big endian targets too
uint8_t buf[16];
memcpy(buf, &const_val->data.x_f128, 16);
LLVMValueRef as_int = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2,
(uint64_t*)buf);
return LLVMConstBitCast(as_int, type_entry->type_ref);
}
default:
zig_unreachable();
}
case TypeTableEntryIdBool:
if (const_val->data.x_bool) {
return LLVMConstAllOnes(LLVMInt1Type());
@@ -3937,8 +3949,11 @@ static void do_code_gen(CodeGen *g) {
// Generate debug info for it but that's it.
ConstExprValue *const_val = var->value;
assert(const_val->special != ConstValSpecialRuntime);
TypeTableEntry *var_type = g->builtin_types.entry_f64;
LLVMValueRef init_val = bigfloat_to_llvm_const(var_type->type_ref, &const_val->data.x_bigfloat);
TypeTableEntry *var_type = g->builtin_types.entry_f128;
ConstExprValue coerced_value;
coerced_value.type = var_type;
coerced_value.data.x_f128 = bigfloat_to_f128(&const_val->data.x_bigfloat);
LLVMValueRef init_val = gen_const_val(g, &coerced_value);
gen_global_var(g, var, init_val, var_type);
continue;
}