authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-04-23 18:44:16+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-04-23 12:44:16-04:00
loge6428f94013132b6a6284b053afb36d35af63c59
tree86275c7d4d6c0729a0905e4e9e2abca1371f1fed
parent58d5c37409a7fc7fea2d6c536bf53c0193c5266a
signature Signed by PGP key 4AEE18F83AFDEB23

stage1: Fix bitcast of immediate to ptr type (#5131)

Consider a (legal according to the `@bitCast` rules) conversion from u16 to [2]u8: since the former is a scalar and the latter is a pointer (arrays are represented at pointers in the codegen phase) we have to allocate a temporary slot on the stack and then bitcast the resulting pointer to the desired destination type. Beware that this means the lifetime of the resulting value is the same of the function it's contained in and for all intents and purposes should be regarded as a local (eg. it should not escape). Closes #4395 Closes #5121

3 files changed, 24 insertions(+), 5 deletions(-)

src/codegen.cpp+5-1
......@@ -3331,12 +3331,16 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutableGen *executable,
33313331 LLVMPointerType(get_llvm_type(g, wanted_type), 0) : get_llvm_type(g, wanted_type);
33323332 return LLVMBuildBitCast(g->builder, value, wanted_type_ref, "");
33333333 } else if (actual_is_ptr) {
3334 // A scalar is wanted but we got a pointer
33343335 LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, wanted_type), 0);
33353336 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, "");
33363337 uint32_t alignment = get_abi_alignment(g, actual_type);
33373338 return gen_load_untyped(g, bitcasted_ptr, alignment, false, "");
33383339 } else {
3339 zig_unreachable();
3340 // A pointer is wanted but we got a scalar
3341 assert(actual_type->id == ZigTypeIdPointer);
3342 LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, wanted_type), 0);
3343 return LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, "");
33403344 }
33413345}
33423346
src/ir.cpp+12-4
......@@ -28878,8 +28878,11 @@ static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
2887828878 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
2887928879 return ira->codegen->invalid_inst_gen;
2888028880
28881 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
28882 uint64_t src_size_bytes = type_size(ira->codegen, src_type);
28881 const bool src_is_ptr = handle_is_ptr(ira->codegen, src_type);
28882 const bool dest_is_ptr = handle_is_ptr(ira->codegen, dest_type);
28883
28884 const uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
28885 const uint64_t src_size_bytes = type_size(ira->codegen, src_type);
2888328886 if (dest_size_bytes != src_size_bytes) {
2888428887 ir_add_error(ira, source_instr,
2888528888 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
2888828891 return ira->codegen->invalid_inst_gen;
2888928892 }
2889028893
28891 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
28892 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
28894 const uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
28895 const uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
2889328896 if (dest_size_bits != src_size_bits) {
2889428897 ir_add_error(ira, source_instr,
2889528898 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
2891128914 return result;
2891228915 }
2891328916
28917 if (dest_is_ptr && !src_is_ptr) {
28918 // Spill the scalar into a local memory location and take its address
28919 value = ir_get_ref(ira, source_instr, value, false, false);
28920 }
28921
2891428922 return ir_build_bit_cast_gen(ira, source_instr, value, dest_type);
2891528923}
2891628924
test/stage1/behavior/bitcast.zig+7
......@@ -1,6 +1,7 @@
11const std = @import("std");
22const builtin = @import("builtin");
33const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;
45const maxInt = std.math.maxInt;
56
67test "@bitCast i32 -> u32" {
......@@ -187,3 +188,9 @@ test "triple level result location with bitcast sandwich passed as tuple element
187188 };
188189 S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
189190}
191
192test "bitcast generates a temporary value" {
193 var y = @as(u16, 0x55AA);
194 const x = @bitCast(u16, @bitCast([2]u8, y));
195 expectEqual(y, x);
196}