提交 81650f48 编写于 作者: K khyperia

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.
上级 286a346d
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
use crate::type_of::LayoutLlvmExt; use crate::type_of::LayoutLlvmExt;
use crate::value::Value; use crate::value::Value;
use libc::{c_char, c_uint}; 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::common::{IntPredicate, RealPredicate, TypeKind};
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::mir::place::PlaceRef;
...@@ -367,6 +366,20 @@ fn checked_binop( ...@@ -367,6 +366,20 @@ fn checked_binop(
(self.extract_value(res, 0), self.extract_value(res, 1)) (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 { fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
let mut bx = Builder::with_cx(self.cx); let mut bx = Builder::with_cx(self.cx);
bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) }); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) });
...@@ -471,7 +484,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>( ...@@ -471,7 +484,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
} }
load 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 { } 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); 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>( ...@@ -479,7 +492,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
let llptr = self.struct_gep(place.llval, i as u64); let llptr = self.struct_gep(place.llval, i as u64);
let load = self.load(llptr, align); let load = self.load(llptr, align);
scalar_load_metadata(self, load, scalar); 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( OperandValue::Pair(
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
use crate::value::Value; use crate::value::Value;
use rustc_ast as ast; 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::span_invalid_monomorphization_error;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::glue; use rustc_codegen_ssa::glue;
...@@ -301,7 +301,7 @@ fn codegen_intrinsic_call( ...@@ -301,7 +301,7 @@ fn codegen_intrinsic_call(
unsafe { unsafe {
llvm::LLVMSetAlignment(load, align); 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 => { sym::volatile_store => {
let dst = args[0].deref(self.cx()); let dst = args[0].deref(self.cx());
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
use rustc_middle::middle::cstore::{self, LinkagePreference}; use rustc_middle::middle::cstore::{self, LinkagePreference};
use rustc_middle::middle::lang_items; use rustc_middle::middle::lang_items;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; 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::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
use rustc_session::Session; use rustc_session::Session;
use rustc_span::Span; use rustc_span::Span;
use rustc_symbol_mangling::test as symbol_names_test; 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::cmp;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
...@@ -330,35 +330,6 @@ pub fn wants_msvc_seh(sess: &Session) -> bool { ...@@ -330,35 +330,6 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
sess.target.target.options.is_like_msvc 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>>( pub fn memcpy_ty<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx, bx: &mut Bx,
dst: Bx::Value, dst: Bx::Value,
......
...@@ -1143,7 +1143,7 @@ fn codegen_argument( ...@@ -1143,7 +1143,7 @@ fn codegen_argument(
} }
} }
// We store bools as `i8` so we need to truncate to `i1`. // 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);
} }
} }
......
...@@ -147,8 +147,8 @@ pub fn immediate_or_packed_pair<Bx: BuilderMethods<'a, 'tcx, Value = V>>( ...@@ -147,8 +147,8 @@ pub fn immediate_or_packed_pair<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", self, llty); debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", self, llty);
// Reconstruct the immediate aggregate. // Reconstruct the immediate aggregate.
let mut llpair = bx.cx().const_undef(llty); let mut llpair = bx.cx().const_undef(llty);
let imm_a = base::from_immediate(bx, a); let imm_a = bx.from_immediate(a);
let imm_b = base::from_immediate(bx, b); let imm_b = bx.from_immediate(b);
llpair = bx.insert_value(llpair, imm_a, 0); llpair = bx.insert_value(llpair, imm_a, 0);
llpair = bx.insert_value(llpair, imm_b, 1); llpair = bx.insert_value(llpair, imm_b, 1);
llpair llpair
...@@ -168,9 +168,9 @@ pub fn from_immediate_or_packed_pair<Bx: BuilderMethods<'a, 'tcx, Value = V>>( ...@@ -168,9 +168,9 @@ pub fn from_immediate_or_packed_pair<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
// Deconstruct the immediate aggregate. // Deconstruct the immediate aggregate.
let a_llval = bx.extract_value(llval, 0); 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 = 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) OperandValue::Pair(a_llval, b_llval)
} else { } else {
OperandValue::Immediate(llval) OperandValue::Immediate(llval)
...@@ -220,29 +220,21 @@ pub fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>( ...@@ -220,29 +220,21 @@ pub fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
_ => bug!("OperandRef::extract_field({:?}): not applicable", self), _ => bug!("OperandRef::extract_field({:?}): not applicable", self),
}; };
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. match (&mut val, &self.layout.abi) {
(OperandValue::Immediate(llval), _) => {
// Bools in union fields needs to be truncated. // Bools in union fields needs to be truncated.
let to_immediate_or_cast = |bx: &mut Bx, val, ty| { *llval = bx.to_immediate(*llval, field);
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.
}; *llval = bx.bitcast(*llval, bx.cx().immediate_backend_type(field));
match val {
OperandValue::Immediate(ref mut llval) => {
*llval = to_immediate_or_cast(bx, *llval, bx.cx().immediate_backend_type(field));
} }
OperandValue::Pair(ref mut a, ref mut b) => { (OperandValue::Pair(a, b), Abi::ScalarPair(a_abi, b_abi)) => {
*a = to_immediate_or_cast( *a = bx.to_immediate_scalar(*a, a_abi);
bx, *a = bx.bitcast(*a, bx.cx().scalar_pair_element_backend_type(field, 0, true));
*a, *b = bx.to_immediate_scalar(*b, b_abi);
bx.cx().scalar_pair_element_backend_type(field, 0, true), *b = bx.bitcast(*b, bx.cx().scalar_pair_element_backend_type(field, 1, true));
);
*b = to_immediate_or_cast(
bx,
*b,
bx.cx().scalar_pair_element_backend_type(field, 1, true),
);
} }
OperandValue::Ref(..) => bug!(), (OperandValue::Pair(..), _) => bug!(),
(OperandValue::Ref(..), _) => bug!(),
} }
OperandRef { val, layout: field } OperandRef { val, layout: field }
...@@ -302,7 +294,7 @@ fn store_with_flags<Bx: BuilderMethods<'a, 'tcx, Value = V>>( ...@@ -302,7 +294,7 @@ fn store_with_flags<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
bug!("cannot directly store unsized values"); bug!("cannot directly store unsized values");
} }
OperandValue::Immediate(s) => { 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); bx.store_with_flags(val, dest.llval, dest.align, flags);
} }
OperandValue::Pair(a, b) => { OperandValue::Pair(a, b) => {
...@@ -313,12 +305,12 @@ fn store_with_flags<Bx: BuilderMethods<'a, 'tcx, Value = V>>( ...@@ -313,12 +305,12 @@ fn store_with_flags<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
let b_offset = a_scalar.value.size(bx).align_to(b_scalar.value.align(bx).abi); 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 llptr = bx.struct_gep(dest.llval, 0);
let val = base::from_immediate(bx, a); let val = bx.from_immediate(a);
let align = dest.align; let align = dest.align;
bx.store_with_flags(val, llptr, align, flags); bx.store_with_flags(val, llptr, align, flags);
let llptr = bx.struct_gep(dest.llval, 1); 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); let align = dest.align.restrict_for_offset(b_offset);
bx.store_with_flags(val, llptr, align, flags); bx.store_with_flags(val, llptr, align, flags);
} }
......
...@@ -98,7 +98,7 @@ pub fn codegen_rvalue( ...@@ -98,7 +98,7 @@ pub fn codegen_rvalue(
} }
// Use llvm.memset.p0i8.* to initialize byte arrays // 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() { if bx.cx().val_ty(v) == bx.cx().type_i8() {
bx.memset(start, v, size, dest.align, MemFlags::empty()); bx.memset(start, v, size, dest.align, MemFlags::empty());
return bx; return bx;
......
...@@ -13,9 +13,9 @@ ...@@ -13,9 +13,9 @@
use crate::mir::place::PlaceRef; use crate::mir::place::PlaceRef;
use crate::MemFlags; use crate::MemFlags;
use rustc_middle::ty::layout::HasParamEnv; use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout};
use rustc_middle::ty::Ty; 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 rustc_target::spec::HasTargetSpec;
use std::iter::TrustedLen; use std::iter::TrustedLen;
...@@ -115,6 +115,16 @@ fn checked_binop( ...@@ -115,6 +115,16 @@ fn checked_binop(
rhs: Self::Value, rhs: Self::Value,
) -> (Self::Value, 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 alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
fn dynamic_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; fn array_alloca(&mut self, ty: Self::Type, len: Self::Value, align: Align) -> Self::Value;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册