use back::symbol_export::{self, ExportedSymbols};
use llvm::{Linkage, ValueRef, Vector, get_param};
use llvm;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::hir::def_id::LOCAL_CRATE;
use middle::lang_items::StartFnLangItem;
-use rustc::ty::subst::Substs;
-use rustc::mir::tcx::LvalueTy;
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::adjustment::CustomCoerceUnsized;
-use rustc::dep_graph::{DepNode, WorkProduct};
+use rustc::dep_graph::{AssertDepGraphSafe, DepNode, WorkProduct};
use rustc::hir::map as hir_map;
use rustc::util::common::time;
use session::config::{self, NoDebugInfo};
use rustc_incremental::IncrementalHashesMap;
use session::{self, DataTypeKind, Session};
-use abi::{self, Abi, FnType};
+use abi;
use mir::lvalue::LvalueRef;
-use adt;
use attributes;
use builder::Builder;
use callee::{Callee};
use debuginfo;
use declare;
use machine;
-use machine::{llalign_of_min, llsize_of};
+use machine::llsize_of;
use meth;
use mir;
use monomorphize::{self, Instance};
use type_::Type;
use type_of;
use value::Value;
-use Disr;
use util::nodemap::{NodeSet, FxHashMap, FxHashSet};
use libc::c_uint;
b.load(ptr, alignment.to_align())
};
- // FIXME: emit metadata on `meta`.
- let meta = b.load(get_meta(b, src), alignment.to_align());
+ let meta = get_meta(b, src);
+ let meta_ty = val_ty(meta);
+ // If the 'meta' field is a pointer, it's a vtable, so use load_nonnull
+ // instead
+ let meta = if meta_ty.element_type().kind() == llvm::TypeKind::Pointer {
+ b.load_nonnull(meta, None)
+ } else {
+ b.load(meta, None)
+ };
(ptr, meta)
}
}
pub fn call_memset<'a, 'tcx>(b: &Builder<'a, 'tcx>,
- ptr: ValueRef,
- fill_byte: ValueRef,
- size: ValueRef,
- align: ValueRef,
- volatile: bool) -> ValueRef {
+ ptr: ValueRef,
+ fill_byte: ValueRef,
+ size: ValueRef,
+ align: ValueRef,
+ volatile: bool) -> ValueRef {
let ptr_width = &b.ccx.sess().target.target.target_pointer_width[..];
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
let llintrinsicfn = b.ccx.get_intrinsic(&intrinsic_key);
let _s = if ccx.sess().trans_stats() {
let mut instance_name = String::new();
DefPathBasedNames::new(ccx.tcx(), true, true)
- .push_def_path(instance.def, &mut instance_name);
+ .push_def_path(instance.def_id(), &mut instance_name);
Some(StatRecorder::new(ccx, instance_name))
} else {
None
// release builds.
info!("trans_instance({})", instance);
- let fn_ty = ccx.tcx().item_type(instance.def);
- let fn_ty = ccx.tcx().erase_regions(&fn_ty);
- let fn_ty = monomorphize::apply_param_substs(ccx.shared(), instance.substs, &fn_ty);
-
- let ty::BareFnTy { abi, ref sig, .. } = *common::ty_fn_ty(ccx, fn_ty);
- let sig = ccx.tcx().erase_late_bound_regions_and_normalize(sig);
+ let fn_ty = common::instance_ty(ccx.shared(), &instance);
+ let sig = common::ty_fn_sig(ccx, fn_ty);
+ let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
let lldecl = match ccx.instances().borrow().get(&instance) {
Some(&val) => val,
attributes::emit_uwtable(lldecl, true);
}
- let fn_ty = FnType::new(ccx, abi, &sig, &[]);
-
- let mir = ccx.tcx().item_mir(instance.def);
- mir::trans_mir(ccx, lldecl, fn_ty, &mir, instance, &sig, abi);
-}
-
-pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
- def_id: DefId,
- substs: &'tcx Substs<'tcx>,
- disr: Disr,
- llfn: ValueRef) {
- attributes::inline(llfn, attributes::InlineAttr::Hint);
- attributes::set_frame_pointer_elimination(ccx, llfn);
-
- let ctor_ty = ccx.tcx().item_type(def_id);
- let ctor_ty = monomorphize::apply_param_substs(ccx.shared(), substs, &ctor_ty);
-
- let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&ctor_ty.fn_sig());
- let fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
-
- let bcx = Builder::new_block(ccx, llfn, "entry-block");
- if !fn_ty.ret.is_ignore() {
- // But if there are no nested returns, we skip the indirection
- // and have a single retslot
- let dest = if fn_ty.ret.is_indirect() {
- get_param(llfn, 0)
- } else {
- // We create an alloca to hold a pointer of type `ret.original_ty`
- // which will hold the pointer to the right alloca which has the
- // final ret value
- bcx.alloca(fn_ty.ret.memory_ty(ccx), "sret_slot")
- };
- // Can return unsized value
- let mut dest_val = LvalueRef::new_sized_ty(dest, sig.output(), Alignment::AbiAligned);
- dest_val.ty = LvalueTy::Downcast {
- adt_def: sig.output().ty_adt_def().unwrap(),
- substs: substs,
- variant_index: disr.0 as usize,
- };
- let mut llarg_idx = fn_ty.ret.is_indirect() as usize;
- let mut arg_idx = 0;
- for (i, arg_ty) in sig.inputs().iter().enumerate() {
- let (lldestptr, _) = dest_val.trans_field_ptr(&bcx, i);
- let arg = &fn_ty.args[arg_idx];
- arg_idx += 1;
- if common::type_is_fat_ptr(bcx.ccx, arg_ty) {
- let meta = &fn_ty.args[arg_idx];
- arg_idx += 1;
- arg.store_fn_arg(&bcx, &mut llarg_idx, get_dataptr(&bcx, lldestptr));
- meta.store_fn_arg(&bcx, &mut llarg_idx, get_meta(&bcx, lldestptr));
- } else {
- arg.store_fn_arg(&bcx, &mut llarg_idx, lldestptr);
- }
- }
- adt::trans_set_discr(&bcx, sig.output(), dest, disr);
-
- if fn_ty.ret.is_indirect() {
- bcx.ret_void();
- return;
- }
-
- if let Some(cast_ty) = fn_ty.ret.cast {
- bcx.ret(bcx.load(
- bcx.pointercast(dest, cast_ty.ptr_to()),
- Some(llalign_of_min(ccx, fn_ty.ret.ty))
- ));
- } else {
- bcx.ret(bcx.load(dest, None))
- }
- } else {
- bcx.ret_void();
- }
+ let mir = ccx.tcx().instance_mir(instance.def);
+ mir::trans_mir(ccx, lldecl, &mir, instance, sig);
}
pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
}
/// Create the `main` function which will initialise the rust runtime and call
-/// users’ main function.
+/// users main function.
pub fn maybe_create_entry_wrapper(ccx: &CrateContext) {
let (main_def_id, span) = match *ccx.sess().entry_fn.borrow() {
Some((id, span)) => {
ccx.tcx().sess.span_fatal(span, "compilation successful");
}
- let instance = Instance::mono(ccx.shared(), main_def_id);
+ let instance = Instance::mono(ccx.tcx(), main_def_id);
if !ccx.codegen_unit().contains_item(&TransItem::Fn(instance)) {
// We want to create the wrapper in the same codegen unit as Rust's main
let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis;
let exported_symbols = find_exported_symbols(tcx, reachable);
- let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks {
- v
- } else {
- tcx.sess.opts.debug_assertions
- };
+ let check_overflow = tcx.sess.overflow_checks();
let link_meta = link::build_link_meta(incremental_hashes_map, &name);
// Instantiate translation items without filling out definitions yet...
for ccx in crate_context_list.iter_need_trans() {
- let cgu = ccx.codegen_unit();
- let trans_items = cgu.items_in_deterministic_order(tcx, &symbol_map);
-
- tcx.dep_graph.with_task(cgu.work_product_dep_node(), || {
+ let dep_node = ccx.codegen_unit().work_product_dep_node();
+ tcx.dep_graph.with_task(dep_node,
+ ccx,
+ AssertDepGraphSafe(symbol_map.clone()),
+ trans_decl_task);
+
+ fn trans_decl_task<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
+ symbol_map: AssertDepGraphSafe<Rc<SymbolMap<'tcx>>>) {
+ // FIXME(#40304): Instead of this, the symbol-map should be an
+ // on-demand thing that we compute.
+ let AssertDepGraphSafe(symbol_map) = symbol_map;
+ let cgu = ccx.codegen_unit();
+ let trans_items = cgu.items_in_deterministic_order(ccx.tcx(), &symbol_map);
for (trans_item, linkage) in trans_items {
trans_item.predefine(&ccx, linkage);
}
- });
+ }
}
// ... and now that we have everything pre-defined, fill out those definitions.
for ccx in crate_context_list.iter_need_trans() {
- let cgu = ccx.codegen_unit();
- let trans_items = cgu.items_in_deterministic_order(tcx, &symbol_map);
- tcx.dep_graph.with_task(cgu.work_product_dep_node(), || {
+ let dep_node = ccx.codegen_unit().work_product_dep_node();
+ tcx.dep_graph.with_task(dep_node,
+ ccx,
+ AssertDepGraphSafe(symbol_map.clone()),
+ trans_def_task);
+
+ fn trans_def_task<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
+ symbol_map: AssertDepGraphSafe<Rc<SymbolMap<'tcx>>>) {
+ // FIXME(#40304): Instead of this, the symbol-map should be an
+ // on-demand thing that we compute.
+ let AssertDepGraphSafe(symbol_map) = symbol_map;
+ let cgu = ccx.codegen_unit();
+ let trans_items = cgu.items_in_deterministic_order(ccx.tcx(), &symbol_map);
for (trans_item, _) in trans_items {
trans_item.define(&ccx);
}
if ccx.sess().opts.debuginfo != NoDebugInfo {
debuginfo::finalize(&ccx);
}
- });
+ }
}
symbol_names_test::report_symbol_names(&shared_ccx);