Skip to content

Commit cbe31a4

Browse files
denismerigouxeddyb
authored andcommitted
Generalized base::coerce_unsized_into
1 parent 78dd95f commit cbe31a4

File tree

15 files changed

+184
-145
lines changed

15 files changed

+184
-145
lines changed

src/librustc_codegen_llvm/asm.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ pub fn codegen_inline_asm(
3535

3636
// Prepare the output operands
3737
let mut indirect_outputs = vec![];
38-
for (i, (out, place)) in ia.outputs.iter().zip(&outputs).enumerate() {
38+
for (i, (out, &place)) in ia.outputs.iter().zip(&outputs).enumerate() {
3939
if out.is_rw {
40-
inputs.push(place.load(bx).immediate());
40+
inputs.push(bx.load_operand(place).immediate());
4141
ext_constraints.push(i.to_string());
4242
}
4343
if out.is_indirect {
44-
indirect_outputs.push(place.load(bx).immediate());
44+
indirect_outputs.push(bx.load_operand(place).immediate());
4545
} else {
4646
output_types.push(place.layout.llvm_type(bx.cx()));
4747
}

src/librustc_codegen_llvm/base.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ use monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
6565
use rustc_codegen_utils::symbol_names_test;
6666
use time_graph;
6767
use mono_item::{MonoItem, MonoItemExt};
68-
use type_of::LayoutLlvmExt;
68+
6969
use rustc::util::nodemap::FxHashMap;
7070
use CrateInfo;
7171
use rustc_data_structures::small_c_str::SmallCStr;
@@ -208,7 +208,7 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>(
208208
let vtable_ptr = cx.layout_of(cx.tcx().mk_mut_ptr(target))
209209
.field(cx, abi::FAT_PTR_EXTRA);
210210
cx.static_ptrcast(meth::get_vtable(cx, source, data.principal()),
211-
cx.backend_type(&vtable_ptr))
211+
cx.backend_type(vtable_ptr))
212212
}
213213
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
214214
source,
@@ -232,13 +232,13 @@ pub fn unsize_thin_ptr<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
232232
(&ty::RawPtr(ty::TypeAndMut { ty: a, .. }),
233233
&ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
234234
assert!(bx.cx().type_is_sized(a));
235-
let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(&bx.cx().layout_of(b)));
235+
let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(bx.cx().layout_of(b)));
236236
(bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None))
237237
}
238238
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
239239
let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty());
240240
assert!(bx.cx().type_is_sized(a));
241-
let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(&bx.cx().layout_of(b)));
241+
let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(bx.cx().layout_of(b)));
242242
(bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None))
243243
}
244244
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
@@ -263,31 +263,31 @@ pub fn unsize_thin_ptr<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
263263
}
264264
let (lldata, llextra) = result.unwrap();
265265
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
266-
(bx.bitcast(lldata, bx.cx().scalar_pair_element_backend_type(&dst_layout, 0, true)),
267-
bx.bitcast(llextra, bx.cx().scalar_pair_element_backend_type(&dst_layout, 1, true)))
266+
(bx.bitcast(lldata, bx.cx().scalar_pair_element_backend_type(dst_layout, 0, true)),
267+
bx.bitcast(llextra, bx.cx().scalar_pair_element_backend_type(dst_layout, 1, true)))
268268
}
269269
_ => bug!("unsize_thin_ptr: called on bad types"),
270270
}
271271
}
272272

