commit 3c827be876a39cbe199e5cd7c6e90edef3a090b5 (tree)
parent 4411f9c019f8f41baeacd39be01af9f961df4e4e
Author: Andrew Kelley <andrew@ziglang.org>
Date: Thu, 27 Jan 2022 21:36:43 -0700
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.
Diffstat:
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp
@@ -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:
{