Generalized base::coerce_unsized_into
This commit is contained in:
parent
78dd95f4c7
commit
cbe31a4229
15 changed files with 184 additions and 145 deletions
|
@ -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" {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue