Skip to content

Commit 81650f4

Browse files
committed
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.
1 parent 286a346 commit 81650f4

File tree

7 files changed

+54
-68
lines changed

7 files changed

+54
-68
lines changed

src/librustc_codegen_llvm/builder.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use crate::type_::Type;
66
use crate::type_of::LayoutLlvmExt;
77
use crate::value::Value;
88
use libc::{c_char, c_uint};
9-
use rustc_codegen_ssa::base::to_immediate;
109
use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, TypeKind};
1110
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
1211
use rustc_codegen_ssa::mir::place::PlaceRef;
@@ -367,6 +366,20 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
367366
(self.extract_value(res, 0), self.extract_value(res, 1))
368367
}
369368

369+
fn from_immediate(&mut self, val: Self::Value) -> Self::Value {
370+
if self.cx().val_ty(val) == self.cx().type_i1() {
371+
self.zext(val, self.cx().type_i8())
372+
} else {
373+
val
374+
}
375+
}
376+
fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &abi::Scalar) -> Self::Value {
377+
if scalar.is_bool() {
378+
return self.trunc(val, self.cx().type_i1());
379+
}
380+
val
381+
}
382+
370383
fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
371384
let mut bx = Builder::with_cx(self.cx);
372385
bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) });
@@ -471,15 +484,15 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
471484
}
472485
load
473486
});
474-
OperandValue::Immediate(to_immediate(self, llval, place.layout))
487+
OperandValue::Immediate(self.to_immediate(llval, place.layout))
475488
} else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
476489
let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
477490

478491
let mut load = |i, scalar: &abi::Scalar, align| {
479492
let llptr = self.struct_gep(place.llval, i as u64);
480493
let load = self.load(llptr, align);
481494
scalar_load_metadata(self, load, scalar);
482-
if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load }
495+
self.to_immediate_scalar(load, scalar)
483496
};
484497

485498
OperandValue::Pair(

src/librustc_codegen_llvm/intrinsic.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::va_arg::emit_va_arg;
88
use crate::value::Value;
99

1010
use rustc_ast as ast;
11-
use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh};
11+
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh};
1212
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
1313
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
1414
use rustc_codegen_ssa::glue;
@@ -301,7 +301,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
301301
unsafe {
302302
llvm::LLVMSetAlignment(load, align);
303303
}
304-
to_immediate(self, load, self.layout_of(tp_ty))
304+
self.to_immediate(load, self.layout_of(tp_ty))
305305
}
306306
sym::volatile_store => {
307307
let dst = args[0].deref(self.cx());

src/librustc_codegen_ssa/base.rs

+2-31
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use rustc_middle::middle::cstore::EncodedMetadata;
3838
use rustc_middle::middle::cstore::{self, LinkagePreference};
3939
use rustc_middle::middle::lang_items;
4040
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
41-
use rustc_middle::ty::layout::{self, HasTyCtxt, TyAndLayout};
41+
use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
4242
use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
4343
use rustc_middle::ty::query::Providers;
4444
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
@@ -48,7 +48,7 @@ use rustc_session::utils::NativeLibKind;
4848
use rustc_session::Session;
4949
use rustc_span::Span;
5050
use rustc_symbol_mangling::test as symbol_names_test;
51-
use rustc_target::abi::{Abi, Align, LayoutOf, Scalar, VariantIdx};
51+
use rustc_target::abi::{Align, LayoutOf, VariantIdx};
5252

5353
use std::cmp;
5454
use std::ops::{Deref, DerefMut};
@@ -330,35 +330,6 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
330330
sess.target.target.options.is_like_msvc
331331
}
332332

333-
pub fn from_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
334-
bx: &mut Bx,
335-
val: Bx::Value,
336-
) -> Bx::Value {
337-
if bx.cx().val_ty(val) == bx.cx().type_i1() { bx.zext(val, bx.cx().type_i8()) } else { val }
338-
}
339-
340-
pub fn to_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
341-
bx: &mut Bx,
342-
val: Bx::Value,
343-
layout: layout::TyAndLayout<'_>,
344-
) -> Bx::Value {
345-
if let Abi::Scalar(ref scalar) = layout.abi {
346-
return to_immediate_scalar(bx, val, scalar);
347-
}
348-
val
349-
}
350-
351-
pub fn to_immediate_scalar<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
352-
bx: &mut Bx,
353-
val: Bx::Value,
354-
scalar: &Scalar,
355-
) -> Bx::Value {
356-
if scalar.is_bool() {
357-
return bx.trunc(val, bx.cx().type_i1());
358-
}
359-
val
360-
}
361-
362333
pub fn memcpy_ty<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
363334
bx: &mut Bx,
364335
dst: Bx::Value,

src/librustc_codegen_ssa/mir/block.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1143,7 +1143,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11431143
}
11441144
}
11451145
// We store bools as `i8` so we need to truncate to `i1`.
1146-
llval = base::to_immediate(bx, llval, arg.layout);
1146+
llval = bx.to_immediate(llval, arg.layout);
11471147
}
11481148
}
11491149

src/librustc_codegen_ssa/mir/operand.rs

+20-28
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
147147
debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", self, llty);
148148
// Reconstruct the immediate aggregate.
149149
let mut llpair = bx.cx().const_undef(llty);
150-
let imm_a = base::from_immediate(bx, a);
151-
let imm_b = base::from_immediate(bx, b);
150+
let imm_a = bx.from_immediate(a);
151+
let imm_b = bx.from_immediate(b);
152152
llpair = bx.insert_value(llpair, imm_a, 0);
153153
llpair = bx.insert_value(llpair, imm_b, 1);
154154
llpair
@@ -168,9 +168,9 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
168168

