Commit e6428f9401
Changed files (3)
test
stage1
behavior
src/codegen.cpp
@@ -3331,12 +3331,16 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutableGen *executable,
LLVMPointerType(get_llvm_type(g, wanted_type), 0) : get_llvm_type(g, wanted_type);
return LLVMBuildBitCast(g->builder, value, wanted_type_ref, "");
} else if (actual_is_ptr) {
+ // A scalar is wanted but we got a pointer
LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, wanted_type), 0);
LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, "");
uint32_t alignment = get_abi_alignment(g, actual_type);
return gen_load_untyped(g, bitcasted_ptr, alignment, false, "");
} else {
- zig_unreachable();
+ // A pointer is wanted but we got a scalar
+ assert(actual_type->id == ZigTypeIdPointer);
+ LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, wanted_type), 0);
+ return LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, "");
}
}
src/ir.cpp
@@ -28878,8 +28878,11 @@ static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
return ira->codegen->invalid_inst_gen;
- uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
- uint64_t src_size_bytes = type_size(ira->codegen, src_type);
+ const bool src_is_ptr = handle_is_ptr(ira->codegen, src_type);
+ const bool dest_is_ptr = handle_is_ptr(ira->codegen, dest_type);
+
+ const uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
+ const uint64_t src_size_bytes = type_size(ira->codegen, src_type);
if (dest_size_bytes != src_size_bytes) {
ir_add_error(ira, source_instr,
buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
@@ -28888,8 +28891,8 @@ static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
return ira->codegen->invalid_inst_gen;
}
- uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
- uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
+ const uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
+ const uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
if (dest_size_bits != src_size_bits) {
ir_add_error(ira, source_instr,
buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
@@ -28911,6 +28914,11 @@ static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
return result;
}
+ if (dest_is_ptr && !src_is_ptr) {
+ // Spill the scalar into a local memory location and take its address
+ value = ir_get_ref(ira, source_instr, value, false, false);
+ }
+
return ir_build_bit_cast_gen(ira, source_instr, value, dest_type);
}
test/stage1/behavior/bitcast.zig
@@ -1,6 +1,7 @@
const std = @import("std");
const builtin = @import("builtin");
const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
const maxInt = std.math.maxInt;
test "@bitCast i32 -> u32" {
@@ -187,3 +188,9 @@ test "triple level result location with bitcast sandwich passed as tuple element
};
S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
}
+
+test "bitcast generates a temporary value" {
+ var y = @as(u16, 0x55AA);
+ const x = @bitCast(u16, @bitCast([2]u8, y));
+ expectEqual(y, x);
+}