From 86d41350c790502d3a1227bab3433ac7472ccb4c Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 20 Nov 2018 12:14:53 +0100 Subject: [PATCH 1/2] Fix invalid bitcast taking bool out of a union represented as a scalar As reported in https://github.com/rust-lang/rust/pull/54668#issuecomment-440186476 --- src/librustc_codegen_ssa/mir/operand.rs | 14 +++++++++++--- src/test/codegen/union-abi.rs | 6 ++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index d574d89d67e32..859047f54917d 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -243,14 +243,22 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { _ => bug!("OperandRef::extract_field({:?}): not applicable", self) }; + let bitcast = |bx: &mut Bx, val, ty| { + if ty == bx.cx().type_i1() { + bx.trunc(val, ty) + } else { + bx.bitcast(val, ty) + } + }; + // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. match val { OperandValue::Immediate(ref mut llval) => { - *llval = bx.bitcast(*llval, bx.cx().immediate_backend_type(field)); + *llval = bitcast(bx, *llval, bx.cx().immediate_backend_type(field)); } OperandValue::Pair(ref mut a, ref mut b) => { - *a = bx.bitcast(*a, bx.cx().scalar_pair_element_backend_type(field, 0, true)); - *b = bx.bitcast(*b, bx.cx().scalar_pair_element_backend_type(field, 1, true)); + *a = bitcast(bx, *a, bx.cx().scalar_pair_element_backend_type(field, 0, true)); + *b = bitcast(bx, *b, bx.cx().scalar_pair_element_backend_type(field, 1, true)); } OperandValue::Ref(..) => bug!() } diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs index 786968128ec1b..5a6df52502eb5 100644 --- a/src/test/codegen/union-abi.rs +++ b/src/test/codegen/union-abi.rs @@ -78,3 +78,9 @@ pub union CUnionU128{a:u128} #[no_mangle] pub fn test_CUnionU128(_: CUnionU128) { loop {} } +pub union UnionBool { b:bool } +// CHECK: define zeroext i1 @test_UnionBool(i8 %b) +#[no_mangle] +pub fn test_UnionBool(b: UnionBool) -> bool { unsafe { b.b } } +// CHECK: %0 = trunc i8 %b to i1 + From 4c21f66c1dffefa0dbeec3e409aa77630cb9a448 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 20 Nov 2018 13:24:41 +0100 Subject: [PATCH 2/2] Add comments and rename a local variable --- src/librustc_codegen_ssa/mir/operand.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 859047f54917d..a91e9318471aa 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -243,7 +243,9 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { _ => bug!("OperandRef::extract_field({:?}): not applicable", self) }; - let bitcast = |bx: &mut Bx, val, ty| { + // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. + // Bools in union fields needs to be truncated. + let to_immediate_or_cast = |bx: &mut Bx, val, ty| { if ty == bx.cx().type_i1() { bx.trunc(val, ty) } else { @@ -251,14 +253,15 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { } }; - // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. match val { OperandValue::Immediate(ref mut llval) => { - *llval = bitcast(bx, *llval, bx.cx().immediate_backend_type(field)); + *llval = to_immediate_or_cast(bx, *llval, bx.cx().immediate_backend_type(field)); } OperandValue::Pair(ref mut a, ref mut b) => { - *a = bitcast(bx, *a, bx.cx().scalar_pair_element_backend_type(field, 0, true)); - *b = bitcast(bx, *b, bx.cx().scalar_pair_element_backend_type(field, 1, true)); + *a = to_immediate_or_cast(bx, *a, bx.cx() + .scalar_pair_element_backend_type(field, 0, true)); + *b = to_immediate_or_cast(bx, *b, bx.cx() + .scalar_pair_element_backend_type(field, 1, true)); } OperandValue::Ref(..) => bug!() }