169169
// Deconstruct the immediate aggregate.
170170
let a_llval = bx.extract_value(llval, 0);
171-
let a_llval = base::to_immediate_scalar(bx, a_llval, a);
171+
let a_llval = bx.to_immediate_scalar(a_llval, a);
172172
let b_llval = bx.extract_value(llval, 1);
173-
let b_llval = base::to_immediate_scalar(bx, b_llval, b);
173+
let b_llval = bx.to_immediate_scalar(b_llval, b);
174174
OperandValue::Pair(a_llval, b_llval)
175175
} else {
176176
OperandValue::Immediate(llval)
@@ -220,29 +220,21 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
220220
_ => bug!("OperandRef::extract_field({:?}): not applicable", self),
221221
};
222222

223-
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
224-
// Bools in union fields needs to be truncated.
225-
let to_immediate_or_cast = |bx: &mut Bx, val, ty| {
226-
if ty == bx.cx().type_i1() { bx.trunc(val, ty) } else { bx.bitcast(val, ty) }
227-
};
228-
229-
match val {
230-
OperandValue::Immediate(ref mut llval) => {
231-
*llval = to_immediate_or_cast(bx, *llval, bx.cx().immediate_backend_type(field));
223+
match (&mut val, &self.layout.abi) {
224+
(OperandValue::Immediate(llval), _) => {
225+
// Bools in union fields needs to be truncated.
226+
*llval = bx.to_immediate(*llval, field);
227+
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
228+
*llval = bx.bitcast(*llval, bx.cx().immediate_backend_type(field));
232229
}
233-
OperandValue::Pair(ref mut a, ref mut b) => {
234-
*a = to_immediate_or_cast(
235-
bx,
236-
*a,
237-
bx.cx().scalar_pair_element_backend_type(field, 0, true),
238-
);
239-
*b = to_immediate_or_cast(
240-
bx,
241-
*b,
242-
bx.cx().scalar_pair_element_backend_type(field, 1, true),
243-
);
230+
(OperandValue::Pair(a, b), Abi::ScalarPair(a_abi, b_abi)) => {
231+
*a = bx.to_immediate_scalar(*a, a_abi);
232+
*a = bx.bitcast(*a, bx.cx().scalar_pair_element_backend_type(field, 0, true));
233+
*b = bx.to_immediate_scalar(*b, b_abi);
234+
*b = bx.bitcast(*b, bx.cx().scalar_pair_element_backend_type(field, 1, true));
244235
}
245-
OperandValue::Ref(..) => bug!(),
236+
(OperandValue::Pair(..), _) => bug!(),
237+
(OperandValue::Ref(..), _) => bug!(),
246238
}
247239

248240
OperandRef { val, layout: field }
@@ -302,7 +294,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
302294
bug!("cannot directly store unsized values");
303295
}
304296
OperandValue::Immediate(s) => {
305-
let val = base::from_immediate(bx, s);
297+
let val = bx.from_immediate(s);
306298
bx.store_with_flags(val, dest.llval, dest.align, flags);
307299
}
308300
OperandValue::Pair(a, b) => {
@@ -313,12 +305,12 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
313305
let b_offset = a_scalar.value.size(bx).align_to(b_scalar.value.align(bx).abi);
314306

315307
let llptr = bx.struct_gep(dest.llval, 0);
316-
let val = base::from_immediate(bx, a);
308+
let val = bx.from_immediate(a);
317309
let align = dest.align;
318310
bx.store_with_flags(val, llptr, align, flags);
319311

320312
let llptr = bx.struct_gep(dest.llval, 1);
321-
let val = base::from_immediate(bx, b);
313+
let val = bx.from_immediate(b);
322314
let align = dest.align.restrict_for_offset(b_offset);
323315
bx.store_with_flags(val, llptr, align, flags);
324316
}

src/librustc_codegen_ssa/mir/rvalue.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
9898
}
9999

100100
// Use llvm.memset.p0i8.* to initialize byte arrays
101-
let v = base::from_immediate(&mut bx, v);
101+
let v = bx.from_immediate(v);
102102
if bx.cx().val_ty(v) == bx.cx().type_i8() {
103103
bx.memset(start, v, size, dest.align, MemFlags::empty());
104104
return bx;

src/librustc_codegen_ssa/traits/builder.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ use crate::mir::operand::OperandRef;
1313
use crate::mir::place::PlaceRef;
1414
use crate::MemFlags;
1515

16-
use rustc_middle::ty::layout::HasParamEnv;
16+
use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout};
1717
use rustc_middle::ty::Ty;
18-
use rustc_target::abi::{Align, Size};
18+
use rustc_target::abi::{Abi, Align, Scalar, Size};
1919
use rustc_target::spec::HasTargetSpec;
2020

2121
use std::iter::TrustedLen;
@@ -115,6 +115,16 @@ pub trait BuilderMethods<'a, 'tcx>:
115115
rhs: Self::Value,
116116
) -> (Self::Value, Self::Value);
117117

118+
fn from_immediate(&mut self, val: Self::Value) -> Self::Value;
119+
fn to_immediate(&mut self, val: Self::Value, layout: TyAndLayout<'_>) -> Self::Value {
120+
if let Abi::Scalar(ref scalar) = layout.abi {
121+
self.to_immediate_scalar(val, scalar)
122+
} else {
123+
val
124+
}
125+
}
126+
fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &Scalar) -> Self::Value;
127+
118128
fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
119129
fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
120130
fn array_alloca(&mut self, ty: Self::Type, len: Self::Value, align: Align) -> Self::Value;

0 commit comments

Comments
 (0)