Auto merge of #54911 - ljedrz:cleanup_codegen_llvm_top, r=michaelwoerister
Cleanup top-level codegen_llvm - improve allocations - improve common patterns - remove explicit returns - fix spelling & grammatical errors - whitespace & formatting improvements
This commit is contained in:
commit
b8b4150c04
18 changed files with 189 additions and 216 deletions
|
@ -150,7 +150,7 @@ impl LlvmType for CastTarget {
|
||||||
// Create list of fields in the main structure
|
// Create list of fields in the main structure
|
||||||
let mut args: Vec<_> =
|
let mut args: Vec<_> =
|
||||||
self.prefix.iter().flat_map(|option_kind| option_kind.map(
|
self.prefix.iter().flat_map(|option_kind| option_kind.map(
|
||||||
|kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx)))
|
|kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx)))
|
||||||
.chain((0..rest_count).map(|_| rest_ll_unit))
|
.chain((0..rest_count).map(|_| rest_ll_unit))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -259,8 +259,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FnTypeExt<'tcx> {
|
pub trait FnTypeExt<'tcx> {
|
||||||
fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>)
|
fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self;
|
||||||
-> Self;
|
|
||||||
fn new(cx: &CodegenCx<'ll, 'tcx>,
|
fn new(cx: &CodegenCx<'ll, 'tcx>,
|
||||||
sig: ty::FnSig<'tcx>,
|
sig: ty::FnSig<'tcx>,
|
||||||
extra_args: &[Ty<'tcx>]) -> Self;
|
extra_args: &[Ty<'tcx>]) -> Self;
|
||||||
|
@ -283,8 +282,7 @@ pub trait FnTypeExt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
|
impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
|
||||||
fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>)
|
fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self {
|
||||||
-> Self {
|
|
||||||
let fn_ty = instance.ty(cx.tcx);
|
let fn_ty = instance.ty(cx.tcx);
|
||||||
let sig = ty_fn_sig(cx, fn_ty);
|
let sig = ty_fn_sig(cx, fn_ty);
|
||||||
let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
|
let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
|
||||||
|
@ -292,16 +290,16 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(cx: &CodegenCx<'ll, 'tcx>,
|
fn new(cx: &CodegenCx<'ll, 'tcx>,
|
||||||
sig: ty::FnSig<'tcx>,
|
sig: ty::FnSig<'tcx>,
|
||||||
extra_args: &[Ty<'tcx>]) -> Self {
|
extra_args: &[Ty<'tcx>]) -> Self {
|
||||||
FnType::new_internal(cx, sig, extra_args, |ty, _| {
|
FnType::new_internal(cx, sig, extra_args, |ty, _| {
|
||||||
ArgType::new(cx.layout_of(ty))
|
ArgType::new(cx.layout_of(ty))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
|
fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
|
||||||
sig: ty::FnSig<'tcx>,
|
sig: ty::FnSig<'tcx>,
|
||||||
extra_args: &[Ty<'tcx>]) -> Self {
|
extra_args: &[Ty<'tcx>]) -> Self {
|
||||||
FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| {
|
FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| {
|
||||||
let mut layout = cx.layout_of(ty);
|
let mut layout = cx.layout_of(ty);
|
||||||
// Don't pass the vtable, it's not an argument of the virtual fn.
|
// Don't pass the vtable, it's not an argument of the virtual fn.
|
||||||
|
@ -338,7 +336,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
|
||||||
RustIntrinsic | PlatformIntrinsic |
|
RustIntrinsic | PlatformIntrinsic |
|
||||||
Rust | RustCall => Conv::C,
|
Rust | RustCall => Conv::C,
|
||||||
|
|
||||||
// It's the ABI's job to select this, not us.
|
// It's the ABI's job to select this, not ours.
|
||||||
System => bug!("system abi should be selected elsewhere"),
|
System => bug!("system abi should be selected elsewhere"),
|
||||||
|
|
||||||
Stdcall => Conv::X86Stdcall,
|
Stdcall => Conv::X86Stdcall,
|
||||||
|
@ -697,14 +695,13 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
|
||||||
// If the value is a boolean, the range is 0..2 and that ultimately
|
// If the value is a boolean, the range is 0..2 and that ultimately
|
||||||
// become 0..0 when the type becomes i1, which would be rejected
|
// become 0..0 when the type becomes i1, which would be rejected
|
||||||
// by the LLVM verifier.
|
// by the LLVM verifier.
|
||||||
match scalar.value {
|
if let layout::Int(..) = scalar.value {
|
||||||
layout::Int(..) if !scalar.is_bool() => {
|
if !scalar.is_bool() {
|
||||||
let range = scalar.valid_range_exclusive(bx.cx);
|
let range = scalar.valid_range_exclusive(bx.cx);
|
||||||
if range.start != range.end {
|
if range.start != range.end {
|
||||||
bx.range_metadata(callsite, range);
|
bx.range_metadata(callsite, range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for arg in &self.args {
|
for arg in &self.args {
|
||||||
|
|
|
@ -33,7 +33,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind
|
||||||
let void = llvm::LLVMVoidTypeInContext(llcx);
|
let void = llvm::LLVMVoidTypeInContext(llcx);
|
||||||
|
|
||||||
for method in ALLOCATOR_METHODS {
|
for method in ALLOCATOR_METHODS {
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::with_capacity(method.inputs.len());
|
||||||
for ty in method.inputs.iter() {
|
for ty in method.inputs.iter() {
|
||||||
match *ty {
|
match *ty {
|
||||||
AllocatorTy::Layout => {
|
AllocatorTy::Layout => {
|
||||||
|
|
|
@ -94,9 +94,8 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
|
||||||
// Currently stack probes seem somewhat incompatible with the address
|
// Currently stack probes seem somewhat incompatible with the address
|
||||||
// sanitizer. With asan we're already protected from stack overflow anyway
|
// sanitizer. With asan we're already protected from stack overflow anyway
|
||||||
// so we don't really need stack probes regardless.
|
// so we don't really need stack probes regardless.
|
||||||
match cx.sess().opts.debugging_opts.sanitizer {
|
if let Some(Sanitizer::Address) = cx.sess().opts.debugging_opts.sanitizer {
|
||||||
Some(Sanitizer::Address) => return,
|
return
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// probestack doesn't play nice either with pgo-gen.
|
// probestack doesn't play nice either with pgo-gen.
|
||||||
|
@ -280,12 +279,14 @@ pub fn provide_extern(providers: &mut Providers) {
|
||||||
// `NativeLibrary` internally contains information about
|
// `NativeLibrary` internally contains information about
|
||||||
// `#[link(wasm_import_module = "...")]` for example.
|
// `#[link(wasm_import_module = "...")]` for example.
|
||||||
let native_libs = tcx.native_libraries(cnum);
|
let native_libs = tcx.native_libraries(cnum);
|
||||||
let mut def_id_to_native_lib = FxHashMap();
|
|
||||||
for lib in native_libs.iter() {
|
let def_id_to_native_lib = native_libs.iter().filter_map(|lib|
|
||||||
if let Some(id) = lib.foreign_module {
|
if let Some(id) = lib.foreign_module {
|
||||||
def_id_to_native_lib.insert(id, lib);
|
Some((id, lib))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
).collect::<FxHashMap<_, _>>();
|
||||||
|
|
||||||
let mut ret = FxHashMap();
|
let mut ret = FxHashMap();
|
||||||
for lib in tcx.foreign_modules(cnum).iter() {
|
for lib in tcx.foreign_modules(cnum).iter() {
|
||||||
|
@ -296,10 +297,10 @@ pub fn provide_extern(providers: &mut Providers) {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
for id in lib.foreign_items.iter() {
|
ret.extend(lib.foreign_items.iter().map(|id| {
|
||||||
assert_eq!(id.krate, cnum);
|
assert_eq!(id.krate, cnum);
|
||||||
ret.insert(*id, module.to_string());
|
(*id, module.to_string())
|
||||||
}
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
Lrc::new(ret)
|
Lrc::new(ret)
|
||||||
|
|
|
@ -213,8 +213,8 @@ pub fn unsized_info(
|
||||||
vtable_ptr.llvm_type(cx))
|
vtable_ptr.llvm_type(cx))
|
||||||
}
|
}
|
||||||
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
|
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
|
||||||
source,
|
source,
|
||||||
target),
|
target),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,11 +340,11 @@ pub fn cast_shift_expr_rhs(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
|
fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
|
||||||
lhs: &'ll Value,
|
lhs: &'ll Value,
|
||||||
rhs: &'ll Value,
|
rhs: &'ll Value,
|
||||||
trunc: F,
|
trunc: F,
|
||||||
zext: G)
|
zext: G)
|
||||||
-> &'ll Value
|
-> &'ll Value
|
||||||
where F: FnOnce(&'ll Value, &'ll Type) -> &'ll Value,
|
where F: FnOnce(&'ll Value, &'ll Type) -> &'ll Value,
|
||||||
G: FnOnce(&'ll Value, &'ll Type) -> &'ll Value
|
G: FnOnce(&'ll Value, &'ll Type) -> &'ll Value
|
||||||
{
|
{
|
||||||
|
@ -363,8 +363,8 @@ fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
|
||||||
if lhs_sz < rhs_sz {
|
if lhs_sz < rhs_sz {
|
||||||
trunc(rhs, lhs_llty)
|
trunc(rhs, lhs_llty)
|
||||||
} else if lhs_sz > rhs_sz {
|
} else if lhs_sz > rhs_sz {
|
||||||
// FIXME (#1877: If shifting by negative
|
// FIXME (#1877: If in the future shifting by negative
|
||||||
// values becomes not undefined then this is wrong.
|
// values is no longer undefined then this is wrong.
|
||||||
zext(rhs, lhs_llty)
|
zext(rhs, lhs_llty)
|
||||||
} else {
|
} else {
|
||||||
rhs
|
rhs
|
||||||
|
@ -495,10 +495,8 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'
|
||||||
let sig = common::ty_fn_sig(cx, fn_ty);
|
let sig = common::ty_fn_sig(cx, fn_ty);
|
||||||
let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
|
let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
|
||||||
|
|
||||||
let lldecl = match cx.instances.borrow().get(&instance) {
|
let lldecl = cx.instances.borrow().get(&instance).cloned().unwrap_or_else(||
|
||||||
Some(&val) => val,
|
bug!("Instance `{:?}` not already declared", instance));
|
||||||
None => bug!("Instance `{:?}` not already declared", instance)
|
|
||||||
};
|
|
||||||
|
|
||||||
cx.stats.borrow_mut().n_closures += 1;
|
cx.stats.borrow_mut().n_closures += 1;
|
||||||
|
|
||||||
|
@ -566,8 +564,8 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
|
||||||
if declare::get_defined_value(cx, "main").is_some() {
|
if declare::get_defined_value(cx, "main").is_some() {
|
||||||
// FIXME: We should be smart and show a better diagnostic here.
|
// FIXME: We should be smart and show a better diagnostic here.
|
||||||
cx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
|
cx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
|
||||||
.help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
|
.help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
|
||||||
.emit();
|
.emit();
|
||||||
cx.sess().abort_if_errors();
|
cx.sess().abort_if_errors();
|
||||||
bug!();
|
bug!();
|
||||||
}
|
}
|
||||||
|
@ -736,9 +734,9 @@ fn determine_cgu_reuse<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
rx: mpsc::Receiver<Box<dyn Any + Send>>)
|
rx: mpsc::Receiver<Box<dyn Any + Send>>)
|
||||||
-> OngoingCodegen {
|
-> OngoingCodegen
|
||||||
|
{
|
||||||
check_for_rustc_errors_attr(tcx);
|
check_for_rustc_errors_attr(tcx);
|
||||||
|
|
||||||
if let Some(true) = tcx.sess.opts.debugging_opts.thinlto {
|
if let Some(true) = tcx.sess.opts.debugging_opts.thinlto {
|
||||||
|
@ -803,8 +801,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
// Run the monomorphization collector and partition the collected items into
|
// Run the monomorphization collector and partition the collected items into
|
||||||
// codegen units.
|
// codegen units.
|
||||||
let codegen_units =
|
let codegen_units = tcx.collect_and_partition_mono_items(LOCAL_CRATE).1;
|
||||||
tcx.collect_and_partition_mono_items(LOCAL_CRATE).1;
|
|
||||||
let codegen_units = (*codegen_units).clone();
|
let codegen_units = (*codegen_units).clone();
|
||||||
|
|
||||||
// Force all codegen_unit queries so they are already either red or green
|
// Force all codegen_unit queries so they are already either red or green
|
||||||
|
@ -837,12 +834,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
.iter()
|
.iter()
|
||||||
.any(|(_, list)| {
|
.any(|(_, list)| {
|
||||||
use rustc::middle::dependency_format::Linkage;
|
use rustc::middle::dependency_format::Linkage;
|
||||||
list.iter().any(|linkage| {
|
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
|
||||||
match linkage {
|
|
||||||
Linkage::Dynamic => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
let allocator_module = if any_dynamic_crate {
|
let allocator_module = if any_dynamic_crate {
|
||||||
None
|
None
|
||||||
|
@ -988,7 +980,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>(
|
||||||
if mode_string != "lazy" {
|
if mode_string != "lazy" {
|
||||||
let message = format!("Unknown codegen-item collection mode '{}'. \
|
let message = format!("Unknown codegen-item collection mode '{}'. \
|
||||||
Falling back to 'lazy' mode.",
|
Falling back to 'lazy' mode.",
|
||||||
mode_string);
|
mode_string);
|
||||||
tcx.sess.warn(&message);
|
tcx.sess.warn(&message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1123,7 +1115,15 @@ impl CrateInfo {
|
||||||
info.load_wasm_imports(tcx, LOCAL_CRATE);
|
info.load_wasm_imports(tcx, LOCAL_CRATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for &cnum in tcx.crates().iter() {
|
let crates = tcx.crates();
|
||||||
|
|
||||||
|
let n_crates = crates.len();
|
||||||
|
info.native_libraries.reserve(n_crates);
|
||||||
|
info.crate_name.reserve(n_crates);
|
||||||
|
info.used_crate_source.reserve(n_crates);
|
||||||
|
info.missing_lang_items.reserve(n_crates);
|
||||||
|
|
||||||
|
for &cnum in crates.iter() {
|
||||||
info.native_libraries.insert(cnum, tcx.native_libraries(cnum));
|
info.native_libraries.insert(cnum, tcx.native_libraries(cnum));
|
||||||
info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
|
info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
|
||||||
info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
|
info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
|
||||||
|
@ -1165,11 +1165,12 @@ impl CrateInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_wasm_imports(&mut self, tcx: TyCtxt, cnum: CrateNum) {
|
fn load_wasm_imports(&mut self, tcx: TyCtxt, cnum: CrateNum) {
|
||||||
for (&id, module) in tcx.wasm_import_module_map(cnum).iter() {
|
self.wasm_imports.extend(tcx.wasm_import_module_map(cnum).iter().map(|(&id, module)| {
|
||||||
let instance = Instance::mono(tcx, id);
|
let instance = Instance::mono(tcx, id);
|
||||||
let import_name = tcx.symbol_name(instance);
|
let import_name = tcx.symbol_name(instance);
|
||||||
self.wasm_imports.insert(import_name.to_string(), module.clone());
|
|
||||||
}
|
(import_name.to_string(), module.clone())
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,10 +110,10 @@ impl Builder<'a, 'll, 'tcx> {
|
||||||
}
|
}
|
||||||
if self.cx.sess().count_llvm_insns() {
|
if self.cx.sess().count_llvm_insns() {
|
||||||
*self.cx.stats
|
*self.cx.stats
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.llvm_insns
|
.llvm_insns
|
||||||
.entry(category.to_string())
|
.entry(category.to_string())
|
||||||
.or_insert(0) += 1;
|
.or_insert(0) += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,9 +735,9 @@ impl Builder<'a, 'll, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
|
pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char,
|
||||||
inputs: &[&'ll Value], output: &'ll Type,
|
inputs: &[&'ll Value], output: &'ll Type,
|
||||||
volatile: bool, alignstack: bool,
|
volatile: bool, alignstack: bool,
|
||||||
dia: AsmDialect) -> Option<&'ll Value> {
|
dia: AsmDialect) -> Option<&'ll Value> {
|
||||||
self.count_insn("inlineasm");
|
self.count_insn("inlineasm");
|
||||||
|
|
||||||
let volatile = if volatile { llvm::True }
|
let volatile = if volatile { llvm::True }
|
||||||
|
@ -1093,7 +1093,7 @@ impl Builder<'a, 'll, 'tcx> {
|
||||||
) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
|
llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
|
||||||
order, failure_order, weak)
|
order, failure_order, weak)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn atomic_rmw(
|
pub fn atomic_rmw(
|
||||||
|
@ -1194,7 +1194,7 @@ impl Builder<'a, 'll, 'tcx> {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
return Cow::Owned(casted_args);
|
Cow::Owned(casted_args)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lifetime_start(&self, ptr: &'ll Value, size: Size) {
|
pub fn lifetime_start(&self, ptr: &'ll Value, size: Size) {
|
||||||
|
|
|
@ -336,16 +336,13 @@ pub fn langcall(tcx: TyCtxt,
|
||||||
msg: &str,
|
msg: &str,
|
||||||
li: LangItem)
|
li: LangItem)
|
||||||
-> DefId {
|
-> DefId {
|
||||||
match tcx.lang_items().require(li) {
|
tcx.lang_items().require(li).unwrap_or_else(|s| {
|
||||||
Ok(id) => id,
|
let msg = format!("{} {}", msg, s);
|
||||||
Err(s) => {
|
match span {
|
||||||
let msg = format!("{} {}", msg, s);
|
Some(span) => tcx.sess.span_fatal(span, &msg[..]),
|
||||||
match span {
|
None => tcx.sess.fatal(&msg[..]),
|
||||||
Some(span) => tcx.sess.span_fatal(span, &msg[..]),
|
|
||||||
None => tcx.sess.fatal(&msg[..]),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// To avoid UB from LLVM, these two functions mask RHS with an
|
// To avoid UB from LLVM, these two functions mask RHS with an
|
||||||
|
|
|
@ -124,7 +124,7 @@ pub fn get_static(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll Value {
|
||||||
assert!(!defined_in_current_codegen_unit,
|
assert!(!defined_in_current_codegen_unit,
|
||||||
"consts::get_static() should always hit the cache for \
|
"consts::get_static() should always hit the cache for \
|
||||||
statics defined in the same CGU, but did not for `{:?}`",
|
statics defined in the same CGU, but did not for `{:?}`",
|
||||||
def_id);
|
def_id);
|
||||||
|
|
||||||
let ty = instance.ty(cx.tcx);
|
let ty = instance.ty(cx.tcx);
|
||||||
let sym = cx.tcx.symbol_name(instance).as_str();
|
let sym = cx.tcx.symbol_name(instance).as_str();
|
||||||
|
@ -249,14 +249,13 @@ fn check_and_apply_linkage(
|
||||||
// extern "C" fn() from being non-null, so we can't just declare a
|
// extern "C" fn() from being non-null, so we can't just declare a
|
||||||
// static and call it a day. Some linkages (like weak) will make it such
|
// static and call it a day. Some linkages (like weak) will make it such
|
||||||
// that the static actually has a null value.
|
// that the static actually has a null value.
|
||||||
let llty2 = match ty.sty {
|
let llty2 = if let ty::RawPtr(ref mt) = ty.sty {
|
||||||
ty::RawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx),
|
cx.layout_of(mt.ty).llvm_type(cx)
|
||||||
_ => {
|
} else {
|
||||||
if span.is_some() {
|
if let Some(span) = span {
|
||||||
cx.sess().span_fatal(span.unwrap(), "must have type `*const T` or `*mut T`")
|
cx.sess().span_fatal(span, "must have type `*const T` or `*mut T`")
|
||||||
} else {
|
} else {
|
||||||
bug!("must have type `*const T` or `*mut T`")
|
bug!("must have type `*const T` or `*mut T`")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -273,9 +272,9 @@ fn check_and_apply_linkage(
|
||||||
let mut real_name = "_rust_extern_with_linkage_".to_string();
|
let mut real_name = "_rust_extern_with_linkage_".to_string();
|
||||||
real_name.push_str(&sym);
|
real_name.push_str(&sym);
|
||||||
let g2 = declare::define_global(cx, &real_name, llty).unwrap_or_else(||{
|
let g2 = declare::define_global(cx, &real_name, llty).unwrap_or_else(||{
|
||||||
if span.is_some() {
|
if let Some(span) = span {
|
||||||
cx.sess().span_fatal(
|
cx.sess().span_fatal(
|
||||||
span.unwrap(),
|
span,
|
||||||
&format!("symbol `{}` is already defined", &sym)
|
&format!("symbol `{}` is already defined", &sym)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -59,8 +59,8 @@ pub struct CodegenCx<'a, 'tcx: 'a> {
|
||||||
/// Cache instances of monomorphic and polymorphic items
|
/// Cache instances of monomorphic and polymorphic items
|
||||||
pub instances: RefCell<FxHashMap<Instance<'tcx>, &'a Value>>,
|
pub instances: RefCell<FxHashMap<Instance<'tcx>, &'a Value>>,
|
||||||
/// Cache generated vtables
|
/// Cache generated vtables
|
||||||
pub vtables: RefCell<FxHashMap<(Ty<'tcx>,
|
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>),
|
||||||
Option<ty::PolyExistentialTraitRef<'tcx>>), &'a Value>>,
|
&'a Value>>,
|
||||||
/// Cache of constant strings,
|
/// Cache of constant strings,
|
||||||
pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, &'a Value>>,
|
pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, &'a Value>>,
|
||||||
|
|
||||||
|
@ -213,9 +213,9 @@ pub unsafe fn create_module(
|
||||||
|
|
||||||
impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
||||||
crate fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
crate fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
codegen_unit: Arc<CodegenUnit<'tcx>>,
|
codegen_unit: Arc<CodegenUnit<'tcx>>,
|
||||||
llvm_module: &'a ::ModuleLlvm)
|
llvm_module: &'a ::ModuleLlvm)
|
||||||
-> CodegenCx<'a, 'tcx> {
|
-> CodegenCx<'a, 'tcx> {
|
||||||
// An interesting part of Windows which MSVC forces our hand on (and
|
// An interesting part of Windows which MSVC forces our hand on (and
|
||||||
// apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
|
// apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
|
||||||
// attributes in LLVM IR as well as native dependencies (in C these
|
// attributes in LLVM IR as well as native dependencies (in C these
|
||||||
|
@ -270,8 +270,8 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
||||||
let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
|
let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
|
||||||
let dctx = debuginfo::CrateDebugContext::new(llmod);
|
let dctx = debuginfo::CrateDebugContext::new(llmod);
|
||||||
debuginfo::metadata::compile_unit_metadata(tcx,
|
debuginfo::metadata::compile_unit_metadata(tcx,
|
||||||
&codegen_unit.name().as_str(),
|
&codegen_unit.name().as_str(),
|
||||||
&dctx);
|
&dctx);
|
||||||
Some(dctx)
|
Some(dctx)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -318,10 +318,8 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
|
||||||
if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
|
if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
match declare_intrinsic(self, key) {
|
|
||||||
Some(v) => return v,
|
declare_intrinsic(self, key).unwrap_or_else(|| bug!("unknown intrinsic '{}'", key))
|
||||||
None => bug!("unknown intrinsic '{}'", key)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a new symbol name with the given prefix. This symbol name must
|
/// Generate a new symbol name with the given prefix. This symbol name must
|
||||||
|
@ -465,9 +463,10 @@ impl LayoutOf for &'a CodegenCx<'ll, 'tcx> {
|
||||||
|
|
||||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
||||||
self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty))
|
self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty))
|
||||||
.unwrap_or_else(|e| match e {
|
.unwrap_or_else(|e| if let LayoutError::SizeOverflow(_) = e {
|
||||||
LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()),
|
self.sess().fatal(&e.to_string())
|
||||||
_ => bug!("failed to get layout for `{}`: {}", ty, e)
|
} else {
|
||||||
|
bug!("failed to get layout for `{}`: {}", ty, e)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -772,5 +771,6 @@ fn declare_intrinsic(cx: &CodegenCx<'ll, '_>, key: &str) -> Option<&'ll Value> {
|
||||||
ifn!("llvm.dbg.declare", fn(Type::metadata(cx), Type::metadata(cx)) -> void);
|
ifn!("llvm.dbg.declare", fn(Type::metadata(cx), Type::metadata(cx)) -> void);
|
||||||
ifn!("llvm.dbg.value", fn(Type::metadata(cx), t_i64, Type::metadata(cx)) -> void);
|
ifn!("llvm.dbg.value", fn(Type::metadata(cx), t_i64, Type::metadata(cx)) -> void);
|
||||||
}
|
}
|
||||||
return None;
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,8 +97,8 @@ pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Opt
|
||||||
C_usize(cx, std::cmp::max(sized_align, unsized_align) as u64)
|
C_usize(cx, std::cmp::max(sized_align, unsized_align) as u64)
|
||||||
}
|
}
|
||||||
_ => bx.select(bx.icmp(llvm::IntUGT, sized_align, unsized_align),
|
_ => bx.select(bx.icmp(llvm::IntUGT, sized_align, unsized_align),
|
||||||
sized_align,
|
sized_align,
|
||||||
unsized_align)
|
unsized_align)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Issue #27023: must add any necessary padding to `size`
|
// Issue #27023: must add any necessary padding to `size`
|
||||||
|
|
|
@ -115,8 +115,8 @@ pub fn codegen_intrinsic_call(
|
||||||
let llval = match name {
|
let llval = match name {
|
||||||
_ if simple.is_some() => {
|
_ if simple.is_some() => {
|
||||||
bx.call(simple.unwrap(),
|
bx.call(simple.unwrap(),
|
||||||
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
|
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
|
||||||
None)
|
None)
|
||||||
}
|
}
|
||||||
"unreachable" => {
|
"unreachable" => {
|
||||||
return;
|
return;
|
||||||
|
@ -373,7 +373,6 @@ pub fn codegen_intrinsic_call(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
|
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
|
||||||
let sty = &arg_tys[0].sty;
|
let sty = &arg_tys[0].sty;
|
||||||
|
@ -540,10 +539,9 @@ pub fn codegen_intrinsic_call(
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
let intr = match Intrinsic::find(&name) {
|
let intr = Intrinsic::find(&name).unwrap_or_else(||
|
||||||
Some(intr) => intr,
|
bug!("unknown intrinsic '{}'", name));
|
||||||
None => bug!("unknown intrinsic '{}'", name),
|
|
||||||
};
|
|
||||||
fn one<T>(x: Vec<T>) -> T {
|
fn one<T>(x: Vec<T>) -> T {
|
||||||
assert_eq!(x.len(), 1);
|
assert_eq!(x.len(), 1);
|
||||||
x.into_iter().next().unwrap()
|
x.into_iter().next().unwrap()
|
||||||
|
@ -822,8 +820,7 @@ fn codegen_msvc_try(
|
||||||
let i64p = Type::i64(cx).ptr_to();
|
let i64p = Type::i64(cx).ptr_to();
|
||||||
let ptr_align = bx.tcx().data_layout.pointer_align;
|
let ptr_align = bx.tcx().data_layout.pointer_align;
|
||||||
let slot = bx.alloca(i64p, "slot", ptr_align);
|
let slot = bx.alloca(i64p, "slot", ptr_align);
|
||||||
bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(),
|
bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None);
|
||||||
None);
|
|
||||||
|
|
||||||
normal.ret(C_i32(cx, 0));
|
normal.ret(C_i32(cx, 0));
|
||||||
|
|
||||||
|
@ -911,8 +908,7 @@ fn codegen_gnu_try(
|
||||||
// being thrown. The second value is a "selector" indicating which of
|
// being thrown. The second value is a "selector" indicating which of
|
||||||
// the landing pad clauses the exception's type had been matched to.
|
// the landing pad clauses the exception's type had been matched to.
|
||||||
// rust_try ignores the selector.
|
// rust_try ignores the selector.
|
||||||
let lpad_ty = Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)],
|
let lpad_ty = Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false);
|
||||||
false);
|
|
||||||
let vals = catch.landing_pad(lpad_ty, bx.cx.eh_personality(), 1);
|
let vals = catch.landing_pad(lpad_ty, bx.cx.eh_personality(), 1);
|
||||||
catch.add_clause(vals, C_null(Type::i8p(cx)));
|
catch.add_clause(vals, C_null(Type::i8p(cx)));
|
||||||
let ptr = catch.extract_value(vals, 0);
|
let ptr = catch.extract_value(vals, 0);
|
||||||
|
@ -976,7 +972,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
|
||||||
let output = tcx.types.i32;
|
let output = tcx.types.i32;
|
||||||
let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, codegen);
|
let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, codegen);
|
||||||
cx.rust_try_fn.set(Some(rust_try));
|
cx.rust_try_fn.set(Some(rust_try));
|
||||||
return rust_try
|
rust_try
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
|
fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
|
||||||
|
@ -1000,11 +996,11 @@ fn generic_simd_intrinsic(
|
||||||
($msg: tt, $($fmt: tt)*) => {
|
($msg: tt, $($fmt: tt)*) => {
|
||||||
span_invalid_monomorphization_error(
|
span_invalid_monomorphization_error(
|
||||||
bx.sess(), span,
|
bx.sess(), span,
|
||||||
&format!(concat!("invalid monomorphization of `{}` intrinsic: ",
|
&format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
|
||||||
$msg),
|
|
||||||
name, $($fmt)*));
|
name, $($fmt)*));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! return_error {
|
macro_rules! return_error {
|
||||||
($($fmt: tt)*) => {
|
($($fmt: tt)*) => {
|
||||||
{
|
{
|
||||||
|
@ -1021,14 +1017,13 @@ fn generic_simd_intrinsic(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! require_simd {
|
macro_rules! require_simd {
|
||||||
($ty: expr, $position: expr) => {
|
($ty: expr, $position: expr) => {
|
||||||
require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty)
|
require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let tcx = bx.tcx();
|
let tcx = bx.tcx();
|
||||||
let sig = tcx.normalize_erasing_late_bound_regions(
|
let sig = tcx.normalize_erasing_late_bound_regions(
|
||||||
ty::ParamEnv::reveal_all(),
|
ty::ParamEnv::reveal_all(),
|
||||||
|
@ -1075,11 +1070,8 @@ fn generic_simd_intrinsic(
|
||||||
}
|
}
|
||||||
|
|
||||||
if name.starts_with("simd_shuffle") {
|
if name.starts_with("simd_shuffle") {
|
||||||
let n: usize = match name["simd_shuffle".len()..].parse() {
|
let n: usize = name["simd_shuffle".len()..].parse().unwrap_or_else(|_|
|
||||||
Ok(n) => n,
|
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?"));
|
||||||
Err(_) => span_bug!(span,
|
|
||||||
"bad `simd_shuffle` instruction only caught in codegen?")
|
|
||||||
};
|
|
||||||
|
|
||||||
require_simd!(ret_ty, "return");
|
require_simd!(ret_ty, "return");
|
||||||
|
|
||||||
|
@ -1121,8 +1113,8 @@ fn generic_simd_intrinsic(
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(bx.shuffle_vector(args[0].immediate(),
|
return Ok(bx.shuffle_vector(args[0].immediate(),
|
||||||
args[1].immediate(),
|
args[1].immediate(),
|
||||||
C_vector(&indices)))
|
C_vector(&indices)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if name == "simd_insert" {
|
if name == "simd_insert" {
|
||||||
|
@ -1130,8 +1122,8 @@ fn generic_simd_intrinsic(
|
||||||
"expected inserted type `{}` (element of input `{}`), found `{}`",
|
"expected inserted type `{}` (element of input `{}`), found `{}`",
|
||||||
in_elem, in_ty, arg_tys[2]);
|
in_elem, in_ty, arg_tys[2]);
|
||||||
return Ok(bx.insert_element(args[0].immediate(),
|
return Ok(bx.insert_element(args[0].immediate(),
|
||||||
args[2].immediate(),
|
args[2].immediate(),
|
||||||
args[1].immediate()))
|
args[1].immediate()))
|
||||||
}
|
}
|
||||||
if name == "simd_extract" {
|
if name == "simd_extract" {
|
||||||
require!(ret_ty == in_elem,
|
require!(ret_ty == in_elem,
|
||||||
|
@ -1150,9 +1142,7 @@ fn generic_simd_intrinsic(
|
||||||
);
|
);
|
||||||
match m_elem_ty.sty {
|
match m_elem_ty.sty {
|
||||||
ty::Int(_) => {},
|
ty::Int(_) => {},
|
||||||
_ => {
|
_ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty)
|
||||||
return_error!("mask element type is `{}`, expected `i_`", m_elem_ty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// truncate the mask to a vector of i1s
|
// truncate the mask to a vector of i1s
|
||||||
let i1 = Type::i1(bx.cx);
|
let i1 = Type::i1(bx.cx);
|
||||||
|
@ -1177,8 +1167,7 @@ fn generic_simd_intrinsic(
|
||||||
($msg: tt, $($fmt: tt)*) => {
|
($msg: tt, $($fmt: tt)*) => {
|
||||||
span_invalid_monomorphization_error(
|
span_invalid_monomorphization_error(
|
||||||
bx.sess(), span,
|
bx.sess(), span,
|
||||||
&format!(concat!("invalid monomorphization of `{}` intrinsic: ",
|
&format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
|
||||||
$msg),
|
|
||||||
name, $($fmt)*));
|
name, $($fmt)*));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1223,63 +1212,53 @@ fn generic_simd_intrinsic(
|
||||||
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
|
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
|
||||||
None);
|
None);
|
||||||
unsafe { llvm::LLVMRustSetHasUnsafeAlgebra(c) };
|
unsafe { llvm::LLVMRustSetHasUnsafeAlgebra(c) };
|
||||||
return Ok(c);
|
Ok(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
if name == "simd_fsqrt" {
|
match name {
|
||||||
return simd_simple_float_intrinsic("sqrt", in_elem, in_ty, in_len, bx, span, args);
|
"simd_fsqrt" => {
|
||||||
}
|
return simd_simple_float_intrinsic("sqrt", in_elem, in_ty, in_len, bx, span, args);
|
||||||
|
}
|
||||||
if name == "simd_fsin" {
|
"simd_fsin" => {
|
||||||
return simd_simple_float_intrinsic("sin", in_elem, in_ty, in_len, bx, span, args);
|
return simd_simple_float_intrinsic("sin", in_elem, in_ty, in_len, bx, span, args);
|
||||||
}
|
}
|
||||||
|
"simd_fcos" => {
|
||||||
if name == "simd_fcos" {
|
return simd_simple_float_intrinsic("cos", in_elem, in_ty, in_len, bx, span, args);
|
||||||
return simd_simple_float_intrinsic("cos", in_elem, in_ty, in_len, bx, span, args);
|
}
|
||||||
}
|
"simd_fabs" => {
|
||||||
|
return simd_simple_float_intrinsic("fabs", in_elem, in_ty, in_len, bx, span, args);
|
||||||
if name == "simd_fabs" {
|
}
|
||||||
return simd_simple_float_intrinsic("fabs", in_elem, in_ty, in_len, bx, span, args);
|
"simd_floor" => {
|
||||||
}
|
return simd_simple_float_intrinsic("floor", in_elem, in_ty, in_len, bx, span, args);
|
||||||
|
}
|
||||||
if name == "simd_floor" {
|
"simd_ceil" => {
|
||||||
return simd_simple_float_intrinsic("floor", in_elem, in_ty, in_len, bx, span, args);
|
return simd_simple_float_intrinsic("ceil", in_elem, in_ty, in_len, bx, span, args);
|
||||||
}
|
}
|
||||||
|
"simd_fexp" => {
|
||||||
if name == "simd_ceil" {
|
return simd_simple_float_intrinsic("exp", in_elem, in_ty, in_len, bx, span, args);
|
||||||
return simd_simple_float_intrinsic("ceil", in_elem, in_ty, in_len, bx, span, args);
|
}
|
||||||
}
|
"simd_fexp2" => {
|
||||||
|
return simd_simple_float_intrinsic("exp2", in_elem, in_ty, in_len, bx, span, args);
|
||||||
if name == "simd_fexp" {
|
}
|
||||||
return simd_simple_float_intrinsic("exp", in_elem, in_ty, in_len, bx, span, args);
|
"simd_flog10" => {
|
||||||
}
|
return simd_simple_float_intrinsic("log10", in_elem, in_ty, in_len, bx, span, args);
|
||||||
|
}
|
||||||
if name == "simd_fexp2" {
|
"simd_flog2" => {
|
||||||
return simd_simple_float_intrinsic("exp2", in_elem, in_ty, in_len, bx, span, args);
|
return simd_simple_float_intrinsic("log2", in_elem, in_ty, in_len, bx, span, args);
|
||||||
}
|
}
|
||||||
|
"simd_flog" => {
|
||||||
if name == "simd_flog10" {
|
return simd_simple_float_intrinsic("log", in_elem, in_ty, in_len, bx, span, args);
|
||||||
return simd_simple_float_intrinsic("log10", in_elem, in_ty, in_len, bx, span, args);
|
}
|
||||||
}
|
"simd_fpowi" => {
|
||||||
|
return simd_simple_float_intrinsic("powi", in_elem, in_ty, in_len, bx, span, args);
|
||||||
if name == "simd_flog2" {
|
}
|
||||||
return simd_simple_float_intrinsic("log2", in_elem, in_ty, in_len, bx, span, args);
|
"simd_fpow" => {
|
||||||
}
|
return simd_simple_float_intrinsic("pow", in_elem, in_ty, in_len, bx, span, args);
|
||||||
|
}
|
||||||
if name == "simd_flog" {
|
"simd_fma" => {
|
||||||
return simd_simple_float_intrinsic("log", in_elem, in_ty, in_len, bx, span, args);
|
return simd_simple_float_intrinsic("fma", in_elem, in_ty, in_len, bx, span, args);
|
||||||
}
|
}
|
||||||
|
_ => { /* fallthrough */ }
|
||||||
if name == "simd_fpowi" {
|
|
||||||
return simd_simple_float_intrinsic("powi", in_elem, in_ty, in_len, bx, span, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "simd_fpow" {
|
|
||||||
return simd_simple_float_intrinsic("pow", in_elem, in_ty, in_len, bx, span, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "simd_fma" {
|
|
||||||
return simd_simple_float_intrinsic("fma", in_elem, in_ty, in_len, bx, span, args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: use:
|
// FIXME: use:
|
||||||
|
@ -1312,7 +1291,7 @@ fn generic_simd_intrinsic(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if name == "simd_gather" {
|
if name == "simd_gather" {
|
||||||
// simd_gather(values: <N x T>, pointers: <N x *_ T>,
|
// simd_gather(values: <N x T>, pointers: <N x *_ T>,
|
||||||
// mask: <N x i{M}>) -> <N x T>
|
// mask: <N x i{M}>) -> <N x T>
|
||||||
// * N: number of elements in the input vectors
|
// * N: number of elements in the input vectors
|
||||||
|
@ -1360,7 +1339,7 @@ fn generic_simd_intrinsic(
|
||||||
// to the element type of the first argument
|
// to the element type of the first argument
|
||||||
let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).sty {
|
let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).sty {
|
||||||
ty::RawPtr(p) if p.ty == in_elem => (ptr_count(arg_tys[1].simd_type(tcx)),
|
ty::RawPtr(p) if p.ty == in_elem => (ptr_count(arg_tys[1].simd_type(tcx)),
|
||||||
non_ptr(arg_tys[1].simd_type(tcx))),
|
non_ptr(arg_tys[1].simd_type(tcx))),
|
||||||
_ => {
|
_ => {
|
||||||
require!(false, "expected element type `{}` of second argument `{}` \
|
require!(false, "expected element type `{}` of second argument `{}` \
|
||||||
to be a pointer to the element type `{}` of the first \
|
to be a pointer to the element type `{}` of the first \
|
||||||
|
@ -1371,7 +1350,7 @@ fn generic_simd_intrinsic(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assert!(pointer_count > 0);
|
assert!(pointer_count > 0);
|
||||||
assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx)));
|
assert_eq!(pointer_count - 1, ptr_count(arg_tys[0].simd_type(tcx)));
|
||||||
assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx)));
|
assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx)));
|
||||||
|
|
||||||
// The element type of the third argument must be a signed integer type of any width:
|
// The element type of the third argument must be a signed integer type of any width:
|
||||||
|
@ -1414,7 +1393,7 @@ fn generic_simd_intrinsic(
|
||||||
return Ok(v);
|
return Ok(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
if name == "simd_scatter" {
|
if name == "simd_scatter" {
|
||||||
// simd_scatter(values: <N x T>, pointers: <N x *mut T>,
|
// simd_scatter(values: <N x T>, pointers: <N x *mut T>,
|
||||||
// mask: <N x i{M}>) -> ()
|
// mask: <N x i{M}>) -> ()
|
||||||
// * N: number of elements in the input vectors
|
// * N: number of elements in the input vectors
|
||||||
|
@ -1468,7 +1447,7 @@ fn generic_simd_intrinsic(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assert!(pointer_count > 0);
|
assert!(pointer_count > 0);
|
||||||
assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx)));
|
assert_eq!(pointer_count - 1, ptr_count(arg_tys[0].simd_type(tcx)));
|
||||||
assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx)));
|
assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx)));
|
||||||
|
|
||||||
// The element type of the third argument must be a signed integer type of any width:
|
// The element type of the third argument must be a signed integer type of any width:
|
||||||
|
@ -1570,7 +1549,6 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
Ok(bx.$float_reduce(acc, args[0].immediate()))
|
Ok(bx.$float_reduce(acc, args[0].immediate()))
|
||||||
}
|
}
|
||||||
|
@ -1750,9 +1728,9 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
require!(false,
|
require!(false,
|
||||||
"unsupported operation on `{}` with element `{}`",
|
"unsupported operation on `{}` with element `{}`",
|
||||||
in_ty,
|
in_ty,
|
||||||
in_elem)
|
in_elem)
|
||||||
})*
|
})*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,7 +306,7 @@ impl ModuleCodegen {
|
||||||
};
|
};
|
||||||
let bytecode_compressed = if emit_bc_compressed {
|
let bytecode_compressed = if emit_bc_compressed {
|
||||||
Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
|
Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
|
||||||
.with_extension(RLIB_BYTECODE_EXTENSION))
|
.with_extension(RLIB_BYTECODE_EXTENSION))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,8 +52,9 @@ fn require_inited() {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn configure_llvm(sess: &Session) {
|
unsafe fn configure_llvm(sess: &Session) {
|
||||||
let mut llvm_c_strs = Vec::new();
|
let n_args = sess.opts.cg.llvm_args.len();
|
||||||
let mut llvm_args = Vec::new();
|
let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
|
||||||
|
let mut llvm_args = Vec::with_capacity(n_args + 1);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut add = |arg: &str| {
|
let mut add = |arg: &str| {
|
||||||
|
|
|
@ -63,7 +63,7 @@ impl MetadataLoader for LlvmMetadataLoader {
|
||||||
let of = ObjectFile::new(mb)
|
let of = ObjectFile::new(mb)
|
||||||
.map(|of| OwningRef::new(box of))
|
.map(|of| OwningRef::new(box of))
|
||||||
.ok_or_else(|| format!("provided path not an object file: '{}'",
|
.ok_or_else(|| format!("provided path not an object file: '{}'",
|
||||||
filename.display()))?;
|
filename.display()))?;
|
||||||
let buf = of.try_map(|of| search_meta_section(of, target, filename))?;
|
let buf = of.try_map(|of| search_meta_section(of, target, filename))?;
|
||||||
Ok(rustc_erase_owner!(buf))
|
Ok(rustc_erase_owner!(buf))
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,9 +151,9 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_place(&mut self,
|
fn visit_place(&mut self,
|
||||||
place: &mir::Place<'tcx>,
|
place: &mir::Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
debug!("visit_place(place={:?}, context={:?})", place, context);
|
debug!("visit_place(place={:?}, context={:?})", place, context);
|
||||||
let cx = self.fx.cx;
|
let cx = self.fx.cx;
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,9 @@ impl FunctionCx<'a, 'll, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_terminator(&mut self,
|
fn codegen_terminator(&mut self,
|
||||||
mut bx: Builder<'a, 'll, 'tcx>,
|
mut bx: Builder<'a, 'll, 'tcx>,
|
||||||
bb: mir::BasicBlock,
|
bb: mir::BasicBlock,
|
||||||
terminator: &mir::Terminator<'tcx>)
|
terminator: &mir::Terminator<'tcx>)
|
||||||
{
|
{
|
||||||
debug!("codegen_terminator: {:?}", terminator);
|
debug!("codegen_terminator: {:?}", terminator);
|
||||||
|
|
||||||
|
|
|
@ -108,8 +108,8 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
||||||
match *self.as_mono_item() {
|
match *self.as_mono_item() {
|
||||||
MonoItem::Fn(instance) => {
|
MonoItem::Fn(instance) => {
|
||||||
format!("Fn({:?}, {})",
|
format!("Fn({:?}, {})",
|
||||||
instance.def,
|
instance.def,
|
||||||
instance.substs.as_ptr() as usize)
|
instance.substs.as_ptr() as usize)
|
||||||
}
|
}
|
||||||
MonoItem::Static(id) => {
|
MonoItem::Static(id) => {
|
||||||
format!("Static({:?})", id)
|
format!("Static({:?})", id)
|
||||||
|
|
|
@ -65,13 +65,12 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
let mut name = String::with_capacity(32);
|
let mut name = String::with_capacity(32);
|
||||||
let printer = DefPathBasedNames::new(cx.tcx, true, true);
|
let printer = DefPathBasedNames::new(cx.tcx, true, true);
|
||||||
printer.push_type_name(layout.ty, &mut name);
|
printer.push_type_name(layout.ty, &mut name);
|
||||||
match (&layout.ty.sty, &layout.variants) {
|
if let (&ty::Adt(def, _), &layout::Variants::Single { index })
|
||||||
(&ty::Adt(def, _), &layout::Variants::Single { index }) => {
|
= (&layout.ty.sty, &layout.variants)
|
||||||
if def.is_enum() && !def.variants.is_empty() {
|
{
|
||||||
write!(&mut name, "::{}", def.variants[index].name).unwrap();
|
if def.is_enum() && !def.variants.is_empty() {
|
||||||
}
|
write!(&mut name, "::{}", def.variants[index].name).unwrap();
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
Some(name)
|
Some(name)
|
||||||
}
|
}
|
||||||
|
@ -132,7 +131,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
|
|
||||||
debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?} \
|
debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?} \
|
||||||
effective_field_align: {}",
|
effective_field_align: {}",
|
||||||
i, field, offset, target_offset, effective_field_align.abi());
|
i, field, offset, target_offset, effective_field_align.abi());
|
||||||
assert!(target_offset >= offset);
|
assert!(target_offset >= offset);
|
||||||
let padding = target_offset - offset;
|
let padding = target_offset - offset;
|
||||||
let padding_align = prev_effective_align.min(effective_field_align);
|
let padding_align = prev_effective_align.min(effective_field_align);
|
||||||
|
@ -155,7 +154,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}",
|
debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}",
|
||||||
padding, offset, layout.size);
|
padding, offset, layout.size);
|
||||||
result.push(Type::padding_filler(cx, padding, padding_align));
|
result.push(Type::padding_filler(cx, padding, padding_align));
|
||||||
assert!(result.len() == 1 + field_count * 2);
|
assert_eq!(result.len(), 1 + field_count * 2);
|
||||||
} else {
|
} else {
|
||||||
debug!("struct_llfields: offset: {:?} stride: {:?}",
|
debug!("struct_llfields: offset: {:?} stride: {:?}",
|
||||||
offset, layout.size);
|
offset, layout.size);
|
||||||
|
|
|
@ -34,6 +34,6 @@ impl fmt::Debug for Value {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
f.write_str(&llvm::build_string(|s| unsafe {
|
f.write_str(&llvm::build_string(|s| unsafe {
|
||||||
llvm::LLVMRustWriteValueToString(self, s);
|
llvm::LLVMRustWriteValueToString(self, s);
|
||||||
}).expect("nun-UTF8 value description from LLVM"))
|
}).expect("non-UTF8 value description from LLVM"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue