fix invalid const bitcast of f80

LLVM bitcast wants integers that match the number of bits. So the const
bitcast has to use an i80, not an i128.

This commit makes the behavior tests fail for me, so it seems I did not
correctly construct the type. But it gets rid of the LLVM segfault.

I noticed that the strategy of memcpy the buf worked if I simply did an
LLVMConstTrunc() on the i128 to make it into an i80 before the
LLVMConstBitCast().

But is that correct in the face of different endianness? I'm not sure.
This commit is contained in:
Andrew Kelley 2022-01-27 21:36:43 -07:00
parent 4411f9c019
commit 3c827be876

View File

@ -8094,10 +8094,18 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n
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));
LLVMTypeRef llvm_i80 = LLVMIntType(80);
LLVMValueRef x;
if (g->is_big_endian) {
x = LLVMConstInt(llvm_i80, const_val->data.x_f80.signExp, false);
x = LLVMConstShl(x, LLVMConstInt(llvm_i80, 64, false));
x = LLVMConstOr(x, LLVMConstInt(llvm_i80, const_val->data.x_f80.signif, false));
} else {
x = LLVMConstInt(llvm_i80, const_val->data.x_f80.signif, false);
x = LLVMConstShl(x, LLVMConstInt(llvm_i80, 16, false));
x = LLVMConstOr(x, LLVMConstInt(llvm_i80, const_val->data.x_f80.signExp, false));
}
return LLVMConstBitCast(x, get_llvm_type(g, type_entry));
}
case 128:
{