1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Translate the completed AST to the LLVM IR.
13 //! Some functions here, such as trans_block and trans_expr, return a value --
14 //! the result of the translation to LLVM -- while others, such as trans_fn
15 //! and trans_item, are called only for the side effect of adding a
16 //! particular definition to the LLVM IR output we're producing.
18 //! Hopefully useful general knowledge about trans:
20 //! * There's no way to find out the Ty type of a ValueRef. Doing so
21 //! would be "trying to get the eggs out of an omelette" (credit:
22 //! pcwalton). You can, instead, find out its TypeRef by calling val_ty,
23 //! but one TypeRef corresponds to many `Ty`s; for instance, tup(int, int,
24 //! int) and rec(x=int, y=int, z=int) will have the same TypeRef.
26 use super::ModuleLlvm
;
27 use super::ModuleSource
;
28 use super::ModuleTranslation
;
29 use super::ModuleKind
;
33 use back
::write
::{self, OngoingCrateTranslation, create_target_machine}
;
34 use llvm
::{ContextRef, ModuleRef, ValueRef, Vector, get_param}
;
37 use rustc
::hir
::def_id
::{CrateNum, DefId, LOCAL_CRATE}
;
38 use rustc
::middle
::lang_items
::StartFnLangItem
;
39 use rustc
::middle
::weak_lang_items
;
40 use rustc
::mir
::mono
::{Linkage, Visibility, Stats}
;
41 use rustc
::middle
::cstore
::{EncodedMetadata}
;
42 use rustc
::ty
::{self, Ty, TyCtxt}
;
43 use rustc
::ty
::layout
::{self, Align, TyLayout, LayoutOf}
;
44 use rustc
::ty
::maps
::Providers
;
45 use rustc
::dep_graph
::{DepNode, DepConstructor}
;
46 use rustc
::ty
::subst
::Kind
;
47 use rustc
::middle
::cstore
::{self, LinkMeta, LinkagePreference}
;
48 use rustc
::middle
::exported_symbols
;
49 use rustc
::util
::common
::{time, print_time_passes_entry}
;
50 use rustc
::session
::config
::{self, NoDebugInfo}
;
51 use rustc
::session
::Session
;
52 use rustc_incremental
;
54 use mir
::place
::PlaceRef
;
56 use builder
::{Builder, MemFlags}
;
58 use common
::{C_bool, C_bytes_in_context, C_i32, C_usize}
;
59 use rustc_mir
::monomorphize
::collector
::{self, MonoItemCollectionMode}
;
60 use common
::{self, C_struct_in_context, C_array, val_ty}
;
62 use context
::{self, CodegenCx}
;
67 use monomorphize
::Instance
;
68 use monomorphize
::partitioning
::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt}
;
69 use rustc_trans_utils
::symbol_names_test
;
71 use trans_item
::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames}
;
73 use type_of
::LayoutLlvmExt
;
74 use rustc
::util
::nodemap
::{FxHashMap, FxHashSet, DefIdSet}
;
76 use rustc_data_structures
::sync
::Lrc
;
77 use rustc_target
::spec
::TargetTriple
;
80 use std
::collections
::BTreeMap
;
81 use std
::ffi
::CString
;
84 use std
::time
::{Instant, Duration}
;
89 use syntax_pos
::symbol
::InternedString
;
94 use mir
::operand
::OperandValue
;
96 pub use rustc_trans_utils
::check_for_rustc_errors_attr
;
98 pub struct StatRecorder
<'a
, 'tcx
: 'a
> {
99 cx
: &'a CodegenCx
<'a
, 'tcx
>,
100 name
: Option
<String
>,
104 impl<'a
, 'tcx
> StatRecorder
<'a
, 'tcx
> {
105 pub fn new(cx
: &'a CodegenCx
<'a
, 'tcx
>, name
: String
) -> StatRecorder
<'a
, 'tcx
> {
106 let istart
= cx
.stats
.borrow().n_llvm_insns
;
115 impl<'a
, 'tcx
> Drop
for StatRecorder
<'a
, 'tcx
> {
117 if self.cx
.sess().trans_stats() {
118 let mut stats
= self.cx
.stats
.borrow_mut();
119 let iend
= stats
.n_llvm_insns
;
120 stats
.fn_stats
.push((self.name
.take().unwrap(), iend
- self.istart
));
122 // Reset LLVM insn count to avoid compound costs.
123 stats
.n_llvm_insns
= self.istart
;
128 pub fn bin_op_to_icmp_predicate(op
: hir
::BinOp_
,
130 -> llvm
::IntPredicate
{
132 hir
::BiEq
=> llvm
::IntEQ
,
133 hir
::BiNe
=> llvm
::IntNE
,
134 hir
::BiLt
=> if signed { llvm::IntSLT }
else { llvm::IntULT }
,
135 hir
::BiLe
=> if signed { llvm::IntSLE }
else { llvm::IntULE }
,
136 hir
::BiGt
=> if signed { llvm::IntSGT }
else { llvm::IntUGT }
,
137 hir
::BiGe
=> if signed { llvm::IntSGE }
else { llvm::IntUGE }
,
139 bug
!("comparison_op_to_icmp_predicate: expected comparison operator, \
146 pub fn bin_op_to_fcmp_predicate(op
: hir
::BinOp_
) -> llvm
::RealPredicate
{
148 hir
::BiEq
=> llvm
::RealOEQ
,
149 hir
::BiNe
=> llvm
::RealUNE
,
150 hir
::BiLt
=> llvm
::RealOLT
,
151 hir
::BiLe
=> llvm
::RealOLE
,
152 hir
::BiGt
=> llvm
::RealOGT
,
153 hir
::BiGe
=> llvm
::RealOGE
,
155 bug
!("comparison_op_to_fcmp_predicate: expected comparison operator, \
162 pub fn compare_simd_types
<'a
, 'tcx
>(
163 bx
: &Builder
<'a
, 'tcx
>,
170 let signed
= match t
.sty
{
172 let cmp
= bin_op_to_fcmp_predicate(op
);
173 return bx
.sext(bx
.fcmp(cmp
, lhs
, rhs
), ret_ty
);
175 ty
::TyUint(_
) => false,
176 ty
::TyInt(_
) => true,
177 _
=> bug
!("compare_simd_types: invalid SIMD type"),
180 let cmp
= bin_op_to_icmp_predicate(op
, signed
);
181 // LLVM outputs an `< size x i1 >`, so we need to perform a sign extension
182 // to get the correctly sized type. This will compile to a single instruction
183 // once the IR is converted to assembly if the SIMD instruction is supported
184 // by the target architecture.
185 bx
.sext(bx
.icmp(cmp
, lhs
, rhs
), ret_ty
)
188 /// Retrieve the information we are losing (making dynamic) in an unsizing
191 /// The `old_info` argument is a bit funny. It is intended for use
192 /// in an upcast, where the new vtable for an object will be derived
193 /// from the old one.
194 pub fn unsized_info
<'cx
, 'tcx
>(cx
: &CodegenCx
<'cx
, 'tcx
>,
197 old_info
: Option
<ValueRef
>)
199 let (source
, target
) = cx
.tcx
.struct_lockstep_tails(source
, target
);
200 match (&source
.sty
, &target
.sty
) {
201 (&ty
::TyArray(_
, len
), &ty
::TySlice(_
)) => {
202 C_usize(cx
, len
.val
.unwrap_u64())
204 (&ty
::TyDynamic(..), &ty
::TyDynamic(..)) => {
205 // For now, upcasts are limited to changes in marker
206 // traits, and hence never actually require an actual
207 // change to the vtable.
208 old_info
.expect("unsized_info: missing old info for trait upcast")
210 (_
, &ty
::TyDynamic(ref data
, ..)) => {
211 let vtable_ptr
= cx
.layout_of(cx
.tcx
.mk_mut_ptr(target
))
212 .field(cx
, abi
::FAT_PTR_EXTRA
);
213 consts
::ptrcast(meth
::get_vtable(cx
, source
, data
.principal()),
214 vtable_ptr
.llvm_type(cx
))
216 _
=> bug
!("unsized_info: invalid unsizing {:?} -> {:?}",
222 /// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer.
223 pub fn unsize_thin_ptr
<'a
, 'tcx
>(
224 bx
: &Builder
<'a
, 'tcx
>,
228 ) -> (ValueRef
, ValueRef
) {
229 debug
!("unsize_thin_ptr: {:?} => {:?}", src_ty
, dst_ty
);
230 match (&src_ty
.sty
, &dst_ty
.sty
) {
231 (&ty
::TyRef(_
, ty
::TypeAndMut { ty: a, .. }
),
232 &ty
::TyRef(_
, ty
::TypeAndMut { ty: b, .. }
)) |
233 (&ty
::TyRef(_
, ty
::TypeAndMut { ty: a, .. }
),
234 &ty
::TyRawPtr(ty
::TypeAndMut { ty: b, .. }
)) |
235 (&ty
::TyRawPtr(ty
::TypeAndMut { ty: a, .. }
),
236 &ty
::TyRawPtr(ty
::TypeAndMut { ty: b, .. }
)) => {
237 assert
!(bx
.cx
.type_is_sized(a
));
238 let ptr_ty
= bx
.cx
.layout_of(b
).llvm_type(bx
.cx
).ptr_to();
239 (bx
.pointercast(src
, ptr_ty
), unsized_info(bx
.cx
, a
, b
, None
))
241 (&ty
::TyAdt(def_a
, _
), &ty
::TyAdt(def_b
, _
)) if def_a
.is_box() && def_b
.is_box() => {
242 let (a
, b
) = (src_ty
.boxed_ty(), dst_ty
.boxed_ty());
243 assert
!(bx
.cx
.type_is_sized(a
));
244 let ptr_ty
= bx
.cx
.layout_of(b
).llvm_type(bx
.cx
).ptr_to();
245 (bx
.pointercast(src
, ptr_ty
), unsized_info(bx
.cx
, a
, b
, None
))
247 (&ty
::TyAdt(def_a
, _
), &ty
::TyAdt(def_b
, _
)) => {
248 assert_eq
!(def_a
, def_b
);
250 let src_layout
= bx
.cx
.layout_of(src_ty
);
251 let dst_layout
= bx
.cx
.layout_of(dst_ty
);
252 let mut result
= None
;
253 for i
in 0..src_layout
.fields
.count() {
254 let src_f
= src_layout
.field(bx
.cx
, i
);
255 assert_eq
!(src_layout
.fields
.offset(i
).bytes(), 0);
256 assert_eq
!(dst_layout
.fields
.offset(i
).bytes(), 0);
260 assert_eq
!(src_layout
.size
, src_f
.size
);
262 let dst_f
= dst_layout
.field(bx
.cx
, i
);
263 assert_ne
!(src_f
.ty
, dst_f
.ty
);
264 assert_eq
!(result
, None
);
265 result
= Some(unsize_thin_ptr(bx
, src
, src_f
.ty
, dst_f
.ty
));
267 let (lldata
, llextra
) = result
.unwrap();
268 // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
269 (bx
.bitcast(lldata
, dst_layout
.scalar_pair_element_llvm_type(bx
.cx
, 0)),
270 bx
.bitcast(llextra
, dst_layout
.scalar_pair_element_llvm_type(bx
.cx
, 1)))
272 _
=> bug
!("unsize_thin_ptr: called on bad types"),
276 /// Coerce `src`, which is a reference to a value of type `src_ty`,
277 /// to a value of type `dst_ty` and store the result in `dst`
278 pub fn coerce_unsized_into
<'a
, 'tcx
>(bx
: &Builder
<'a
, 'tcx
>,
280 dst
: PlaceRef
<'tcx
>) {
281 let src_ty
= src
.layout
.ty
;
282 let dst_ty
= dst
.layout
.ty
;
283 let coerce_ptr
= || {
284 let (base
, info
) = match src
.load(bx
).val
{
285 OperandValue
::Pair(base
, info
) => {
286 // fat-ptr to fat-ptr unsize preserves the vtable
287 // i.e. &'a fmt::Debug+Send => &'a fmt::Debug
288 // So we need to pointercast the base to ensure
289 // the types match up.
290 let thin_ptr
= dst
.layout
.field(bx
.cx
, abi
::FAT_PTR_ADDR
);
291 (bx
.pointercast(base
, thin_ptr
.llvm_type(bx
.cx
)), info
)
293 OperandValue
::Immediate(base
) => {
294 unsize_thin_ptr(bx
, base
, src_ty
, dst_ty
)
296 OperandValue
::Ref(..) => bug
!()
298 OperandValue
::Pair(base
, info
).store(bx
, dst
);
300 match (&src_ty
.sty
, &dst_ty
.sty
) {
301 (&ty
::TyRef(..), &ty
::TyRef(..)) |
302 (&ty
::TyRef(..), &ty
::TyRawPtr(..)) |
303 (&ty
::TyRawPtr(..), &ty
::TyRawPtr(..)) => {
306 (&ty
::TyAdt(def_a
, _
), &ty
::TyAdt(def_b
, _
)) if def_a
.is_box() && def_b
.is_box() => {
310 (&ty
::TyAdt(def_a
, _
), &ty
::TyAdt(def_b
, _
)) => {
311 assert_eq
!(def_a
, def_b
);
313 for i
in 0..def_a
.variants
[0].fields
.len() {
314 let src_f
= src
.project_field(bx
, i
);
315 let dst_f
= dst
.project_field(bx
, i
);
317 if dst_f
.layout
.is_zst() {
321 if src_f
.layout
.ty
== dst_f
.layout
.ty
{
322 memcpy_ty(bx
, dst_f
.llval
, src_f
.llval
, src_f
.layout
,
323 src_f
.align
.min(dst_f
.align
), MemFlags
::empty());
325 coerce_unsized_into(bx
, src_f
, dst_f
);
329 _
=> bug
!("coerce_unsized_into: invalid coercion {:?} -> {:?}",
335 pub fn cast_shift_expr_rhs(
336 cx
: &Builder
, op
: hir
::BinOp_
, lhs
: ValueRef
, rhs
: ValueRef
338 cast_shift_rhs(op
, lhs
, rhs
, |a
, b
| cx
.trunc(a
, b
), |a
, b
| cx
.zext(a
, b
))
341 fn cast_shift_rhs
<F
, G
>(op
: hir
::BinOp_
,
347 where F
: FnOnce(ValueRef
, Type
) -> ValueRef
,
348 G
: FnOnce(ValueRef
, Type
) -> ValueRef
350 // Shifts may have any size int on the rhs
352 let mut rhs_llty
= val_ty(rhs
);
353 let mut lhs_llty
= val_ty(lhs
);
354 if rhs_llty
.kind() == Vector
{
355 rhs_llty
= rhs_llty
.element_type()
357 if lhs_llty
.kind() == Vector
{
358 lhs_llty
= lhs_llty
.element_type()
360 let rhs_sz
= rhs_llty
.int_width();
361 let lhs_sz
= lhs_llty
.int_width();
364 } else if lhs_sz
> rhs_sz
{
365 // FIXME (#1877: If shifting by negative
366 // values becomes not undefined then this is wrong.
376 /// Returns whether this session's target will use SEH-based unwinding.
378 /// This is only true for MSVC targets, and even then the 64-bit MSVC target
379 /// currently uses SEH-ish unwinding with DWARF info tables to the side (same as
380 /// 64-bit MinGW) instead of "full SEH".
381 pub fn wants_msvc_seh(sess
: &Session
) -> bool
{
382 sess
.target
.target
.options
.is_like_msvc
385 pub fn call_assume
<'a
, 'tcx
>(bx
: &Builder
<'a
, 'tcx
>, val
: ValueRef
) {
386 let assume_intrinsic
= bx
.cx
.get_intrinsic("llvm.assume");
387 bx
.call(assume_intrinsic
, &[val
], None
);
390 pub fn from_immediate(bx
: &Builder
, val
: ValueRef
) -> ValueRef
{
391 if val_ty(val
) == Type
::i1(bx
.cx
) {
392 bx
.zext(val
, Type
::i8(bx
.cx
))
398 pub fn to_immediate(bx
: &Builder
, val
: ValueRef
, layout
: layout
::TyLayout
) -> ValueRef
{
399 if let layout
::Abi
::Scalar(ref scalar
) = layout
.abi
{
400 if scalar
.is_bool() {
401 return bx
.trunc(val
, Type
::i1(bx
.cx
));
407 pub fn call_memcpy(bx
: &Builder
,
413 if flags
.contains(MemFlags
::NONTEMPORAL
) {
414 // HACK(nox): This is inefficient but there is no nontemporal memcpy.
415 let val
= bx
.load(src
, align
);
416 let ptr
= bx
.pointercast(dst
, val_ty(val
).ptr_to());
417 bx
.store_with_flags(val
, ptr
, align
, flags
);
421 let ptr_width
= &cx
.sess().target
.target
.target_pointer_width
;
422 let key
= format
!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width
);
423 let memcpy
= cx
.get_intrinsic(&key
);
424 let src_ptr
= bx
.pointercast(src
, Type
::i8p(cx
));
425 let dst_ptr
= bx
.pointercast(dst
, Type
::i8p(cx
));
426 let size
= bx
.intcast(n_bytes
, cx
.isize_ty
, false);
427 let align
= C_i32(cx
, align
.abi() as i32);
428 let volatile
= C_bool(cx
, flags
.contains(MemFlags
::VOLATILE
));
429 bx
.call(memcpy
, &[dst_ptr
, src_ptr
, size
, align
, volatile
], None
);
432 pub fn memcpy_ty
<'a
, 'tcx
>(
433 bx
: &Builder
<'a
, 'tcx
>,
436 layout
: TyLayout
<'tcx
>,
440 let size
= layout
.size
.bytes();
445 call_memcpy(bx
, dst
, src
, C_usize(bx
.cx
, size
), align
, flags
);
448 pub fn call_memset
<'a
, 'tcx
>(bx
: &Builder
<'a
, 'tcx
>,
453 volatile
: bool
) -> ValueRef
{
454 let ptr_width
= &bx
.cx
.sess().target
.target
.target_pointer_width
;
455 let intrinsic_key
= format
!("llvm.memset.p0i8.i{}", ptr_width
);
456 let llintrinsicfn
= bx
.cx
.get_intrinsic(&intrinsic_key
);
457 let volatile
= C_bool(bx
.cx
, volatile
);
458 bx
.call(llintrinsicfn
, &[ptr
, fill_byte
, size
, align
, volatile
], None
)
461 pub fn trans_instance
<'a
, 'tcx
>(cx
: &CodegenCx
<'a
, 'tcx
>, instance
: Instance
<'tcx
>) {
462 let _s
= if cx
.sess().trans_stats() {
463 let mut instance_name
= String
::new();
464 DefPathBasedNames
::new(cx
.tcx
, true, true)
465 .push_def_path(instance
.def_id(), &mut instance_name
);
466 Some(StatRecorder
::new(cx
, instance_name
))
471 // this is an info! to allow collecting monomorphization statistics
472 // and to allow finding the last function before LLVM aborts from
474 info
!("trans_instance({})", instance
);
476 let fn_ty
= instance
.ty(cx
.tcx
);
477 let sig
= common
::ty_fn_sig(cx
, fn_ty
);
478 let sig
= cx
.tcx
.normalize_erasing_late_bound_regions(ty
::ParamEnv
::reveal_all(), &sig
);
480 let lldecl
= match cx
.instances
.borrow().get(&instance
) {
482 None
=> bug
!("Instance `{:?}` not already declared", instance
)
485 cx
.stats
.borrow_mut().n_closures
+= 1;
487 // The `uwtable` attribute according to LLVM is:
489 // This attribute indicates that the ABI being targeted requires that an
490 // unwind table entry be produced for this function even if we can show
491 // that no exceptions passes by it. This is normally the case for the
492 // ELF x86-64 abi, but it can be disabled for some compilation units.
494 // Typically when we're compiling with `-C panic=abort` (which implies this
495 // `no_landing_pads` check) we don't need `uwtable` because we can't
496 // generate any exceptions! On Windows, however, exceptions include other
497 // events such as illegal instructions, segfaults, etc. This means that on
498 // Windows we end up still needing the `uwtable` attribute even if the `-C
499 // panic=abort` flag is passed.
501 // You can also find more info on why Windows is whitelisted here in:
502 // https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
503 if !cx
.sess().no_landing_pads() ||
504 cx
.sess().target
.target
.options
.requires_uwtable
{
505 attributes
::emit_uwtable(lldecl
, true);
508 let mir
= cx
.tcx
.instance_mir(instance
.def
);
509 mir
::trans_mir(cx
, lldecl
, &mir
, instance
, sig
);
512 pub fn set_link_section(cx
: &CodegenCx
,
514 attrs
: &[ast
::Attribute
]) {
515 if let Some(sect
) = attr
::first_attr_value_str_by_name(attrs
, "link_section") {
516 if contains_null(§
.as_str()) {
517 cx
.sess().fatal(&format
!("Illegal null byte in link_section value: `{}`", §
));
520 let buf
= CString
::new(sect
.as_str().as_bytes()).unwrap();
521 llvm
::LLVMSetSection(llval
, buf
.as_ptr());
526 /// Create the `main` function which will initialize the rust runtime and call
527 /// users main function.
528 fn maybe_create_entry_wrapper(cx
: &CodegenCx
) {
529 let (main_def_id
, span
) = match *cx
.sess().entry_fn
.borrow() {
530 Some((id
, span
, _
)) => {
531 (cx
.tcx
.hir
.local_def_id(id
), span
)
536 let instance
= Instance
::mono(cx
.tcx
, main_def_id
);
538 if !cx
.codegen_unit
.contains_item(&MonoItem
::Fn(instance
)) {
539 // We want to create the wrapper in the same codegen unit as Rust's main
544 let main_llfn
= callee
::get_fn(cx
, instance
);
546 let et
= cx
.sess().entry_fn
.get().map(|e
| e
.2);
548 Some(config
::EntryMain
) => create_entry_fn(cx
, span
, main_llfn
, main_def_id
, true),
549 Some(config
::EntryStart
) => create_entry_fn(cx
, span
, main_llfn
, main_def_id
, false),
550 None
=> {}
// Do nothing.
553 fn create_entry_fn
<'cx
>(cx
: &'cx CodegenCx
,
556 rust_main_def_id
: DefId
,
557 use_start_lang_item
: bool
) {
558 let llfty
= Type
::func(&[Type
::c_int(cx
), Type
::i8p(cx
).ptr_to()], &Type
::c_int(cx
));
560 let main_ret_ty
= cx
.tcx
.fn_sig(rust_main_def_id
).output();
561 // Given that `main()` has no arguments,
562 // then its return type cannot have
563 // late-bound regions, since late-bound
564 // regions must appear in the argument
566 let main_ret_ty
= cx
.tcx
.erase_regions(
567 &main_ret_ty
.no_late_bound_regions().unwrap(),
570 if declare
::get_defined_value(cx
, "main").is_some() {
571 // FIXME: We should be smart and show a better diagnostic here.
572 cx
.sess().struct_span_err(sp
, "entry symbol `main` defined multiple times")
573 .help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
575 cx
.sess().abort_if_errors();
578 let llfn
= declare
::declare_cfn(cx
, "main", llfty
);
580 // `main` should respect same config for frame pointer elimination as rest of code
581 attributes
::set_frame_pointer_elimination(cx
, llfn
);
583 let bx
= Builder
::new_block(cx
, llfn
, "top");
585 debuginfo
::gdb
::insert_reference_to_gdb_debug_scripts_section_global(&bx
);
587 // Params from native main() used as args for rust start function
588 let param_argc
= get_param(llfn
, 0);
589 let param_argv
= get_param(llfn
, 1);
590 let arg_argc
= bx
.intcast(param_argc
, cx
.isize_ty
, true);
591 let arg_argv
= param_argv
;
593 let (start_fn
, args
) = if use_start_lang_item
{
594 let start_def_id
= cx
.tcx
.require_lang_item(StartFnLangItem
);
595 let start_fn
= callee
::resolve_and_get_fn(
598 cx
.tcx
.intern_substs(&[Kind
::from(main_ret_ty
)]),
600 (start_fn
, vec
![bx
.pointercast(rust_main
, Type
::i8p(cx
).ptr_to()),
603 debug
!("using user-defined start fn");
604 (rust_main
, vec
![arg_argc
, arg_argv
])
607 let result
= bx
.call(start_fn
, &args
, None
);
608 bx
.ret(bx
.intcast(result
, Type
::c_int(cx
), true));
612 fn contains_null(s
: &str) -> bool
{
613 s
.bytes().any(|b
| b
== 0)
616 fn write_metadata
<'a
, 'gcx
>(tcx
: TyCtxt
<'a
, 'gcx
, 'gcx
>,
618 link_meta
: &LinkMeta
)
619 -> (ContextRef
, ModuleRef
, EncodedMetadata
) {
621 use flate2
::Compression
;
622 use flate2
::write
::DeflateEncoder
;
624 let (metadata_llcx
, metadata_llmod
) = unsafe {
625 context
::create_context_and_module(tcx
.sess
, llmod_id
)
628 #[derive(PartialEq, Eq, PartialOrd, Ord)]
635 let kind
= tcx
.sess
.crate_types
.borrow().iter().map(|ty
| {
637 config
::CrateTypeExecutable
|
638 config
::CrateTypeStaticlib
|
639 config
::CrateTypeCdylib
=> MetadataKind
::None
,
641 config
::CrateTypeRlib
=> MetadataKind
::Uncompressed
,
643 config
::CrateTypeDylib
|
644 config
::CrateTypeProcMacro
=> MetadataKind
::Compressed
,
648 if kind
== MetadataKind
::None
{
649 return (metadata_llcx
,
651 EncodedMetadata
::new());
654 let metadata
= tcx
.encode_metadata(link_meta
);
655 if kind
== MetadataKind
::Uncompressed
{
656 return (metadata_llcx
, metadata_llmod
, metadata
);
659 assert
!(kind
== MetadataKind
::Compressed
);
660 let mut compressed
= tcx
.metadata_encoding_version();
661 DeflateEncoder
::new(&mut compressed
, Compression
::fast())
662 .write_all(&metadata
.raw_data
).unwrap();
664 let llmeta
= C_bytes_in_context(metadata_llcx
, &compressed
);
665 let llconst
= C_struct_in_context(metadata_llcx
, &[llmeta
], false);
666 let name
= exported_symbols
::metadata_symbol_name(tcx
);
667 let buf
= CString
::new(name
).unwrap();
668 let llglobal
= unsafe {
669 llvm
::LLVMAddGlobal(metadata_llmod
, val_ty(llconst
).to_ref(), buf
.as_ptr())
672 llvm
::LLVMSetInitializer(llglobal
, llconst
);
673 let section_name
= metadata
::metadata_section_name(&tcx
.sess
.target
.target
);
674 let name
= CString
::new(section_name
).unwrap();
675 llvm
::LLVMSetSection(llglobal
, name
.as_ptr());
677 // Also generate a .section directive to force no
678 // flags, at least for ELF outputs, so that the
679 // metadata doesn't get loaded into memory.
680 let directive
= format
!(".section {}", section_name
);
681 let directive
= CString
::new(directive
).unwrap();
682 llvm
::LLVMSetModuleInlineAsm(metadata_llmod
, directive
.as_ptr())
684 return (metadata_llcx
, metadata_llmod
, metadata
);
687 pub struct ValueIter
{
689 step
: unsafe extern "C" fn(ValueRef
) -> ValueRef
,
692 impl Iterator
for ValueIter
{
693 type Item
= ValueRef
;
695 fn next(&mut self) -> Option
<ValueRef
> {
698 self.cur
= unsafe { (self.step)(old) }
;
706 pub fn iter_globals(llmod
: llvm
::ModuleRef
) -> ValueIter
{
709 cur
: llvm
::LLVMGetFirstGlobal(llmod
),
710 step
: llvm
::LLVMGetNextGlobal
,
715 pub fn trans_crate
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
716 rx
: mpsc
::Receiver
<Box
<Any
+ Send
>>)
717 -> OngoingCrateTranslation
{
719 check_for_rustc_errors_attr(tcx
);
721 if let Some(true) = tcx
.sess
.opts
.debugging_opts
.thinlto
{
722 if unsafe { !llvm::LLVMRustThinLTOAvailable() }
{
723 tcx
.sess
.fatal("this compiler's LLVM does not support ThinLTO");
727 if (tcx
.sess
.opts
.debugging_opts
.pgo_gen
.is_some() ||
728 !tcx
.sess
.opts
.debugging_opts
.pgo_use
.is_empty()) &&
729 unsafe { !llvm::LLVMRustPGOAvailable() }
731 tcx
.sess
.fatal("this compiler's LLVM does not support PGO");
734 let crate_hash
= tcx
.crate_hash(LOCAL_CRATE
);
735 let link_meta
= link
::build_link_meta(crate_hash
);
737 // Translate the metadata.
738 let llmod_id
= "metadata";
739 let (metadata_llcx
, metadata_llmod
, metadata
) =
740 time(tcx
.sess
, "write metadata", || {
741 write_metadata(tcx
, llmod_id
, &link_meta
)
744 let metadata_module
= ModuleTranslation
{
745 name
: link
::METADATA_MODULE_NAME
.to_string(),
746 llmod_id
: llmod_id
.to_string(),
747 source
: ModuleSource
::Translated(ModuleLlvm
{
749 llmod
: metadata_llmod
,
750 tm
: create_target_machine(tcx
.sess
, false),
752 kind
: ModuleKind
::Metadata
,
755 let time_graph
= if tcx
.sess
.opts
.debugging_opts
.trans_time_graph
{
756 Some(time_graph
::TimeGraph
::new())
761 // Skip crate items and just output metadata in -Z no-trans mode.
762 if tcx
.sess
.opts
.debugging_opts
.no_trans
||
763 !tcx
.sess
.opts
.output_types
.should_trans() {
764 let ongoing_translation
= write
::start_async_translation(
772 ongoing_translation
.submit_pre_translated_module_to_llvm(tcx
, metadata_module
);
773 ongoing_translation
.translation_finished(tcx
);
775 assert_and_save_dep_graph(tcx
);
777 ongoing_translation
.check_for_errors(tcx
.sess
);
779 return ongoing_translation
;
782 // Run the translation item collector and partition the collected items into
785 tcx
.collect_and_partition_translation_items(LOCAL_CRATE
).1;
786 let codegen_units
= (*codegen_units
).clone();
788 // Force all codegen_unit queries so they are already either red or green
789 // when compile_codegen_unit accesses them. We are not able to re-execute
790 // the codegen_unit query from just the DepNode, so an unknown color would
791 // lead to having to re-execute compile_codegen_unit, possibly
793 if tcx
.dep_graph
.is_fully_enabled() {
794 for cgu
in &codegen_units
{
795 tcx
.codegen_unit(cgu
.name().clone());
799 let ongoing_translation
= write
::start_async_translation(
805 codegen_units
.len());
807 // Translate an allocator shim, if any
808 let allocator_module
= if let Some(kind
) = *tcx
.sess
.allocator_kind
.get() {
810 let llmod_id
= "allocator";
812 context
::create_context_and_module(tcx
.sess
, llmod_id
);
813 let modules
= ModuleLlvm
{
816 tm
: create_target_machine(tcx
.sess
, false),
818 time(tcx
.sess
, "write allocator module", || {
819 allocator
::trans(tcx
, &modules
, kind
)
822 Some(ModuleTranslation
{
823 name
: link
::ALLOCATOR_MODULE_NAME
.to_string(),
824 llmod_id
: llmod_id
.to_string(),
825 source
: ModuleSource
::Translated(modules
),
826 kind
: ModuleKind
::Allocator
,
833 if let Some(allocator_module
) = allocator_module
{
834 ongoing_translation
.submit_pre_translated_module_to_llvm(tcx
, allocator_module
);
837 ongoing_translation
.submit_pre_translated_module_to_llvm(tcx
, metadata_module
);
839 // We sort the codegen units by size. This way we can schedule work for LLVM
840 // a bit more efficiently.
841 let codegen_units
= {
842 let mut codegen_units
= codegen_units
;
843 codegen_units
.sort_by_cached_key(|cgu
| cmp
::Reverse(cgu
.size_estimate()));
847 let mut total_trans_time
= Duration
::new(0, 0);
848 let mut all_stats
= Stats
::default();
850 for cgu
in codegen_units
.into_iter() {
851 ongoing_translation
.wait_for_signal_to_translate_item();
852 ongoing_translation
.check_for_errors(tcx
.sess
);
854 // First, if incremental compilation is enabled, we try to re-use the
855 // codegen unit from the cache.
856 if tcx
.dep_graph
.is_fully_enabled() {
857 let cgu_id
= cgu
.work_product_id();
859 // Check whether there is a previous work-product we can
860 // re-use. Not only must the file exist, and the inputs not
861 // be dirty, but the hash of the symbols we will generate must
863 if let Some(buf
) = tcx
.dep_graph
.previous_work_product(&cgu_id
) {
864 let dep_node
= &DepNode
::new(tcx
,
865 DepConstructor
::CompileCodegenUnit(cgu
.name().clone()));
867 // We try to mark the DepNode::CompileCodegenUnit green. If we
868 // succeed it means that none of the dependencies has changed
869 // and we can safely re-use.
870 if let Some(dep_node_index
) = tcx
.dep_graph
.try_mark_green(tcx
, dep_node
) {
871 // Append ".rs" to LLVM module identifier.
873 // LLVM code generator emits a ".file filename" directive
874 // for ELF backends. Value of the "filename" is set as the
875 // LLVM module identifier. Due to a LLVM MC bug[1], LLVM
876 // crashes if the module identifier is same as other symbols
877 // such as a function name in the module.
878 // 1. http://llvm.org/bugs/show_bug.cgi?id=11479
879 let llmod_id
= format
!("{}.rs", cgu
.name());
881 let module
= ModuleTranslation
{
882 name
: cgu
.name().to_string(),
883 source
: ModuleSource
::Preexisting(buf
),
884 kind
: ModuleKind
::Regular
,
887 tcx
.dep_graph
.mark_loaded_from_cache(dep_node_index
, true);
888 write
::submit_translated_module_to_llvm(tcx
, module
, 0);
889 // Continue to next cgu, this one is done.
893 // This can happen if files were deleted from the cache
894 // directory for some reason. We just re-compile then.
898 let _timing_guard
= time_graph
.as_ref().map(|time_graph
| {
899 time_graph
.start(write
::TRANS_WORKER_TIMELINE
,
900 write
::TRANS_WORK_PACKAGE_KIND
,
901 &format
!("codegen {}", cgu
.name()))
903 let start_time
= Instant
::now();
904 all_stats
.extend(tcx
.compile_codegen_unit(*cgu
.name()));
905 total_trans_time
+= start_time
.elapsed();
906 ongoing_translation
.check_for_errors(tcx
.sess
);
909 ongoing_translation
.translation_finished(tcx
);
911 // Since the main thread is sometimes blocked during trans, we keep track
912 // -Ztime-passes output manually.
913 print_time_passes_entry(tcx
.sess
.time_passes(),
914 "translate to LLVM IR",
917 if tcx
.sess
.opts
.incremental
.is_some() {
918 ::rustc_incremental
::assert_module_sources
::assert_module_sources(tcx
);
921 symbol_names_test
::report_symbol_names(tcx
);
923 if tcx
.sess
.trans_stats() {
924 println
!("--- trans stats ---");
925 println
!("n_glues_created: {}", all_stats
.n_glues_created
);
926 println
!("n_null_glues: {}", all_stats
.n_null_glues
);
927 println
!("n_real_glues: {}", all_stats
.n_real_glues
);
929 println
!("n_fns: {}", all_stats
.n_fns
);
930 println
!("n_inlines: {}", all_stats
.n_inlines
);
931 println
!("n_closures: {}", all_stats
.n_closures
);
932 println
!("fn stats:");
933 all_stats
.fn_stats
.sort_by_key(|&(_
, insns
)| insns
);
934 for &(ref name
, insns
) in all_stats
.fn_stats
.iter() {
935 println
!("{} insns, {}", insns
, *name
);
939 if tcx
.sess
.count_llvm_insns() {
940 for (k
, v
) in all_stats
.llvm_insns
.iter() {
941 println
!("{:7} {}", *v
, *k
);
945 ongoing_translation
.check_for_errors(tcx
.sess
);
947 assert_and_save_dep_graph(tcx
);
951 fn assert_and_save_dep_graph
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>) {
954 || rustc_incremental
::assert_dep_graph(tcx
));
957 "serialize dep graph",
958 || rustc_incremental
::save_dep_graph(tcx
));
961 fn collect_and_partition_translation_items
<'a
, 'tcx
>(
962 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
964 ) -> (Arc
<DefIdSet
>, Arc
<Vec
<Arc
<CodegenUnit
<'tcx
>>>>)
966 assert_eq
!(cnum
, LOCAL_CRATE
);
968 let collection_mode
= match tcx
.sess
.opts
.debugging_opts
.print_trans_items
{
970 let mode_string
= s
.to_lowercase();
971 let mode_string
= mode_string
.trim();
972 if mode_string
== "eager" {
973 MonoItemCollectionMode
::Eager
975 if mode_string
!= "lazy" {
976 let message
= format
!("Unknown codegen-item collection mode '{}'. \
977 Falling back to 'lazy' mode.",
979 tcx
.sess
.warn(&message
);
982 MonoItemCollectionMode
::Lazy
986 if tcx
.sess
.opts
.cg
.link_dead_code
{
987 MonoItemCollectionMode
::Eager
989 MonoItemCollectionMode
::Lazy
994 let (items
, inlining_map
) =
995 time(tcx
.sess
, "translation item collection", || {
996 collector
::collect_crate_mono_items(tcx
, collection_mode
)
999 tcx
.sess
.abort_if_errors();
1001 ::rustc_mir
::monomorphize
::assert_symbols_are_distinct(tcx
, items
.iter());
1003 let strategy
= if tcx
.sess
.opts
.incremental
.is_some() {
1004 PartitioningStrategy
::PerModule
1006 PartitioningStrategy
::FixedUnitCount(tcx
.sess
.codegen_units())
1009 let codegen_units
= time(tcx
.sess
, "codegen unit partitioning", || {
1010 partitioning
::partition(tcx
,
1011 items
.iter().cloned(),
1016 .collect
::<Vec
<_
>>()
1019 let translation_items
: DefIdSet
= items
.iter().filter_map(|trans_item
| {
1021 MonoItem
::Fn(ref instance
) => Some(instance
.def_id()),
1022 MonoItem
::Static(def_id
) => Some(def_id
),
1027 if tcx
.sess
.opts
.debugging_opts
.print_trans_items
.is_some() {
1028 let mut item_to_cgus
= FxHashMap();
1030 for cgu
in &codegen_units
{
1031 for (&trans_item
, &linkage
) in cgu
.items() {
1032 item_to_cgus
.entry(trans_item
)
1033 .or_insert(Vec
::new())
1034 .push((cgu
.name().clone(), linkage
));
1038 let mut item_keys
: Vec
<_
> = items
1041 let mut output
= i
.to_string(tcx
);
1042 output
.push_str(" @@");
1043 let mut empty
= Vec
::new();
1044 let cgus
= item_to_cgus
.get_mut(i
).unwrap_or(&mut empty
);
1045 cgus
.as_mut_slice().sort_by_key(|&(ref name
, _
)| name
.clone());
1047 for &(ref cgu_name
, (linkage
, _
)) in cgus
.iter() {
1048 output
.push_str(" ");
1049 output
.push_str(&cgu_name
.as_str());
1051 let linkage_abbrev
= match linkage
{
1052 Linkage
::External
=> "External",
1053 Linkage
::AvailableExternally
=> "Available",
1054 Linkage
::LinkOnceAny
=> "OnceAny",
1055 Linkage
::LinkOnceODR
=> "OnceODR",
1056 Linkage
::WeakAny
=> "WeakAny",
1057 Linkage
::WeakODR
=> "WeakODR",
1058 Linkage
::Appending
=> "Appending",
1059 Linkage
::Internal
=> "Internal",
1060 Linkage
::Private
=> "Private",
1061 Linkage
::ExternalWeak
=> "ExternalWeak",
1062 Linkage
::Common
=> "Common",
1065 output
.push_str("[");
1066 output
.push_str(linkage_abbrev
);
1067 output
.push_str("]");
1075 for item
in item_keys
{
1076 println
!("TRANS_ITEM {}", item
);
1080 (Arc
::new(translation_items
), Arc
::new(codegen_units
))
1084 pub fn new(tcx
: TyCtxt
) -> CrateInfo
{
1085 let mut info
= CrateInfo
{
1086 panic_runtime
: None
,
1087 compiler_builtins
: None
,
1088 profiler_runtime
: None
,
1089 sanitizer_runtime
: None
,
1090 is_no_builtins
: FxHashSet(),
1091 native_libraries
: FxHashMap(),
1092 used_libraries
: tcx
.native_libraries(LOCAL_CRATE
),
1093 link_args
: tcx
.link_args(LOCAL_CRATE
),
1094 crate_name
: FxHashMap(),
1095 used_crates_dynamic
: cstore
::used_crates(tcx
, LinkagePreference
::RequireDynamic
),
1096 used_crates_static
: cstore
::used_crates(tcx
, LinkagePreference
::RequireStatic
),
1097 used_crate_source
: FxHashMap(),
1098 wasm_custom_sections
: BTreeMap
::new(),
1099 wasm_imports
: FxHashMap(),
1100 lang_item_to_crate
: FxHashMap(),
1101 missing_lang_items
: FxHashMap(),
1103 let lang_items
= tcx
.lang_items();
1105 let load_wasm_items
= tcx
.sess
.crate_types
.borrow()
1107 .any(|c
| *c
!= config
::CrateTypeRlib
) &&
1108 tcx
.sess
.opts
.target_triple
== TargetTriple
::from_triple("wasm32-unknown-unknown");
1110 if load_wasm_items
{
1111 info
!("attempting to load all wasm sections");
1112 for &id
in tcx
.wasm_custom_sections(LOCAL_CRATE
).iter() {
1113 let (name
, contents
) = fetch_wasm_section(tcx
, id
);
1114 info
.wasm_custom_sections
.entry(name
)
1115 .or_insert(Vec
::new())
1118 info
.load_wasm_imports(tcx
, LOCAL_CRATE
);
1121 for &cnum
in tcx
.crates().iter() {
1122 info
.native_libraries
.insert(cnum
, tcx
.native_libraries(cnum
));
1123 info
.crate_name
.insert(cnum
, tcx
.crate_name(cnum
).to_string());
1124 info
.used_crate_source
.insert(cnum
, tcx
.used_crate_source(cnum
));
1125 if tcx
.is_panic_runtime(cnum
) {
1126 info
.panic_runtime
= Some(cnum
);
1128 if tcx
.is_compiler_builtins(cnum
) {
1129 info
.compiler_builtins
= Some(cnum
);
1131 if tcx
.is_profiler_runtime(cnum
) {
1132 info
.profiler_runtime
= Some(cnum
);
1134 if tcx
.is_sanitizer_runtime(cnum
) {
1135 info
.sanitizer_runtime
= Some(cnum
);
1137 if tcx
.is_no_builtins(cnum
) {
1138 info
.is_no_builtins
.insert(cnum
);
1140 if load_wasm_items
{
1141 for &id
in tcx
.wasm_custom_sections(cnum
).iter() {
1142 let (name
, contents
) = fetch_wasm_section(tcx
, id
);
1143 info
.wasm_custom_sections
.entry(name
)
1144 .or_insert(Vec
::new())
1147 info
.load_wasm_imports(tcx
, cnum
);
1149 let missing
= tcx
.missing_lang_items(cnum
);
1150 for &item
in missing
.iter() {
1151 if let Ok(id
) = lang_items
.require(item
) {
1152 info
.lang_item_to_crate
.insert(item
, id
.krate
);
1156 // No need to look for lang items that are whitelisted and don't
1157 // actually need to exist.
1158 let missing
= missing
.iter()
1160 .filter(|&l
| !weak_lang_items
::whitelisted(tcx
, l
))
1162 info
.missing_lang_items
.insert(cnum
, missing
);
1168 fn load_wasm_imports(&mut self, tcx
: TyCtxt
, cnum
: CrateNum
) {
1169 for (&id
, module
) in tcx
.wasm_import_module_map(cnum
).iter() {
1170 let instance
= Instance
::mono(tcx
, id
);
1171 let import_name
= tcx
.symbol_name(instance
);
1172 self.wasm_imports
.insert(import_name
.to_string(), module
.clone());
1177 fn is_translated_item(tcx
: TyCtxt
, id
: DefId
) -> bool
{
1178 let (all_trans_items
, _
) =
1179 tcx
.collect_and_partition_translation_items(LOCAL_CRATE
);
1180 all_trans_items
.contains(&id
)
1183 fn compile_codegen_unit
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
1184 cgu
: InternedString
) -> Stats
{
1185 let cgu
= tcx
.codegen_unit(cgu
);
1187 let start_time
= Instant
::now();
1188 let (stats
, module
) = module_translation(tcx
, cgu
);
1189 let time_to_translate
= start_time
.elapsed();
1191 // We assume that the cost to run LLVM on a CGU is proportional to
1192 // the time we needed for translating it.
1193 let cost
= time_to_translate
.as_secs() * 1_000_000_000 +
1194 time_to_translate
.subsec_nanos() as u64;
1196 write
::submit_translated_module_to_llvm(tcx
,
1201 fn module_translation
<'a
, 'tcx
>(
1202 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
1203 cgu
: Arc
<CodegenUnit
<'tcx
>>)
1204 -> (Stats
, ModuleTranslation
)
1206 let cgu_name
= cgu
.name().to_string();
1208 // Append ".rs" to LLVM module identifier.
1210 // LLVM code generator emits a ".file filename" directive
1211 // for ELF backends. Value of the "filename" is set as the
1212 // LLVM module identifier. Due to a LLVM MC bug[1], LLVM
1213 // crashes if the module identifier is same as other symbols
1214 // such as a function name in the module.
1215 // 1. http://llvm.org/bugs/show_bug.cgi?id=11479
1216 let llmod_id
= format
!("{}-{}.rs",
1218 tcx
.crate_disambiguator(LOCAL_CRATE
)
1219 .to_fingerprint().to_hex());
1221 // Instantiate translation items without filling out definitions yet...
1222 let cx
= CodegenCx
::new(tcx
, cgu
, &llmod_id
);
1224 let trans_items
= cx
.codegen_unit
1225 .items_in_deterministic_order(cx
.tcx
);
1226 for &(trans_item
, (linkage
, visibility
)) in &trans_items
{
1227 trans_item
.predefine(&cx
, linkage
, visibility
);
1230 // ... and now that we have everything pre-defined, fill out those definitions.
1231 for &(trans_item
, _
) in &trans_items
{
1232 trans_item
.define(&cx
);
1235 // If this codegen unit contains the main function, also create the
1237 maybe_create_entry_wrapper(&cx
);
1239 // Run replace-all-uses-with for statics that need it
1240 for &(old_g
, new_g
) in cx
.statics_to_rauw
.borrow().iter() {
1242 let bitcast
= llvm
::LLVMConstPointerCast(new_g
, llvm
::LLVMTypeOf(old_g
));
1243 llvm
::LLVMReplaceAllUsesWith(old_g
, bitcast
);
1244 llvm
::LLVMDeleteGlobal(old_g
);
1248 // Create the llvm.used variable
1249 // This variable has type [N x i8*] and is stored in the llvm.metadata section
1250 if !cx
.used_statics
.borrow().is_empty() {
1251 let name
= CString
::new("llvm.used").unwrap();
1252 let section
= CString
::new("llvm.metadata").unwrap();
1253 let array
= C_array(Type
::i8(&cx
).ptr_to(), &*cx
.used_statics
.borrow());
1256 let g
= llvm
::LLVMAddGlobal(cx
.llmod
,
1257 val_ty(array
).to_ref(),
1259 llvm
::LLVMSetInitializer(g
, array
);
1260 llvm
::LLVMRustSetLinkage(g
, llvm
::Linkage
::AppendingLinkage
);
1261 llvm
::LLVMSetSection(g
, section
.as_ptr());
1265 // Finalize debuginfo
1266 if cx
.sess().opts
.debuginfo
!= NoDebugInfo
{
1267 debuginfo
::finalize(&cx
);
1270 let llvm_module
= ModuleLlvm
{
1273 tm
: create_target_machine(cx
.sess(), false),
1278 source
: ModuleSource
::Translated(llvm_module
),
1279 kind
: ModuleKind
::Regular
,
1284 (cx
.into_stats(), module
)
1288 pub fn provide(providers
: &mut Providers
) {
1289 providers
.collect_and_partition_translation_items
=
1290 collect_and_partition_translation_items
;
1292 providers
.is_translated_item
= is_translated_item
;
1294 providers
.codegen_unit
= |tcx
, name
| {
1295 let (_
, all
) = tcx
.collect_and_partition_translation_items(LOCAL_CRATE
);
1297 .find(|cgu
| *cgu
.name() == name
)
1299 .expect(&format
!("failed to find cgu with name {:?}", name
))
1301 providers
.compile_codegen_unit
= compile_codegen_unit
;
1303 provide_extern(providers
);
1306 pub fn provide_extern(providers
: &mut Providers
) {
1307 providers
.dllimport_foreign_items
= |tcx
, krate
| {
1308 let module_map
= tcx
.foreign_modules(krate
);
1309 let module_map
= module_map
.iter()
1310 .map(|lib
| (lib
.def_id
, lib
))
1311 .collect
::<FxHashMap
<_
, _
>>();
1313 let dllimports
= tcx
.native_libraries(krate
)
1316 if lib
.kind
!= cstore
::NativeLibraryKind
::NativeUnknown
{
1319 let cfg
= match lib
.cfg
{
1320 Some(ref cfg
) => cfg
,
1321 None
=> return true,
1323 attr
::cfg_matches(cfg
, &tcx
.sess
.parse_sess
, None
)
1325 .filter_map(|lib
| lib
.foreign_module
)
1326 .map(|id
| &module_map
[&id
])
1327 .flat_map(|module
| module
.foreign_items
.iter().cloned())
1329 Lrc
::new(dllimports
)
1332 providers
.is_dllimport_foreign_item
= |tcx
, def_id
| {
1333 tcx
.dllimport_foreign_items(def_id
.krate
).contains(&def_id
)
1337 pub fn linkage_to_llvm(linkage
: Linkage
) -> llvm
::Linkage
{
1339 Linkage
::External
=> llvm
::Linkage
::ExternalLinkage
,
1340 Linkage
::AvailableExternally
=> llvm
::Linkage
::AvailableExternallyLinkage
,
1341 Linkage
::LinkOnceAny
=> llvm
::Linkage
::LinkOnceAnyLinkage
,
1342 Linkage
::LinkOnceODR
=> llvm
::Linkage
::LinkOnceODRLinkage
,
1343 Linkage
::WeakAny
=> llvm
::Linkage
::WeakAnyLinkage
,
1344 Linkage
::WeakODR
=> llvm
::Linkage
::WeakODRLinkage
,
1345 Linkage
::Appending
=> llvm
::Linkage
::AppendingLinkage
,
1346 Linkage
::Internal
=> llvm
::Linkage
::InternalLinkage
,
1347 Linkage
::Private
=> llvm
::Linkage
::PrivateLinkage
,
1348 Linkage
::ExternalWeak
=> llvm
::Linkage
::ExternalWeakLinkage
,
1349 Linkage
::Common
=> llvm
::Linkage
::CommonLinkage
,
1353 pub fn visibility_to_llvm(linkage
: Visibility
) -> llvm
::Visibility
{
1355 Visibility
::Default
=> llvm
::Visibility
::Default
,
1356 Visibility
::Hidden
=> llvm
::Visibility
::Hidden
,
1357 Visibility
::Protected
=> llvm
::Visibility
::Protected
,
1361 // FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
1362 // the HashStable trait. Normally DepGraph::with_task() calls are
1363 // hidden behind queries, but CGU creation is a special case in two
1364 // ways: (1) it's not a query and (2) CGU are output nodes, so their
1365 // Fingerprints are not actually needed. It remains to be clarified
1366 // how exactly this case will be handled in the red/green system but
1367 // for now we content ourselves with providing a no-op HashStable
1368 // implementation for CGUs.
1369 mod temp_stable_hash_impls
{
1370 use rustc_data_structures
::stable_hasher
::{StableHasherResult
, StableHasher
,
1372 use ModuleTranslation
;
1374 impl<HCX
> HashStable
<HCX
> for ModuleTranslation
{
1375 fn hash_stable
<W
: StableHasherResult
>(&self,
1377 _
: &mut StableHasher
<W
>) {
1383 fn fetch_wasm_section(tcx
: TyCtxt
, id
: DefId
) -> (String
, Vec
<u8>) {
1384 use rustc
::mir
::interpret
::{GlobalId, Value, PrimVal}
;
1385 use rustc
::middle
::const_val
::ConstVal
;
1387 info
!("loading wasm section {:?}", id
);
1389 let section
= tcx
.get_attrs(id
)
1391 .find(|a
| a
.check_name("wasm_custom_section"))
1392 .expect("missing #[wasm_custom_section] attribute")
1394 .expect("malformed #[wasm_custom_section] attribute");
1396 let instance
= ty
::Instance
::mono(tcx
, id
);
1397 let cid
= GlobalId
{
1401 let param_env
= ty
::ParamEnv
::reveal_all();
1402 let val
= tcx
.const_eval(param_env
.and(cid
)).unwrap();
1404 let val
= match val
.val
{
1405 ConstVal
::Value(val
) => val
,
1406 ConstVal
::Unevaluated(..) => bug
!("should be evaluated"),
1408 let val
= match val
{
1409 Value
::ByRef(ptr
, _align
) => ptr
.into_inner_primval(),
1410 ref v
=> bug
!("should be ByRef, was {:?}", v
),
1412 let mem
= match val
{
1413 PrimVal
::Ptr(mem
) => mem
,
1414 ref v
=> bug
!("should be Ptr, was {:?}", v
),
1416 assert_eq
!(mem
.offset
, 0);
1419 .get_alloc(mem
.alloc_id
)
1420 .expect("miri allocation never successfully created");
1421 (section
.to_string(), alloc
.bytes
.clone())