Skip to content

Commit ca3c42f

Browse files
committed
Generalized base::coerce_unsized_into
1 parent 8b7f82f commit ca3c42f

File tree

16 files changed

+320
-138
lines changed

16 files changed

+320
-138
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: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -275,22 +275,23 @@ pub fn unsize_thin_ptr<'a, 'll: 'a, 'tcx: 'll, Bx: BuilderMethods<'a, 'll, 'tcx>
275275

276276
/// Coerce `src`, which is a reference to a value of type `src_ty`,
277277
/// to a value of type `dst_ty` and store the result in `dst`
278-
pub fn coerce_unsized_into(
279-
bx: &Builder<'a, 'll, 'tcx, &'ll Value>,
280-
src: PlaceRef<'tcx, &'ll Value>,
281-
dst: PlaceRef<'tcx, &'ll Value>
282-
) {
278+
pub fn coerce_unsized_into<'a, 'll: 'a, 'tcx: 'll, Bx: BuilderMethods<'a, 'll, 'tcx>>(
279+
bx: &Bx,
280+
src: PlaceRef<'tcx, <Bx::CodegenCx as Backend>::Value>,
281+
dst: PlaceRef<'tcx, <Bx::CodegenCx as Backend>::Value>
282+
) where &'a Bx::CodegenCx: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>> + HasTyCtxt<'tcx>
283+
{
283284
let src_ty = src.layout.ty;
284285
let dst_ty = dst.layout.ty;
285286
let coerce_ptr = || {
286-
let (base, info) = match src.load(bx).val {
287+
let (base, info) = match bx.load_ref(&src).val {
287288
OperandValue::Pair(base, info) => {
288289
// fat-ptr to fat-ptr unsize preserves the vtable
289290
// i.e. &'a fmt::Debug+Send => &'a fmt::Debug
290291
// So we need to pointercast the base to ensure
291292
// the types match up.
292293
let thin_ptr = dst.layout.field(bx.cx(), abi::FAT_PTR_ADDR);
293-
(bx.pointercast(base, thin_ptr.llvm_type(bx.cx())), info)
294+
(bx.pointercast(base, bx.cx().backend_type(&thin_ptr)), info)
294295
}
295296
OperandValue::Immediate(base) => {
296297
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;
@@ -531,6 +534,73 @@ impl BuilderMethods<'a, 'll, 'tcx>
531534
}
532535
}
533536

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

535605
fn range_metadata(&self, load: &'ll Value, range: Range<u128>) {
536606
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> {}

0 commit comments

Comments
 (0)