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
signaturebadge-question-mark 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,...@@ -3331,12 +3331,16 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutableGen *executable,
3331 LLVMPointerType(get_llvm_type(g, wanted_type), 0) : get_llvm_type(g, wanted_type);3331 LLVMPointerType(get_llvm_type(g, wanted_type), 0) : get_llvm_type(g, wanted_type);
3332 return LLVMBuildBitCast(g->builder, value, wanted_type_ref, "");3332 return LLVMBuildBitCast(g->builder, value, wanted_type_ref, "");
3333 } else if (actual_is_ptr) {3333 } else if (actual_is_ptr) {
3334 // A scalar is wanted but we got a pointer
3334 LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, wanted_type), 0);3335 LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, wanted_type), 0);
3335 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, "");3336 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, "");
3336 uint32_t alignment = get_abi_alignment(g, actual_type);3337 uint32_t alignment = get_abi_alignment(g, actual_type);
3337 return gen_load_untyped(g, bitcasted_ptr, alignment, false, "");3338 return gen_load_untyped(g, bitcasted_ptr, alignment, false, "");
3338 } else {3339 } 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, "");
3340 }3344 }
3341}3345}
33423346
src/ir.cpp+12-4
...@@ -28878,8 +28878,11 @@ static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrIn...@@ -28878,8 +28878,11 @@ static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
28878 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))28878 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
28879 return ira->codegen->invalid_inst_gen;28879 return ira->codegen->invalid_inst_gen;
2888028880
28881 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);28881 const bool src_is_ptr = handle_is_ptr(ira->codegen, src_type);
28882 uint64_t src_size_bytes = type_size(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);
28883 if (dest_size_bytes != src_size_bytes) {28886 if (dest_size_bytes != src_size_bytes) {
28884 ir_add_error(ira, source_instr,28887 ir_add_error(ira, source_instr,
28885 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,28888 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...@@ -28888,8 +28891,8 @@ static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
28888 return ira->codegen->invalid_inst_gen;28891 return ira->codegen->invalid_inst_gen;
28889 }28892 }
2889028893
28891 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);28894 const 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);28895 const uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
28893 if (dest_size_bits != src_size_bits) {28896 if (dest_size_bits != src_size_bits) {
28894 ir_add_error(ira, source_instr,28897 ir_add_error(ira, source_instr,
28895 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",28898 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...@@ -28911,6 +28914,11 @@ static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
28911 return result;28914 return result;
28912 }28915 }
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
28914 return ir_build_bit_cast_gen(ira, source_instr, value, dest_type);28922 return ir_build_bit_cast_gen(ira, source_instr, value, dest_type);
28915}28923}
2891628924
test/stage1/behavior/bitcast.zig+7
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const expect = std.testing.expect;3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;
4const maxInt = std.math.maxInt;5const maxInt = std.math.maxInt;
56
6test "@bitCast i32 -> u32" {7test "@bitCast i32 -> u32" {
...@@ -187,3 +188,9 @@ test "triple level result location with bitcast sandwich passed as tuple element...@@ -187,3 +188,9 @@ test "triple level result location with bitcast sandwich passed as tuple element
187 };188 };
188 S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});189 S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
189}190}
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}