Generalized base::coerce_unsized_into

This commit is contained in:
Denis Merigoux 2018-09-14 17:48:57 +02:00 committed by Eduard-Mihai Burtescu
parent 78dd95f4c7
commit cbe31a4229
15 changed files with 184 additions and 145 deletions

View file

@ -13,15 +13,18 @@ use llvm::{self, False, OperandBundleDef, BasicBlock};
use common::{self, *};
use context::CodegenCx;
use type_::Type;
use type_of::LayoutLlvmExt;
use value::Value;
use libc::{c_uint, c_char};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::{Align, Size, TyLayout};
use rustc::ty::layout::{self, Align, Size, TyLayout};
use rustc::session::{config, Session};
use rustc_data_structures::small_c_str::SmallCStr;
use interfaces::*;
use syntax;
use base;
use mir::operand::{OperandValue, OperandRef};
use mir::place::PlaceRef;
use std::borrow::Cow;
use std::ops::Range;
use std::ptr;
@ -538,6 +541,73 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
}
}
fn load_operand(
&self,
place: PlaceRef<'tcx, &'ll Value>
) -> OperandRef<'tcx, &'ll Value> {
debug!("PlaceRef::load: {:?}", place);
assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
if place.layout.is_zst() {
return OperandRef::new_zst(self.cx(), place.layout);
}
let scalar_load_metadata = |load, scalar: &layout::Scalar| {
let vr = scalar.valid_range.clone();
match scalar.value {
layout::Int(..) => {
let range = scalar.valid_range_exclusive(self.cx());
if range.start != range.end {
self.range_metadata(load, range);
}
}
layout::Pointer if vr.start() < vr.end() && !vr.contains(&0) => {
self.nonnull_metadata(load);
}
_ => {}
}
};
let val = if let Some(llextra) = place.llextra {
OperandValue::Ref(place.llval, Some(llextra), place.align)
} else if place.layout.is_llvm_immediate() {
let mut const_llval = None;
unsafe {
if let Some(global) = llvm::LLVMIsAGlobalVariable(place.llval) {
if llvm::LLVMIsGlobalConstant(global) == llvm::True {
const_llval = llvm::LLVMGetInitializer(global);
}
}
}
let llval = const_llval.unwrap_or_else(|| {
let load = self.load(place.llval, place.align);
if let layout::Abi::Scalar(ref scalar) = place.layout.abi {
scalar_load_metadata(load, scalar);
}
load
});
OperandValue::Immediate(base::to_immediate(self, llval, place.layout))
} else if let layout::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
let load = |i, scalar: &layout::Scalar| {
let llptr = self.struct_gep(place.llval, i as u64);
let load = self.load(llptr, place.align);
scalar_load_metadata(load, scalar);
if scalar.is_bool() {
self.trunc(load, self.cx().type_i1())
} else {
load
}
};
OperandValue::Pair(load(0, a), load(1, b))
} else {
OperandValue::Ref(place.llval, None, place.align)
};
OperandRef { val, layout: place.layout }
}
fn range_metadata(&self, load: &'ll Value, range: Range<u128>) {
if self.sess().target.target.arch == "amdgpu" {