From 81650f485c8cafbb6f06d43e90236f34c53175cf Mon Sep 17 00:00:00 2001 From: khyperia Date: Sat, 29 Aug 2020 18:10:01 +0200 Subject: [PATCH] Make to_immediate/from_immediate configurable by backends librustc_codegen_ssa has the concept of an immediate vs. memory type, and librustc_codegen_llvm uses this distinction to implement bools being i8 in memory, and i1 in immediate contexts. However, some of that implementation leaked into codegen_ssa when converting to/from immediate values. So, move those methods into builder traits, so that behavior can be configured by backends. This is useful if a backend is able to keep bools as bools, or, needs to do more trickery than just bools to bytes. --- src/librustc_codegen_llvm/builder.rs | 19 +++++++-- src/librustc_codegen_llvm/intrinsic.rs | 4 +- src/librustc_codegen_ssa/base.rs | 33 +-------------- src/librustc_codegen_ssa/mir/block.rs | 2 +- src/librustc_codegen_ssa/mir/operand.rs | 48 +++++++++------------- src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- src/librustc_codegen_ssa/traits/builder.rs | 14 ++++++- 7 files changed, 54 insertions(+), 68 deletions(-) diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 4ece08f6293..89c3e21632e 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -6,7 +6,6 @@ use crate::type_of::LayoutLlvmExt; use crate::value::Value; use libc::{c_char, c_uint}; -use rustc_codegen_ssa::base::to_immediate; use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, TypeKind}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; @@ -367,6 +366,20 @@ fn checked_binop( (self.extract_value(res, 0), self.extract_value(res, 1)) } + fn from_immediate(&mut self, val: Self::Value) -> Self::Value { + if self.cx().val_ty(val) == self.cx().type_i1() { + self.zext(val, self.cx().type_i8()) + } else { + val + } + } + fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &abi::Scalar) -> Self::Value { + if scalar.is_bool() { + return self.trunc(val, self.cx().type_i1()); + } + val + } + fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value { let mut bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) }); @@ -471,7 +484,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>( } load }); - OperandValue::Immediate(to_immediate(self, llval, place.layout)) + OperandValue::Immediate(self.to_immediate(llval, place.layout)) } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi { let b_offset = a.value.size(self).align_to(b.value.align(self).abi); @@ -479,7 +492,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>( let llptr = self.struct_gep(place.llval, i as u64); let load = self.load(llptr, align); scalar_load_metadata(self, load, scalar); - if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load } + self.to_immediate_scalar(load, scalar) }; OperandValue::Pair( diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index c1dfb83b135..951b9928cc9 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -8,7 +8,7 @@ use crate::value::Value; use rustc_ast as ast; -use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh}; +use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh}; use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::glue; @@ -301,7 +301,7 @@ fn codegen_intrinsic_call( unsafe { llvm::LLVMSetAlignment(load, align); } - to_immediate(self, load, self.layout_of(tp_ty)) + self.to_immediate(load, self.layout_of(tp_ty)) } sym::volatile_store => { let dst = args[0].deref(self.cx()); diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 77c12c410d5..e0b649d91c7 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -38,7 +38,7 @@ use rustc_middle::middle::cstore::{self, LinkagePreference}; use rustc_middle::middle::lang_items; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; -use rustc_middle::ty::layout::{self, HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; @@ -48,7 +48,7 @@ use rustc_session::Session; use rustc_span::Span; use rustc_symbol_mangling::test as symbol_names_test; -use rustc_target::abi::{Abi, Align, LayoutOf, Scalar, VariantIdx}; +use rustc_target::abi::{Align, LayoutOf, VariantIdx}; use std::cmp; use std::ops::{Deref, DerefMut}; @@ -330,35 +330,6 @@ pub fn wants_msvc_seh(sess: &Session) -> bool { sess.target.target.options.is_like_msvc } -pub fn from_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - bx: &mut Bx, - val: Bx::Value, -) -> Bx::Value { - if bx.cx().val_ty(val) == bx.cx().type_i1() { bx.zext(val, bx.cx().type_i8()) } else { val } -} - -pub fn to_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - bx: &mut Bx, - val: Bx::Value, - layout: layout::TyAndLayout<'_>, -) -> Bx::Value { - if let Abi::Scalar(ref scalar) = layout.abi { - return to_immediate_scalar(bx, val, scalar); - } - val -} - -pub fn to_immediate_scalar<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - bx: &mut Bx, - val: Bx::Value, - scalar: &Scalar, -) -> Bx::Value { - if scalar.is_bool() { - return bx.trunc(val, bx.cx().type_i1()); - } - val -} - pub fn memcpy_ty<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, dst: Bx::Value, diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 8048a569f79..6eb80157239 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -1143,7 +1143,7 @@ fn codegen_argument( } } // We store bools as `i8` so we need to truncate to `i1`. - llval = base::to_immediate(bx, llval, arg.layout); + llval = bx.to_immediate(llval, arg.layout); } } diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 937c7457c63..fb84e914661 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -147,8 +147,8 @@ pub fn immediate_or_packed_pair>( debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", self, llty); // Reconstruct the immediate aggregate. let mut llpair = bx.cx().const_undef(llty); - let imm_a = base::from_immediate(bx, a); - let imm_b = base::from_immediate(bx, b); + let imm_a = bx.from_immediate(a); + let imm_b = bx.from_immediate(b); llpair = bx.insert_value(llpair, imm_a, 0); llpair = bx.insert_value(llpair, imm_b, 1); llpair @@ -168,9 +168,9 @@ pub fn from_immediate_or_packed_pair>( // Deconstruct the immediate aggregate. let a_llval = bx.extract_value(llval, 0); - let a_llval = base::to_immediate_scalar(bx, a_llval, a); + let a_llval = bx.to_immediate_scalar(a_llval, a); let b_llval = bx.extract_value(llval, 1); - let b_llval = base::to_immediate_scalar(bx, b_llval, b); + let b_llval = bx.to_immediate_scalar(b_llval, b); OperandValue::Pair(a_llval, b_llval) } else { OperandValue::Immediate(llval) @@ -220,29 +220,21 @@ pub fn extract_field>( _ => bug!("OperandRef::extract_field({:?}): not applicable", self), }; - // 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 { bx.bitcast(val, ty) } - }; - - match val { - OperandValue::Immediate(ref mut llval) => { - *llval = to_immediate_or_cast(bx, *llval, bx.cx().immediate_backend_type(field)); + match (&mut val, &self.layout.abi) { + (OperandValue::Immediate(llval), _) => { + // Bools in union fields needs to be truncated. + *llval = bx.to_immediate(*llval, field); + // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. + *llval = bx.bitcast(*llval, bx.cx().immediate_backend_type(field)); } - OperandValue::Pair(ref mut a, ref mut b) => { - *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::Pair(a, b), Abi::ScalarPair(a_abi, b_abi)) => { + *a = bx.to_immediate_scalar(*a, a_abi); + *a = bx.bitcast(*a, bx.cx().scalar_pair_element_backend_type(field, 0, true)); + *b = bx.to_immediate_scalar(*b, b_abi); + *b = bx.bitcast(*b, bx.cx().scalar_pair_element_backend_type(field, 1, true)); } - OperandValue::Ref(..) => bug!(), + (OperandValue::Pair(..), _) => bug!(), + (OperandValue::Ref(..), _) => bug!(), } OperandRef { val, layout: field } @@ -302,7 +294,7 @@ fn store_with_flags>( bug!("cannot directly store unsized values"); } OperandValue::Immediate(s) => { - let val = base::from_immediate(bx, s); + let val = bx.from_immediate(s); bx.store_with_flags(val, dest.llval, dest.align, flags); } OperandValue::Pair(a, b) => { @@ -313,12 +305,12 @@ fn store_with_flags>( let b_offset = a_scalar.value.size(bx).align_to(b_scalar.value.align(bx).abi); let llptr = bx.struct_gep(dest.llval, 0); - let val = base::from_immediate(bx, a); + let val = bx.from_immediate(a); let align = dest.align; bx.store_with_flags(val, llptr, align, flags); let llptr = bx.struct_gep(dest.llval, 1); - let val = base::from_immediate(bx, b); + let val = bx.from_immediate(b); let align = dest.align.restrict_for_offset(b_offset); bx.store_with_flags(val, llptr, align, flags); } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 71f924df119..1994c45707c 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -98,7 +98,7 @@ pub fn codegen_rvalue( } // Use llvm.memset.p0i8.* to initialize byte arrays - let v = base::from_immediate(&mut bx, v); + let v = bx.from_immediate(v); if bx.cx().val_ty(v) == bx.cx().type_i8() { bx.memset(start, v, size, dest.align, MemFlags::empty()); return bx; diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 5ffc83c5f99..5142922260a 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -13,9 +13,9 @@ use crate::mir::place::PlaceRef; use crate::MemFlags; -use rustc_middle::ty::layout::HasParamEnv; +use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout}; use rustc_middle::ty::Ty; -use rustc_target::abi::{Align, Size}; +use rustc_target::abi::{Abi, Align, Scalar, Size}; use rustc_target::spec::HasTargetSpec; use std::iter::TrustedLen; @@ -115,6 +115,16 @@ fn checked_binop( rhs: Self::Value, ) -> (Self::Value, Self::Value); + fn from_immediate(&mut self, val: Self::Value) -> Self::Value; + fn to_immediate(&mut self, val: Self::Value, layout: TyAndLayout<'_>) -> Self::Value { + if let Abi::Scalar(ref scalar) = layout.abi { + self.to_immediate_scalar(val, scalar) + } else { + val + } + } + fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &Scalar) -> Self::Value; + fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; fn array_alloca(&mut self, ty: Self::Type, len: Self::Value, align: Align) -> Self::Value; -- GitLab