Skip to content

Commit 8b9ff39

Browse files
committed
Generalized base::coerce_unsized_into
1 parent 56f3990 commit 8b9ff39

File tree

16 files changed

+189
-133
lines changed

16 files changed

+189
-133
lines changed

src/librustc_codegen_llvm/asm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ pub fn codegen_inline_asm(
3737
let mut indirect_outputs = vec![];
3838
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_ref(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_ref(place).immediate());
4545
} else {
4646
output_types.push(place.layout.llvm_type(bx.cx()));
4747
}

src/librustc_codegen_llvm/base.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, Codege
6666
use rustc_codegen_utils::symbol_names_test;
6767
use time_graph;
6868
use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt};
69-
use type_of::LayoutLlvmExt;
69+
7070
use rustc::util::nodemap::{FxHashMap, DefIdSet};
7171
use CrateInfo;
7272
use rustc_data_structures::small_c_str::SmallCStr;
@@ -274,22 +274,23 @@ pub fn unsize_thin_ptr<'a, 'll: 'a, 'tcx: 'll, Bx: BuilderMethods<'a, 'll, 'tcx>
274274

275275
/// Coerce `src`, which is a reference to a value of type `src_ty`,
276276
/// to a value of type `dst_ty` and store the result in `dst`
277-
pub fn coerce_unsized_into(
278-
bx: &Builder<'a, 'll, 'tcx, &'ll Value>,
279-
src: PlaceRef<'tcx, &'ll Value>,
280-
dst: PlaceRef<'tcx, &'ll Value>
281-
) {
277+
pub fn coerce_unsized_into<'a, 'll: 'a, 'tcx: 'll, Bx: BuilderMethods<'a, 'll, 'tcx>>(
278+
bx: &Bx,
279+
src: PlaceRef<'tcx, <Bx::CodegenCx as Backend>::Value>,
280+
dst: PlaceRef<'tcx, <Bx::CodegenCx as Backend>::Value>
281+
) where &'a Bx::CodegenCx: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>> + HasTyCtxt<'tcx>
282+
{
282283
let src_ty = src.layout.ty;
283284
let dst_ty = dst.layout.ty;
284285
let coerce_ptr = || {
285-
let (base, info) = match src.load(bx).val {
286+
let (base, info) = match bx.load_ref(&src).val {
286287
OperandValue::Pair(base, info) => {
287288
// fat-ptr to fat-ptr unsize preserves the vtable
288289
// i.e. &'a fmt::Debug+Send => &'a fmt::Debug
289290
// So we need to pointercast the base to ensure
290291
// the types match up.
291292
let thin_ptr = dst.layout.field(bx.cx(), abi::FAT_PTR_ADDR);
292-
(bx.pointercast(base, thin_ptr.llvm_type(bx.cx())), info)
293+
(bx.pointercast(base, bx.cx().backend_type(&thin_ptr)), info)
293294
}
294295
OperandValue::Immediate(base) => {
295296
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::TyCtxt;
19-
use rustc::ty::layout::{Align, Size};
20+
use rustc::ty::layout::{self, Align, Size};
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;
@@ -533,6 +536,73 @@ impl BuilderMethods<'a, 'll, 'tcx>
533536
}
534537
}
535538

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

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

src/librustc_codegen_llvm/glue.rs

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

1515
use std;
1616

17-
use builder::Builder;
1817
use common::*;
1918
use meth;
20-
use rustc::ty::layout::LayoutOf;
19+
use rustc::ty::layout::{LayoutOf, TyLayout, HasTyCtxt};
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, &'ll Value>,
23+
pub fn size_and_align_of_dst<'a, 'll: 'a, 'tcx: 'll,
24+
Bx: BuilderMethods<'a, 'll, 'tcx>
25+
>(
26+
bx: &Bx,
2727
t: Ty<'tcx>,
28-
info: Option<&'ll Value>
29-
) -> (&'ll Value, &'ll Value) {
28+
info: Option<<Bx::CodegenCx as Backend>::Value>
29+
) -> (<Bx::CodegenCx as Backend>::Value, <Bx::CodegenCx as Backend>::Value) where
30+
&'a Bx::CodegenCx: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>> + HasTyCtxt<'tcx>
31+
{
3032
debug!("calculate size of DST: {}; with lost info: {:?}",
3133
t, info);
3234
if bx.cx().type_is_sized(t) {
33-
let (size, align) = bx.cx().size_and_align_of(t);
35+
let (size, align) = bx.cx().layout_of(t).size_and_align();
3436
debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}",
3537
t, info, size, align);
3638
let size = bx.cx().const_usize(size.bytes());
@@ -47,7 +49,7 @@ pub fn size_and_align_of_dst(
4749
let unit = t.sequence_element_type(bx.tcx());
4850
// The info in this case is the length of the str, so the size is that
4951
// times the unit size.
50-
let (size, align) = bx.cx().size_and_align_of(unit);
52+
let (size, align) = bx.cx().layout_of(unit).size_and_align();
5153
(bx.mul(info.unwrap(), bx.cx().const_usize(size.bytes())),
5254
bx.cx().const_usize(align.abi()))
5355
}

src/librustc_codegen_llvm/interfaces/backend.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::fmt::Debug;
11+
use super::CodegenObject;
1212

1313
pub trait Backend {
14-
type Value : Debug + PartialEq + Copy;
14+
type Value : CodegenObject;
1515
type BasicBlock;
16-
type Type : Debug + PartialEq + Copy;
16+
type Type : CodegenObject;
1717
type Context;
1818
}

src/librustc_codegen_llvm/interfaces/builder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ use rustc::session::Session;
1616
use builder::MemFlags;
1717
use super::backend::Backend;
1818
use super::CodegenMethods;
19+
use mir::place::PlaceRef;
20+
use mir::operand::OperandRef;
1921

2022
use std::borrow::Cow;
2123
use std::ops::Range;
@@ -228,6 +230,10 @@ pub trait BuilderMethods<'a, 'll :'a, 'tcx: 'll> : HasCodegen<'a, 'll, 'tcx> {
228230
ptr: <Self::CodegenCx as Backend>::Value,
229231
order: AtomicOrdering, align: Align
230232
) -> <Self::CodegenCx as Backend>::Value;
233+
fn load_ref(
234+
&self,
235+
&PlaceRef<'tcx,<Self::CodegenCx as Backend>::Value>
236+
) -> OperandRef<'tcx, <Self::CodegenCx as Backend>::Value>;
231237

232238
fn range_metadata(&self, load: <Self::CodegenCx as Backend>::Value, range: Range<u128>);
233239
fn nonnull_metadata(&self, load: <Self::CodegenCx as Backend>::Value);

src/librustc_codegen_llvm/interfaces/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ pub use self::statics::StaticMethods;
2626
pub use self::misc::MiscMethods;
2727
pub use self::debuginfo::DebugInfoMethods;
2828

29+
use std::fmt;
30+
2931
pub trait CodegenMethods<'ll, 'tcx: 'll> :
3032
Backend + TypeMethods<'ll, 'tcx> + MiscMethods<'tcx> + ConstMethods +
3133
StaticMethods<'tcx> + DebugInfoMethods<'tcx> {}
34+
35+
pub trait CodegenObject : Copy + PartialEq + fmt::Debug {}

src/librustc_codegen_llvm/interfaces/type_.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ pub trait DerivedTypeMethods<'tcx> : Backend {
8585

8686
pub trait LayoutTypeMethods<'tcx> : Backend {
8787
fn backend_type(&self, ty: &TyLayout<'tcx>) -> Self::Type;
88+
fn immediate_backend_type(&self, ty: &TyLayout<'tcx>) -> Self::Type;
89+
fn is_backend_immediate(&self, ty: &TyLayout<'tcx>) -> bool;
8890
fn scalar_pair_element_backend_type<'a>(
8991
&self,
9092
ty: &TyLayout<'tcx>,
@@ -93,4 +95,5 @@ pub trait LayoutTypeMethods<'tcx> : Backend {
9395
) -> Self::Type;
9496
}
9597

96-
pub trait TypeMethods<'a, 'tcx: 'a> : BaseTypeMethods<'a, 'tcx> + DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {}
98+
pub trait TypeMethods<'a, 'tcx: 'a> :
99+
BaseTypeMethods<'a, 'tcx> + DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {}

src/librustc_codegen_llvm/intrinsic.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ impl IntrinsicCallMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx, &'ll Value>
149149
let tp_ty = substs.type_at(0);
150150
if let OperandValue::Pair(_, meta) = args[0].val {
151151
let (llsize, _) =
152-
glue::size_and_align_of_dst(&self, tp_ty, Some(meta));
152+
glue::size_and_align_of_dst(self, tp_ty, Some(meta));
153153
llsize
154154
} else {
155155
cx.const_usize(cx.size_of(tp_ty).bytes())
@@ -163,7 +163,7 @@ impl IntrinsicCallMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx, &'ll Value>
163163
let tp_ty = substs.type_at(0);
164164
if let OperandValue::Pair(_, meta) = args[0].val {
165165
let (_, llalign) =
166-
glue::size_and_align_of_dst(&self, tp_ty, Some(meta));
166+
glue::size_and_align_of_dst(self, tp_ty, Some(meta));
167167
llalign
168168
} else {
169169
cx.const_usize(cx.align_of(tp_ty).abi())
@@ -341,9 +341,9 @@ impl IntrinsicCallMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx, &'ll Value>
341341
cx.type_bool()
342342
);
343343

344-
let dest = result.project_field(&self, 0);
344+
let dest = result.project_field(self, 0);
345345
&self.store(val, dest.llval, dest.align);
346-
let dest = result.project_field(&self, 1);
346+
let dest = result.project_field(self, 1);
347347
&self.store(overflow, dest.llval, dest.align);
348348

349349
return;
@@ -481,9 +481,9 @@ impl IntrinsicCallMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx, &'ll Value>
481481
&self.cx().type_bool()
482482
);
483483

484-
let dest = result.project_field(&self, 0);
484+
let dest = result.project_field(self, 0);
485485
&self.store(val, dest.llval, dest.align);
486-
let dest = result.project_field(&self, 1);
486+
let dest = result.project_field(self, 1);
487487
&self.store(success, dest.llval, dest.align);
488488
return;
489489
} else {
@@ -639,7 +639,7 @@ impl IntrinsicCallMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx, &'ll Value>
639639
};
640640
let arg = PlaceRef::new_sized(ptr, arg.layout, align);
641641
(0..contents.len()).map(|i| {
642-
arg.project_field(bx, i).load(bx).immediate()
642+
bx.load_ref(&arg.project_field(bx, i)).immediate()
643643
}).collect()
644644
}
645645
intrinsics::Type::Pointer(_, Some(ref llvm_elem), _) => {
@@ -690,7 +690,7 @@ impl IntrinsicCallMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx, &'ll Value>
690690
assert!(!flatten);
691691

692692
for i in 0..elems.len() {
693-
let dest = result.project_field(&self, i);
693+
let dest = result.project_field(self, i);
694694
let val = &self.extract_value(val, i as u64);
695695
&self.store(val, dest.llval, dest.align);
696696
}
@@ -707,7 +707,7 @@ impl IntrinsicCallMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx, &'ll Value>
707707
&self.store(llval, ptr, result.align);
708708
} else {
709709
OperandRef::from_immediate_or_packed_pair(&self, llval, result.layout)
710-
.val.store(&self, result);
710+
.val.store(self, result);
711711
}
712712
}
713713
}

src/librustc_codegen_llvm/meth.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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, 'll, 'tcx>>(
5656
self,
57-
bx: &Builder<'a, 'll, 'tcx, &'ll Value>,
58-
llvtable: &'ll Value
59-
) -> &'ll Value {
57+
bx: &Bx,
58+
llvtable: <Bx::CodegenCx as Backend>::Value
59+
) -> <Bx::CodegenCx as Backend>::Value {
6060
// Load the data pointer from the object.
6161
debug!("get_int({:?}, {:?})", llvtable, self);
6262

0 commit comments

Comments
 (0)