273273
/// Coerce `src`, which is a reference to a value of type `src_ty`,
274274
/// to a value of type `dst_ty` and store the result in `dst`
275-
pub fn coerce_unsized_into(
276-
bx: &Builder<'a, 'll, 'tcx>,
277-
src: PlaceRef<'tcx, &'ll Value>,
278-
dst: PlaceRef<'tcx, &'ll Value>
279-
) {
275+
pub fn coerce_unsized_into<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
276+
bx: &Bx,
277+
src: PlaceRef<'tcx, Bx::Value>,
278+
dst: PlaceRef<'tcx, Bx::Value>
279+
) {
280280
let src_ty = src.layout.ty;
281281
let dst_ty = dst.layout.ty;
282282
let coerce_ptr = || {
283-
let (base, info) = match src.load(bx).val {
283+
let (base, info) = match bx.load_operand(src).val {
284284
OperandValue::Pair(base, info) => {
285285
// fat-ptr to fat-ptr unsize preserves the vtable
286286
// i.e. &'a fmt::Debug+Send => &'a fmt::Debug
287287
// So we need to pointercast the base to ensure
288288
// the types match up.
289289
let thin_ptr = dst.layout.field(bx.cx(), abi::FAT_PTR_ADDR);
290-
(bx.pointercast(base, thin_ptr.llvm_type(bx.cx())), info)
290+
(bx.pointercast(base, bx.cx().backend_type(thin_ptr)), info)
291291
}
292292
OperandValue::Immediate(base) => {
293293
unsize_thin_ptr(bx, base, src_ty, dst_ty)

src/librustc_codegen_llvm/builder.rs

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,18 @@ use llvm::{self, False, OperandBundleDef, BasicBlock};
1313
use common::{self, *};
1414
use context::CodegenCx;
1515
use type_::Type;
16+
use type_of::LayoutLlvmExt;
1617
use value::Value;
1718
use libc::{c_uint, c_char};
1819
use rustc::ty::{self, Ty, TyCtxt};
19-
use rustc::ty::layout::{Align, Size, TyLayout};
20+
use rustc::ty::layout::{self, Align, Size, TyLayout};
2021
use rustc::session::{config, Session};
2122
use rustc_data_structures::small_c_str::SmallCStr;
2223
use interfaces::*;
2324
use syntax;
24-
25+
use base;
26+
use mir::operand::{OperandValue, OperandRef};
27+
use mir::place::PlaceRef;
2528
use std::borrow::Cow;
2629
use std::ops::Range;
2730
use std::ptr;
@@ -538,6 +541,73 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
538541
}
539542
}
540543

544+
fn load_operand(
545+
&self,
546+
place: PlaceRef<'tcx, &'ll Value>
547+
) -> OperandRef<'tcx, &'ll Value> {
548+
debug!("PlaceRef::load: {:?}", place);
549+
550+
assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
551+
552+
if place.layout.is_zst() {
553+
return OperandRef::new_zst(self.cx(), place.layout);
554+
}
555+
556+
let scalar_load_metadata = |load, scalar: &layout::Scalar| {
557+
let vr = scalar.valid_range.clone();
558+
match scalar.value {
559+
layout::Int(..) => {
560+
let range = scalar.valid_range_exclusive(self.cx());
561+
if range.start != range.end {
562+
self.range_metadata(load, range);
563+
}
564+
}
565+
layout::Pointer if vr.start() < vr.end() && !vr.contains(&0) => {
566+
self.nonnull_metadata(load);
567+
}
568+
_ => {}
569+
}
570+
};
571+
572+
let val = if let Some(llextra) = place.llextra {
573+
OperandValue::Ref(place.llval, Some(llextra), place.align)
574+
} else if place.layout.is_llvm_immediate() {
575+
let mut const_llval = None;
576+
unsafe {
577+
if let Some(global) = llvm::LLVMIsAGlobalVariable(place.llval) {
578+
if llvm::LLVMIsGlobalConstant(global) == llvm::True {
579+
const_llval = llvm::LLVMGetInitializer(global);
580+
}
581+
}
582+
}
583+
let llval = const_llval.unwrap_or_else(|| {
584+
let load = self.load(place.llval, place.align);
585+
if let layout::Abi::Scalar(ref scalar) = place.layout.abi {
586+
scalar_load_metadata(load, scalar);
587+
}
588+
load
589+
});
590+
OperandValue::Immediate(base::to_immediate(self, llval, place.layout))
591+
} else if let layout::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
592+
let load = |i, scalar: &layout::Scalar| {
593+
let llptr = self.struct_gep(place.llval, i as u64);
594+
let load = self.load(llptr, place.align);
595+
scalar_load_metadata(load, scalar);
596+
if scalar.is_bool() {
597+
self.trunc(load, self.cx().type_i1())
598+
} else {
599+
load
600+
}
601+
};
602+
OperandValue::Pair(load(0, a), load(1, b))
603+
} else {
604+
OperandValue::Ref(place.llval, None, place.align)
605+
};
606+
607+
OperandRef { val, layout: place.layout }
608+
}
609+
610+
541611

542612
fn range_metadata(&self, load: &'ll Value, range: Range<u128>) {
543613
if self.sess().target.target.arch == "amdgpu" {

src/librustc_codegen_llvm/glue.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,21 @@
1414

1515
use std;
1616

17-
use builder::Builder;
1817
use common::*;
1918
use meth;
20-
use rustc::ty::layout::{LayoutOf, HasTyCtxt};
19+
use rustc::ty::layout::LayoutOf;
2120
use rustc::ty::{self, Ty};
22-
use value::Value;
2321
use interfaces::*;
2422

25-
pub fn size_and_align_of_dst(
26-
bx: &Builder<'_, 'll, 'tcx>,
23+
pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
24+
bx: &Bx,
2725
t: Ty<'tcx>,
28-
info: Option<&'ll Value>
29-
) -> (&'ll Value, &'ll Value) {
26+
info: Option<Bx::Value>
27+
) -> (Bx::Value, Bx::Value) {
3028
debug!("calculate size of DST: {}; with lost info: {:?}",
3129
t, info);
3230
if bx.cx().type_is_sized(t) {
33-
let (size, align) = bx.cx().size_and_align_of(t);
31+
let (size, align) = bx.cx().layout_of(t).size_and_align();
3432
debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}",
3533
t, info, size, align);
3634
let size = bx.cx().const_usize(size.bytes());
@@ -47,7 +45,7 @@ pub fn size_and_align_of_dst(
4745
let unit = t.sequence_element_type(bx.tcx());
4846
// The info in this case is the length of the str, so the size is that
4947
// times the unit size.
50-
let (size, align) = bx.cx().size_and_align_of(unit);
48+
let (size, align) = bx.cx().layout_of(unit).size_and_align();
5149
(bx.mul(info.unwrap(), bx.cx().const_usize(size.bytes())),
5250
bx.cx().const_usize(align.abi()))
5351
}

src/librustc_codegen_llvm/interfaces/backend.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@
1010

1111
use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout};
1212
use rustc::ty::Ty;
13-
use std::fmt::Debug;
13+
14+
use super::CodegenObject;
1415

1516
pub trait BackendTypes {
16-
type Value: Debug + PartialEq + Copy;
17+
type Value: CodegenObject;
1718
type BasicBlock;
18-
type Type: Debug + PartialEq + Copy;
19+
type Type: CodegenObject;
1920
type Context;
2021
}
2122

src/librustc_codegen_llvm/interfaces/builder.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use super::HasCodegen;
1212
use builder::MemFlags;
1313
use common::*;
1414
use libc::c_char;
15+
use mir::operand::OperandRef;
16+
use mir::place::PlaceRef;
1517
use rustc::session::Session;
1618
use rustc::ty::layout::{Align, Size};
1719

@@ -88,6 +90,7 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: HasCodegen<'tcx> {
8890
fn load(&self, ptr: Self::Value, align: Align) -> Self::Value;
8991
fn volatile_load(&self, ptr: Self::Value) -> Self::Value;
9092
fn atomic_load(&self, ptr: Self::Value, order: AtomicOrdering, size: Size) -> Self::Value;
93+
fn load_operand(&self, place: PlaceRef<'tcx, Self::Value>) -> OperandRef<'tcx, Self::Value>;
9194

9295
fn range_metadata(&self, load: Self::Value, range: Range<u128>);
9396
fn nonnull_metadata(&self, load: Self::Value);

src/librustc_codegen_llvm/interfaces/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ pub use self::misc::MiscMethods;
2626
pub use self::statics::StaticMethods;
2727
pub use self::type_::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMethods};
2828

29+
use std::fmt;
30+
2931
pub trait CodegenMethods<'tcx>:
3032
Backend<'tcx>
3133
+ TypeMethods<'tcx>
@@ -54,3 +56,6 @@ pub trait HasCodegen<'tcx>: Backend<'tcx> {
5456
Context = Self::Context,
5557
>;
5658
}
59+
60+
pub trait CodegenObject: Copy + PartialEq + fmt::Debug {}
61+
impl<T: Copy + PartialEq + fmt::Debug> CodegenObject for T {}

src/librustc_codegen_llvm/interfaces/type_.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,14 @@ pub trait DerivedTypeMethods<'tcx>: Backend<'tcx> {
6969
}
7070

7171
pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
72-
fn backend_type(&self, ty: &TyLayout<'tcx>) -> Self::Type;
72+
fn backend_type(&self, layout: TyLayout<'tcx>) -> Self::Type;
73+
fn immediate_backend_type(&self, layout: TyLayout<'tcx>) -> Self::Type;
74+
fn is_backend_immediate(&self, layout: TyLayout<'tcx>) -> bool;
7375
fn scalar_pair_element_backend_type<'a>(
7476
&self,
75-
ty: &TyLayout<'tcx>,
77+
layout: TyLayout<'tcx>,
7678
index: usize,
77-
immediate: bool
79+
immediate: bool,
7880
) -> Self::Type;
7981
}
8082

src/librustc_codegen_llvm/intrinsic.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ impl IntrinsicCallMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
154154
let tp_ty = substs.type_at(0);
155155
if let OperandValue::Pair(_, meta) = args[0].val {
156156
let (llsize, _) =
157-
glue::size_and_align_of_dst(&self, tp_ty, Some(meta));
157+
glue::size_and_align_of_dst(self, tp_ty, Some(meta));
158158
llsize
159159
} else {
160160
cx.const_usize(cx.size_of(tp_ty).bytes())
@@ -168,7 +168,7 @@ impl IntrinsicCallMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
168168
let tp_ty = substs.type_at(0);
169169
if let OperandValue::Pair(_, meta) = args[0].val {
170170
let (_, llalign) =
171-
glue::size_and_align_of_dst(&self, tp_ty, Some(meta));
171+
glue::size_and_align_of_dst(self, tp_ty, Some(meta));
172172
llalign
173173
} else {
174174
cx.const_usize(cx.align_of(tp_ty).abi())
@@ -353,9 +353,9 @@ impl IntrinsicCallMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
353353
cx.type_bool()
354354
);
355355

356-
let dest = result.project_field(&self, 0);
356+
let dest = result.project_field(self, 0);
357357
self.store(val, dest.llval, dest.align);
358-
let dest = result.project_field(&self, 1);
358+
let dest = result.project_field(self, 1);
359359
self.store(overflow, dest.llval, dest.align);
360360

361361
return;
@@ -520,9 +520,9 @@ impl IntrinsicCallMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
520520
cx.type_bool()
521521
);
522522

523-
let dest = result.project_field(&self, 0);
523+
let dest = result.project_field(self, 0);
524524
self.store(val, dest.llval, dest.align);
525-
let dest = result.project_field(&self, 1);
525+
let dest = result.project_field(self, 1);
526526
self.store(success, dest.llval, dest.align);
527527
return;
528528
} else {
@@ -678,7 +678,7 @@ impl IntrinsicCallMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
678678
};
679679
let arg = PlaceRef::new_sized(ptr, arg.layout, align);
680680
(0..contents.len()).map(|i| {
681-
arg.project_field(bx, i).load(bx).immediate()
681+
bx.load_operand(arg.project_field(bx, i)).immediate()
682682
}).collect()
683683
}
684684
intrinsics::Type::Pointer(_, Some(ref llvm_elem), _) => {
@@ -729,7 +729,7 @@ impl IntrinsicCallMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
729729
assert!(!flatten);
730730

731731
for i in 0..elems.len() {
732-
let dest = result.project_field(&self, i);
732+
let dest = result.project_field(self, i);
733733
let val = self.extract_value(val, i as u64);
734734
self.store(val, dest.llval, dest.align);
735735
}
@@ -746,7 +746,7 @@ impl IntrinsicCallMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
746746
self.store(llval, ptr, result.align);
747747
} else {
748748
OperandRef::from_immediate_or_packed_pair(&self, llval, result.layout)
749-
.val.store(&self, result);
749+
.val.store(self, result);
750750
}
751751
}
752752
}

src/librustc_codegen_llvm/meth.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub const DESTRUCTOR: VirtualIndex = VirtualIndex(0);
2626
pub const SIZE: VirtualIndex = VirtualIndex(1);
2727
pub const ALIGN: VirtualIndex = VirtualIndex(2);
2828

29-
impl<'a, 'tcx> VirtualIndex {
29+
impl<'a, 'tcx: 'a> VirtualIndex {
3030
pub fn from_index(index: usize) -> Self {
3131
VirtualIndex(index as u64 + 3)
3232
}
@@ -52,11 +52,11 @@ impl<'a, 'tcx> VirtualIndex {
5252
ptr
5353
}
5454

55-
pub fn get_usize(
55+
pub fn get_usize<Bx: BuilderMethods<'a, 'tcx>>(
5656
self,
57-
bx: &Builder<'a, 'll, 'tcx>,
58-
llvtable: &'ll Value
59-
) -> &'ll Value {
57+
bx: &Bx,
58+
llvtable: Bx::Value
59+
) -> Bx::Value {
6060
// Load the data pointer from the object.
6161
debug!("get_int({:?}, {:?})", llvtable, self);
6262

0 commit comments

Comments
 (0)