1 // Copyright 2012-2014 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 #![allow(non_camel_case_types, non_snake_case)]
13 //! Code that is useful in various trans modules.
17 use llvm
::{ValueRef, BasicBlockRef, BuilderRef, ContextRef, TypeKind}
;
18 use llvm
::{True, False, Bool, OperandBundleDef}
;
20 use rustc
::hir
::def
::Def
;
21 use rustc
::hir
::def_id
::DefId
;
22 use rustc
::infer
::TransNormalize
;
23 use rustc
::util
::common
::MemoizationMap
;
24 use middle
::lang_items
::LangItem
;
25 use rustc
::ty
::subst
::Substs
;
26 use abi
::{Abi, FnType}
;
34 use debuginfo
::{self, DebugLoc}
;
41 use rustc
::ty
::{self, Ty, TyCtxt}
;
42 use rustc
::ty
::layout
::Layout
;
43 use rustc
::traits
::{self, SelectionContext, Reveal}
;
44 use rustc
::ty
::fold
::TypeFoldable
;
46 use util
::nodemap
::NodeMap
;
48 use arena
::TypedArena
;
49 use libc
::{c_uint, c_char}
;
51 use std
::ffi
::CString
;
52 use std
::cell
::{Cell, RefCell}
;
55 use syntax
::parse
::token
::InternedString
;
56 use syntax
::parse
::token
;
57 use syntax_pos
::{DUMMY_SP, Span}
;
59 pub use context
::{CrateContext, SharedCrateContext}
;
61 /// Is the type's representation size known at compile time?
62 pub fn type_is_sized
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>, ty
: Ty
<'tcx
>) -> bool
{
63 ty
.is_sized(tcx
, &tcx
.empty_parameter_environment(), DUMMY_SP
)
66 pub fn type_is_fat_ptr
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>, ty
: Ty
<'tcx
>) -> bool
{
68 ty
::TyRawPtr(ty
::TypeAndMut{ty, ..}
) |
69 ty
::TyRef(_
, ty
::TypeAndMut{ty, ..}
) |
71 !type_is_sized(tcx
, ty
)
79 pub fn type_is_immediate
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, ty
: Ty
<'tcx
>) -> bool
{
80 use machine
::llsize_of_alloc
;
81 use type_of
::sizing_type_of
;
84 let simple
= ty
.is_scalar() ||
85 ty
.is_unique() || ty
.is_region_ptr() ||
87 if simple
&& !type_is_fat_ptr(tcx
, ty
) {
90 if !type_is_sized(tcx
, ty
) {
94 ty
::TyStruct(..) | ty
::TyEnum(..) | ty
::TyTuple(..) | ty
::TyArray(_
, _
) |
95 ty
::TyClosure(..) => {
96 let llty
= sizing_type_of(ccx
, ty
);
97 llsize_of_alloc(ccx
, llty
) <= llsize_of_alloc(ccx
, ccx
.int_type())
99 _
=> type_is_zero_size(ccx
, ty
)
103 /// Returns Some([a, b]) if the type has a pair of fields with types a and b.
104 pub fn type_pair_fields
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, ty
: Ty
<'tcx
>)
105 -> Option
<[Ty
<'tcx
>; 2]> {
107 ty
::TyEnum(adt
, substs
) | ty
::TyStruct(adt
, substs
) => {
108 assert_eq
!(adt
.variants
.len(), 1);
109 let fields
= &adt
.variants
[0].fields
;
110 if fields
.len() != 2 {
113 Some([monomorphize
::field_ty(ccx
.tcx(), substs
, &fields
[0]),
114 monomorphize
::field_ty(ccx
.tcx(), substs
, &fields
[1])])
116 ty
::TyClosure(_
, ty
::ClosureSubsts { upvar_tys: tys, .. }
) |
117 ty
::TyTuple(tys
) => {
121 Some([tys
[0], tys
[1]])
127 /// Returns true if the type is represented as a pair of immediates.
128 pub fn type_is_imm_pair
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, ty
: Ty
<'tcx
>)
131 let layout
= tcx
.normalizing_infer_ctxt(Reveal
::All
).enter(|infcx
| {
132 match ty
.layout(&infcx
) {
133 Ok(layout
) => layout
,
135 bug
!("type_is_imm_pair: layout for `{:?}` failed: {}",
142 Layout
::FatPointer { .. }
=> true,
143 Layout
::Univariant { ref variant, .. }
=> {
144 // There must be only 2 fields.
145 if variant
.offset_after_field
.len() != 2 {
149 match type_pair_fields(ccx
, ty
) {
151 type_is_immediate(ccx
, a
) && type_is_immediate(ccx
, b
)
160 /// Identify types which have size zero at runtime.
161 pub fn type_is_zero_size
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, ty
: Ty
<'tcx
>) -> bool
{
162 use machine
::llsize_of_alloc
;
163 use type_of
::sizing_type_of
;
164 let llty
= sizing_type_of(ccx
, ty
);
165 llsize_of_alloc(ccx
, llty
) == 0
168 /// Generates a unique symbol based off the name given. This is used to create
169 /// unique symbols for things like closures.
170 pub fn gensym_name(name
: &str) -> ast
::Name
{
171 let num
= token
::gensym(name
).0;
172 // use one colon which will get translated to a period by the mangler, and
173 // we're guaranteed that `num` is globally unique for this crate.
174 token
::gensym(&format
!("{}:{}", name
, num
))
178 * A note on nomenclature of linking: "extern", "foreign", and "upcall".
180 * An "extern" is an LLVM symbol we wind up emitting an undefined external
181 * reference to. This means "we don't have the thing in this compilation unit,
182 * please make sure you link it in at runtime". This could be a reference to
183 * C code found in a C library, or rust code found in a rust crate.
185 * Most "externs" are implicitly declared (automatically) as a result of a
186 * user declaring an extern _module_ dependency; this causes the rust driver
187 * to locate an extern crate, scan its compilation metadata, and emit extern
188 * declarations for any symbols used by the declaring crate.
190 * A "foreign" is an extern that references C (or other non-rust ABI) code.
191 * There is no metadata to scan for extern references so in these cases either
192 * a header-digester like bindgen, or manual function prototypes, have to
193 * serve as declarators. So these are usually given explicitly as prototype
194 * declarations, in rust code, with ABI attributes on them noting which ABI to
197 * An "upcall" is a foreign call generated by the compiler (not corresponding
198 * to any user-written call in the code) into the runtime library, to perform
199 * some helper task such as bringing a task to life, allocating memory, etc.
205 #[derive(Copy, Clone)]
206 pub struct NodeIdAndSpan
{
211 pub fn expr_info(expr
: &hir
::Expr
) -> NodeIdAndSpan
{
212 NodeIdAndSpan { id: expr.id, span: expr.span }
215 /// The concrete version of ty::FieldDef. The name is the field index if
216 /// the field is numeric.
217 pub struct Field
<'tcx
>(pub ast
::Name
, pub Ty
<'tcx
>);
219 /// The concrete version of ty::VariantDef
220 pub struct VariantInfo
<'tcx
> {
222 pub fields
: Vec
<Field
<'tcx
>>
225 impl<'a
, 'tcx
> VariantInfo
<'tcx
> {
226 pub fn from_ty(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
228 opt_def
: Option
<Def
>)
232 ty
::TyStruct(adt
, substs
) | ty
::TyEnum(adt
, substs
) => {
233 let variant
= match opt_def
{
234 None
=> adt
.struct_variant(),
235 Some(def
) => adt
.variant_of_def(def
)
239 discr
: Disr
::from(variant
.disr_val
),
240 fields
: variant
.fields
.iter().map(|f
| {
241 Field(f
.name
, monomorphize
::field_ty(tcx
, substs
, f
))
246 ty
::TyTuple(ref v
) => {
249 fields
: v
.iter().enumerate().map(|(i
, &t
)| {
250 Field(token
::intern(&i
.to_string()), t
)
256 bug
!("cannot get field types from the type {:?}", ty
);
261 /// Return the variant corresponding to a given node (e.g. expr)
262 pub fn of_node(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>, ty
: Ty
<'tcx
>, id
: ast
::NodeId
) -> Self {
263 Self::from_ty(tcx
, ty
, Some(tcx
.expect_def(id
)))
266 pub fn field_index(&self, name
: ast
::Name
) -> usize {
267 self.fields
.iter().position(|&Field(n
,_
)| n
== name
).unwrap_or_else(|| {
268 bug
!("unknown field `{}`", name
)
273 pub struct BuilderRef_res
{
277 impl Drop
for BuilderRef_res
{
280 llvm
::LLVMDisposeBuilder(self.b
);
285 pub fn BuilderRef_res(b
: BuilderRef
) -> BuilderRef_res
{
291 pub fn validate_substs(substs
: &Substs
) {
292 assert
!(!substs
.types
.needs_infer());
295 // work around bizarre resolve errors
296 type RvalueDatum
<'tcx
> = datum
::Datum
<'tcx
, datum
::Rvalue
>;
297 pub type LvalueDatum
<'tcx
> = datum
::Datum
<'tcx
, datum
::Lvalue
>;
299 #[derive(Clone, Debug)]
300 struct HintEntry
<'tcx
> {
301 // The datum for the dropflag-hint itself; note that many
302 // source-level Lvalues will be associated with the same
303 // dropflag-hint datum.
304 datum
: cleanup
::DropHintDatum
<'tcx
>,
307 pub struct DropFlagHintsMap
<'tcx
> {
308 // Maps NodeId for expressions that read/write unfragmented state
309 // to that state's drop-flag "hint." (A stack-local hint
310 // indicates either that (1.) it is certain that no-drop is
311 // needed, or (2.) inline drop-flag must be consulted.)
312 node_map
: NodeMap
<HintEntry
<'tcx
>>,
315 impl<'tcx
> DropFlagHintsMap
<'tcx
> {
316 pub fn new() -> DropFlagHintsMap
<'tcx
> { DropFlagHintsMap { node_map: NodeMap() }
}
317 pub fn has_hint(&self, id
: ast
::NodeId
) -> bool { self.node_map.contains_key(&id) }
318 pub fn insert(&mut self, id
: ast
::NodeId
, datum
: cleanup
::DropHintDatum
<'tcx
>) {
319 self.node_map
.insert(id
, HintEntry { datum: datum }
);
321 pub fn hint_datum(&self, id
: ast
::NodeId
) -> Option
<cleanup
::DropHintDatum
<'tcx
>> {
322 self.node_map
.get(&id
).map(|t
|t
.datum
)
326 // Function context. Every LLVM function we create will have one of
328 pub struct FunctionContext
<'a
, 'tcx
: 'a
> {
329 // The MIR for this function. At present, this is optional because
330 // we only have MIR available for things that are local to the
332 pub mir
: Option
<CachedMir
<'a
, 'tcx
>>,
334 // The ValueRef returned from a call to llvm::LLVMAddFunction; the
335 // address of the first instruction in the sequence of
336 // instructions for this function that will go in the .text
337 // section of the executable we're generating.
340 // always an empty parameter-environment NOTE: @jroesch another use of ParamEnv
341 pub param_env
: ty
::ParameterEnvironment
<'tcx
>,
343 // A pointer to where to store the return value. If the return type is
344 // immediate, this points to an alloca in the function. Otherwise, it's a
345 // pointer to the hidden first parameter of the function. After function
346 // construction, this should always be Some.
347 pub llretslotptr
: Cell
<Option
<ValueRef
>>,
349 // These pub elements: "hoisted basic blocks" containing
350 // administrative activities that have to happen in only one place in
351 // the function, due to LLVM's quirks.
352 // A marker for the place where we want to insert the function's static
353 // allocas, so that LLVM will coalesce them into a single alloca call.
354 pub alloca_insert_pt
: Cell
<Option
<ValueRef
>>,
355 pub llreturn
: Cell
<Option
<BasicBlockRef
>>,
357 // If the function has any nested return's, including something like:
358 // fn foo() -> Option<Foo> { Some(Foo { x: return None }) }, then
359 // we use a separate alloca for each return
360 pub needs_ret_allocas
: bool
,
362 // When working with landingpad-based exceptions this value is alloca'd and
363 // later loaded when using the resume instruction. This ends up being
364 // critical to chaining landing pads and resuing already-translated
367 // Note that for cleanuppad-based exceptions this is not used.
368 pub landingpad_alloca
: Cell
<Option
<ValueRef
>>,
370 // Maps the DefId's for local variables to the allocas created for
371 // them in llallocas.
372 pub lllocals
: RefCell
<NodeMap
<LvalueDatum
<'tcx
>>>,
374 // Same as above, but for closure upvars
375 pub llupvars
: RefCell
<NodeMap
<ValueRef
>>,
377 // Carries info about drop-flags for local bindings (longer term,
378 // paths) for the code being compiled.
379 pub lldropflag_hints
: RefCell
<DropFlagHintsMap
<'tcx
>>,
381 // Describes the return/argument LLVM types and their ABI handling.
384 // If this function is being monomorphized, this contains the type
385 // substitutions used.
386 pub param_substs
: &'tcx Substs
<'tcx
>,
388 // The source span and nesting context where this function comes from, for
389 // error reporting and symbol generation.
390 pub span
: Option
<Span
>,
392 // The arena that blocks are allocated from.
393 pub block_arena
: &'a TypedArena
<BlockS
<'a
, 'tcx
>>,
395 // The arena that landing pads are allocated from.
396 pub lpad_arena
: TypedArena
<LandingPad
>,
398 // This function's enclosing crate context.
399 pub ccx
: &'a CrateContext
<'a
, 'tcx
>,
401 // Used and maintained by the debuginfo module.
402 pub debug_context
: debuginfo
::FunctionDebugContext
,
405 pub scopes
: RefCell
<Vec
<cleanup
::CleanupScope
<'a
, 'tcx
>>>,
407 pub cfg
: Option
<cfg
::CFG
>,
410 impl<'a
, 'tcx
> FunctionContext
<'a
, 'tcx
> {
411 pub fn mir(&self) -> CachedMir
<'a
, 'tcx
> {
412 self.mir
.clone().expect("fcx.mir was empty")
415 pub fn cleanup(&self) {
417 llvm
::LLVMInstructionEraseFromParent(self.alloca_insert_pt
423 pub fn get_llreturn(&self) -> BasicBlockRef
{
424 if self.llreturn
.get().is_none() {
426 self.llreturn
.set(Some(unsafe {
427 llvm
::LLVMAppendBasicBlockInContext(self.ccx
.llcx(), self.llfn
,
428 "return\0".as_ptr() as *const _
)
432 self.llreturn
.get().unwrap()
435 pub fn get_ret_slot(&self, bcx
: Block
<'a
, 'tcx
>, name
: &str) -> ValueRef
{
436 if self.needs_ret_allocas
{
437 base
::alloca(bcx
, self.fn_ty
.ret
.memory_ty(self.ccx
), name
)
439 self.llretslotptr
.get().unwrap()
443 pub fn new_block(&'a
self,
445 opt_node_id
: Option
<ast
::NodeId
>)
448 let name
= CString
::new(name
).unwrap();
449 let llbb
= llvm
::LLVMAppendBasicBlockInContext(self.ccx
.llcx(),
452 BlockS
::new(llbb
, opt_node_id
, self)
456 pub fn new_id_block(&'a
self,
458 node_id
: ast
::NodeId
)
460 self.new_block(name
, Some(node_id
))
463 pub fn new_temp_block(&'a
self,
466 self.new_block(name
, None
)
469 pub fn join_blocks(&'a
self,
471 in_cxs
: &[Block
<'a
, 'tcx
>])
473 let out
= self.new_id_block("join", id
);
474 let mut reachable
= false;
476 if !bcx
.unreachable
.get() {
477 build
::Br(*bcx
, out
.llbb
, DebugLoc
::None
);
482 build
::Unreachable(out
);
487 pub fn monomorphize
<T
>(&self, value
: &T
) -> T
488 where T
: TransNormalize
<'tcx
>
490 monomorphize
::apply_param_substs(self.ccx
.tcx(),
495 /// This is the same as `common::type_needs_drop`, except that it
496 /// may use or update caches within this `FunctionContext`.
497 pub fn type_needs_drop(&self, ty
: Ty
<'tcx
>) -> bool
{
498 self.ccx
.tcx().type_needs_drop_given_env(ty
, &self.param_env
)
501 pub fn eh_personality(&self) -> ValueRef
{
502 // The exception handling personality function.
504 // If our compilation unit has the `eh_personality` lang item somewhere
505 // within it, then we just need to translate that. Otherwise, we're
506 // building an rlib which will depend on some upstream implementation of
507 // this function, so we just codegen a generic reference to it. We don't
508 // specify any of the types for the function, we just make it a symbol
509 // that LLVM can later use.
511 // Note that MSVC is a little special here in that we don't use the
512 // `eh_personality` lang item at all. Currently LLVM has support for
513 // both Dwarf and SEH unwind mechanisms for MSVC targets and uses the
514 // *name of the personality function* to decide what kind of unwind side
515 // tables/landing pads to emit. It looks like Dwarf is used by default,
516 // injecting a dependency on the `_Unwind_Resume` symbol for resuming
517 // an "exception", but for MSVC we want to force SEH. This means that we
518 // can't actually have the personality function be our standard
519 // `rust_eh_personality` function, but rather we wired it up to the
520 // CRT's custom personality function, which forces LLVM to consider
521 // landing pads as "landing pads for SEH".
524 match tcx
.lang_items
.eh_personality() {
525 Some(def_id
) if !base
::wants_msvc_seh(ccx
.sess()) => {
526 Callee
::def(ccx
, def_id
, tcx
.mk_substs(Substs
::empty())).reify(ccx
).val
529 if let Some(llpersonality
) = ccx
.eh_personality().get() {
532 let name
= if base
::wants_msvc_seh(ccx
.sess()) {
535 "rust_eh_personality"
537 let fty
= Type
::variadic_func(&[], &Type
::i32(ccx
));
538 let f
= declare
::declare_cfn(ccx
, name
, fty
);
539 ccx
.eh_personality().set(Some(f
));
545 // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined,
546 // otherwise declares it as an external function.
547 pub fn eh_unwind_resume(&self) -> Callee
<'tcx
> {
551 assert
!(ccx
.sess().target
.target
.options
.custom_unwind_resume
);
552 if let Some(def_id
) = tcx
.lang_items
.eh_unwind_resume() {
553 return Callee
::def(ccx
, def_id
, tcx
.mk_substs(Substs
::empty()));
556 let ty
= tcx
.mk_fn_ptr(tcx
.mk_bare_fn(ty
::BareFnTy
{
557 unsafety
: hir
::Unsafety
::Unsafe
,
559 sig
: ty
::Binder(ty
::FnSig
{
560 inputs
: vec
![tcx
.mk_mut_ptr(tcx
.types
.u8)],
561 output
: tcx
.types
.never
,
566 let unwresume
= ccx
.eh_unwind_resume();
567 if let Some(llfn
) = unwresume
.get() {
568 return Callee
::ptr(datum
::immediate_rvalue(llfn
, ty
));
570 let llfn
= declare
::declare_fn(ccx
, "rust_eh_unwind_resume", ty
);
571 attributes
::unwind(llfn
, true);
572 unwresume
.set(Some(llfn
));
573 Callee
::ptr(datum
::immediate_rvalue(llfn
, ty
))
577 // Basic block context. We create a block context for each basic block
578 // (single-entry, single-exit sequence of instructions) we generate from Rust
579 // code. Each basic block we generate is attached to a function, typically
580 // with many basic blocks per function. All the basic blocks attached to a
581 // function are organized as a directed graph.
582 pub struct BlockS
<'blk
, 'tcx
: 'blk
> {
583 // The BasicBlockRef returned from a call to
584 // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
585 // block to the function pointed to by llfn. We insert
586 // instructions into that block by way of this block context.
587 // The block pointing to this one in the function's digraph.
588 pub llbb
: BasicBlockRef
,
589 pub terminated
: Cell
<bool
>,
590 pub unreachable
: Cell
<bool
>,
592 // If this block part of a landing pad, then this is `Some` indicating what
593 // kind of landing pad its in, otherwise this is none.
594 pub lpad
: Cell
<Option
<&'blk LandingPad
>>,
596 // AST node-id associated with this block, if any. Used for
597 // debugging purposes only.
598 pub opt_node_id
: Option
<ast
::NodeId
>,
600 // The function context for the function to which this block is
602 pub fcx
: &'blk FunctionContext
<'blk
, 'tcx
>,
605 pub type Block
<'blk
, 'tcx
> = &'blk BlockS
<'blk
, 'tcx
>;
607 impl<'blk
, 'tcx
> BlockS
<'blk
, 'tcx
> {
608 pub fn new(llbb
: BasicBlockRef
,
609 opt_node_id
: Option
<ast
::NodeId
>,
610 fcx
: &'blk FunctionContext
<'blk
, 'tcx
>)
611 -> Block
<'blk
, 'tcx
> {
612 fcx
.block_arena
.alloc(BlockS
{
614 terminated
: Cell
::new(false),
615 unreachable
: Cell
::new(false),
616 lpad
: Cell
::new(None
),
617 opt_node_id
: opt_node_id
,
622 pub fn ccx(&self) -> &'blk CrateContext
<'blk
, 'tcx
> {
625 pub fn fcx(&self) -> &'blk FunctionContext
<'blk
, 'tcx
> {
628 pub fn tcx(&self) -> TyCtxt
<'blk
, 'tcx
, 'tcx
> {
631 pub fn sess(&self) -> &'blk Session { self.fcx.ccx.sess() }
633 pub fn lpad(&self) -> Option
<&'blk LandingPad
> {
637 pub fn set_lpad_ref(&self, lpad
: Option
<&'blk LandingPad
>) {
638 // FIXME: use an IVar?
642 pub fn set_lpad(&self, lpad
: Option
<LandingPad
>) {
643 self.set_lpad_ref(lpad
.map(|p
| &*self.fcx().lpad_arena
.alloc(p
)))
646 pub fn mir(&self) -> CachedMir
<'blk
, 'tcx
> {
650 pub fn name(&self, name
: ast
::Name
) -> String
{
654 pub fn node_id_to_string(&self, id
: ast
::NodeId
) -> String
{
655 self.tcx().map
.node_to_string(id
).to_string()
658 pub fn to_str(&self) -> String
{
659 format
!("[block {:p}]", self)
662 pub fn monomorphize
<T
>(&self, value
: &T
) -> T
663 where T
: TransNormalize
<'tcx
>
665 monomorphize
::apply_param_substs(self.tcx(),
666 self.fcx
.param_substs
,
670 pub fn build(&'blk
self) -> BlockAndBuilder
<'blk
, 'tcx
> {
671 BlockAndBuilder
::new(self, OwnedBuilder
::new_with_ccx(self.ccx()))
675 pub struct OwnedBuilder
<'blk
, 'tcx
: 'blk
> {
676 builder
: Builder
<'blk
, 'tcx
>
679 impl<'blk
, 'tcx
> OwnedBuilder
<'blk
, 'tcx
> {
680 pub fn new_with_ccx(ccx
: &'blk CrateContext
<'blk
, 'tcx
>) -> Self {
681 // Create a fresh builder from the crate context.
682 let llbuilder
= unsafe {
683 llvm
::LLVMCreateBuilderInContext(ccx
.llcx())
687 llbuilder
: llbuilder
,
694 impl<'blk
, 'tcx
> Drop
for OwnedBuilder
<'blk
, 'tcx
> {
697 llvm
::LLVMDisposeBuilder(self.builder
.llbuilder
);
702 pub struct BlockAndBuilder
<'blk
, 'tcx
: 'blk
> {
703 bcx
: Block
<'blk
, 'tcx
>,
704 owned_builder
: OwnedBuilder
<'blk
, 'tcx
>,
707 impl<'blk
, 'tcx
> BlockAndBuilder
<'blk
, 'tcx
> {
708 pub fn new(bcx
: Block
<'blk
, 'tcx
>, owned_builder
: OwnedBuilder
<'blk
, 'tcx
>) -> Self {
709 // Set the builder's position to this block's end.
710 owned_builder
.builder
.position_at_end(bcx
.llbb
);
713 owned_builder
: owned_builder
,
717 pub fn with_block
<F
, R
>(&self, f
: F
) -> R
718 where F
: FnOnce(Block
<'blk
, 'tcx
>) -> R
720 let result
= f(self.bcx
);
721 self.position_at_end(self.bcx
.llbb
);
725 pub fn map_block
<F
>(self, f
: F
) -> Self
726 where F
: FnOnce(Block
<'blk
, 'tcx
>) -> Block
<'blk
, 'tcx
>
728 let BlockAndBuilder { bcx, owned_builder }
= self;
730 BlockAndBuilder
::new(bcx
, owned_builder
)
733 pub fn at_start
<F
, R
>(&self, f
: F
) -> R
734 where F
: FnOnce(&BlockAndBuilder
<'blk
, 'tcx
>) -> R
736 self.position_at_start(self.bcx
.llbb
);
738 self.position_at_end(self.bcx
.llbb
);
742 // Methods delegated to bcx
744 pub fn is_unreachable(&self) -> bool
{
745 self.bcx
.unreachable
.get()
748 pub fn ccx(&self) -> &'blk CrateContext
<'blk
, 'tcx
> {
751 pub fn fcx(&self) -> &'blk FunctionContext
<'blk
, 'tcx
> {
754 pub fn tcx(&self) -> TyCtxt
<'blk
, 'tcx
, 'tcx
> {
757 pub fn sess(&self) -> &'blk Session
{
761 pub fn llbb(&self) -> BasicBlockRef
{
765 pub fn mir(&self) -> CachedMir
<'blk
, 'tcx
> {
769 pub fn monomorphize
<T
>(&self, value
: &T
) -> T
770 where T
: TransNormalize
<'tcx
>
772 self.bcx
.monomorphize(value
)
775 pub fn set_lpad(&self, lpad
: Option
<LandingPad
>) {
776 self.bcx
.set_lpad(lpad
)
779 pub fn set_lpad_ref(&self, lpad
: Option
<&'blk LandingPad
>) {
780 // FIXME: use an IVar?
781 self.bcx
.set_lpad_ref(lpad
);
784 pub fn lpad(&self) -> Option
<&'blk LandingPad
> {
789 impl<'blk
, 'tcx
> Deref
for BlockAndBuilder
<'blk
, 'tcx
> {
790 type Target
= Builder
<'blk
, 'tcx
>;
791 fn deref(&self) -> &Self::Target
{
792 &self.owned_builder
.builder
796 /// A structure representing an active landing pad for the duration of a basic
799 /// Each `Block` may contain an instance of this, indicating whether the block
800 /// is part of a landing pad or not. This is used to make decision about whether
801 /// to emit `invoke` instructions (e.g. in a landing pad we don't continue to
802 /// use `invoke`) and also about various function call metadata.
804 /// For GNU exceptions (`landingpad` + `resume` instructions) this structure is
805 /// just a bunch of `None` instances (not too interesting), but for MSVC
806 /// exceptions (`cleanuppad` + `cleanupret` instructions) this contains data.
807 /// When inside of a landing pad, each function call in LLVM IR needs to be
808 /// annotated with which landing pad it's a part of. This is accomplished via
809 /// the `OperandBundleDef` value created for MSVC landing pads.
810 pub struct LandingPad
{
811 cleanuppad
: Option
<ValueRef
>,
812 operand
: Option
<OperandBundleDef
>,
816 pub fn gnu() -> LandingPad
{
817 LandingPad { cleanuppad: None, operand: None }
820 pub fn msvc(cleanuppad
: ValueRef
) -> LandingPad
{
822 cleanuppad
: Some(cleanuppad
),
823 operand
: Some(OperandBundleDef
::new("funclet", &[cleanuppad
])),
827 pub fn bundle(&self) -> Option
<&OperandBundleDef
> {
828 self.operand
.as_ref()
831 pub fn cleanuppad(&self) -> Option
<ValueRef
> {
836 impl Clone
for LandingPad
{
837 fn clone(&self) -> LandingPad
{
839 cleanuppad
: self.cleanuppad
,
840 operand
: self.cleanuppad
.map(|p
| {
841 OperandBundleDef
::new("funclet", &[p
])
847 pub struct Result
<'blk
, 'tcx
: 'blk
> {
848 pub bcx
: Block
<'blk
, 'tcx
>,
852 impl<'b
, 'tcx
> Result
<'b
, 'tcx
> {
853 pub fn new(bcx
: Block
<'b
, 'tcx
>, val
: ValueRef
) -> Result
<'b
, 'tcx
> {
861 pub fn val_ty(v
: ValueRef
) -> Type
{
863 Type
::from_ref(llvm
::LLVMTypeOf(v
))
867 // LLVM constant constructors.
868 pub fn C_null(t
: Type
) -> ValueRef
{
870 llvm
::LLVMConstNull(t
.to_ref())
874 pub fn C_undef(t
: Type
) -> ValueRef
{
876 llvm
::LLVMGetUndef(t
.to_ref())
880 pub fn C_integral(t
: Type
, u
: u64, sign_extend
: bool
) -> ValueRef
{
882 llvm
::LLVMConstInt(t
.to_ref(), u
, sign_extend
as Bool
)
886 pub fn C_floating(s
: &str, t
: Type
) -> ValueRef
{
888 let s
= CString
::new(s
).unwrap();
889 llvm
::LLVMConstRealOfString(t
.to_ref(), s
.as_ptr())
893 pub fn C_floating_f64(f
: f64, t
: Type
) -> ValueRef
{
895 llvm
::LLVMConstReal(t
.to_ref(), f
)
899 pub fn C_nil(ccx
: &CrateContext
) -> ValueRef
{
900 C_struct(ccx
, &[], false)
903 pub fn C_bool(ccx
: &CrateContext
, val
: bool
) -> ValueRef
{
904 C_integral(Type
::i1(ccx
), val
as u64, false)
907 pub fn C_i32(ccx
: &CrateContext
, i
: i32) -> ValueRef
{
908 C_integral(Type
::i32(ccx
), i
as u64, true)
911 pub fn C_u32(ccx
: &CrateContext
, i
: u32) -> ValueRef
{
912 C_integral(Type
::i32(ccx
), i
as u64, false)
915 pub fn C_u64(ccx
: &CrateContext
, i
: u64) -> ValueRef
{
916 C_integral(Type
::i64(ccx
), i
, false)
919 pub fn C_int
<I
: AsI64
>(ccx
: &CrateContext
, i
: I
) -> ValueRef
{
922 let bit_size
= machine
::llbitsize_of_real(ccx
, ccx
.int_type());
925 // make sure it doesn't overflow
926 assert
!(v
< (1<<(bit_size
-1)) && v
>= -(1<<(bit_size
-1)));
929 C_integral(ccx
.int_type(), v
as u64, true)
932 pub fn C_uint
<I
: AsU64
>(ccx
: &CrateContext
, i
: I
) -> ValueRef
{
935 let bit_size
= machine
::llbitsize_of_real(ccx
, ccx
.int_type());
938 // make sure it doesn't overflow
939 assert
!(v
< (1<<bit_size
));
942 C_integral(ccx
.int_type(), v
, false)
945 pub trait AsI64 { fn as_i64(self) -> i64; }
946 pub trait AsU64 { fn as_u64(self) -> u64; }
948 // FIXME: remove the intptr conversions, because they
949 // are host-architecture-dependent
950 impl AsI64
for i64 { fn as_i64(self) -> i64 { self as i64 }
}
951 impl AsI64
for i32 { fn as_i64(self) -> i64 { self as i64 }
}
952 impl AsI64
for isize { fn as_i64(self) -> i64 { self as i64 }
}
954 impl AsU64
for u64 { fn as_u64(self) -> u64 { self as u64 }
}
955 impl AsU64
for u32 { fn as_u64(self) -> u64 { self as u64 }
}
956 impl AsU64
for usize { fn as_u64(self) -> u64 { self as u64 }
}
958 pub fn C_u8(ccx
: &CrateContext
, i
: u8) -> ValueRef
{
959 C_integral(Type
::i8(ccx
), i
as u64, false)
963 // This is a 'c-like' raw string, which differs from
964 // our boxed-and-length-annotated strings.
965 pub fn C_cstr(cx
: &CrateContext
, s
: InternedString
, null_terminated
: bool
) -> ValueRef
{
967 if let Some(&llval
) = cx
.const_cstr_cache().borrow().get(&s
) {
971 let sc
= llvm
::LLVMConstStringInContext(cx
.llcx(),
972 s
.as_ptr() as *const c_char
,
974 !null_terminated
as Bool
);
976 let gsym
= token
::gensym("str");
977 let sym
= format
!("str{}", gsym
.0);
978 let g
= declare
::define_global(cx
, &sym
[..], val_ty(sc
)).unwrap_or_else(||{
979 bug
!("symbol `{}` is already defined", sym
);
981 llvm
::LLVMSetInitializer(g
, sc
);
982 llvm
::LLVMSetGlobalConstant(g
, True
);
983 llvm
::LLVMSetLinkage(g
, llvm
::InternalLinkage
);
985 cx
.const_cstr_cache().borrow_mut().insert(s
, g
);
990 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
991 // you will be kicked off fast isel. See issue #4352 for an example of this.
992 pub fn C_str_slice(cx
: &CrateContext
, s
: InternedString
) -> ValueRef
{
994 let cs
= consts
::ptrcast(C_cstr(cx
, s
, false), Type
::i8p(cx
));
995 C_named_struct(cx
.tn().find_type("str_slice").unwrap(), &[cs
, C_uint(cx
, len
)])
998 pub fn C_struct(cx
: &CrateContext
, elts
: &[ValueRef
], packed
: bool
) -> ValueRef
{
999 C_struct_in_context(cx
.llcx(), elts
, packed
)
1002 pub fn C_struct_in_context(llcx
: ContextRef
, elts
: &[ValueRef
], packed
: bool
) -> ValueRef
{
1004 llvm
::LLVMConstStructInContext(llcx
,
1005 elts
.as_ptr(), elts
.len() as c_uint
,
1010 pub fn C_named_struct(t
: Type
, elts
: &[ValueRef
]) -> ValueRef
{
1012 llvm
::LLVMConstNamedStruct(t
.to_ref(), elts
.as_ptr(), elts
.len() as c_uint
)
1016 pub fn C_array(ty
: Type
, elts
: &[ValueRef
]) -> ValueRef
{
1018 return llvm
::LLVMConstArray(ty
.to_ref(), elts
.as_ptr(), elts
.len() as c_uint
);
1022 pub fn C_vector(elts
: &[ValueRef
]) -> ValueRef
{
1024 return llvm
::LLVMConstVector(elts
.as_ptr(), elts
.len() as c_uint
);
1028 pub fn C_bytes(cx
: &CrateContext
, bytes
: &[u8]) -> ValueRef
{
1029 C_bytes_in_context(cx
.llcx(), bytes
)
1032 pub fn C_bytes_in_context(llcx
: ContextRef
, bytes
: &[u8]) -> ValueRef
{
1034 let ptr
= bytes
.as_ptr() as *const c_char
;
1035 return llvm
::LLVMConstStringInContext(llcx
, ptr
, bytes
.len() as c_uint
, True
);
1039 pub fn const_get_elt(v
: ValueRef
, us
: &[c_uint
])
1042 let r
= llvm
::LLVMConstExtractValue(v
, us
.as_ptr(), us
.len() as c_uint
);
1044 debug
!("const_get_elt(v={:?}, us={:?}, r={:?})",
1045 Value(v
), us
, Value(r
));
1051 pub fn const_to_int(v
: ValueRef
) -> i64 {
1053 llvm
::LLVMConstIntGetSExtValue(v
)
1057 pub fn const_to_uint(v
: ValueRef
) -> u64 {
1059 llvm
::LLVMConstIntGetZExtValue(v
)
1063 fn is_const_integral(v
: ValueRef
) -> bool
{
1065 !llvm
::LLVMIsAConstantInt(v
).is_null()
1069 pub fn const_to_opt_int(v
: ValueRef
) -> Option
<i64> {
1071 if is_const_integral(v
) {
1072 Some(llvm
::LLVMConstIntGetSExtValue(v
))
1079 pub fn const_to_opt_uint(v
: ValueRef
) -> Option
<u64> {
1081 if is_const_integral(v
) {
1082 Some(llvm
::LLVMConstIntGetZExtValue(v
))
1089 pub fn is_undef(val
: ValueRef
) -> bool
{
1091 llvm
::LLVMIsUndef(val
) != False
1095 #[allow(dead_code)] // potentially useful
1096 pub fn is_null(val
: ValueRef
) -> bool
{
1098 llvm
::LLVMIsNull(val
) != False
1102 pub fn monomorphize_type
<'blk
, 'tcx
>(bcx
: &BlockS
<'blk
, 'tcx
>, t
: Ty
<'tcx
>) -> Ty
<'tcx
> {
1103 bcx
.fcx
.monomorphize(&t
)
1106 pub fn node_id_type
<'blk
, 'tcx
>(bcx
: &BlockS
<'blk
, 'tcx
>, id
: ast
::NodeId
) -> Ty
<'tcx
> {
1107 let tcx
= bcx
.tcx();
1108 let t
= tcx
.node_id_to_type(id
);
1109 monomorphize_type(bcx
, t
)
1112 pub fn expr_ty
<'blk
, 'tcx
>(bcx
: &BlockS
<'blk
, 'tcx
>, ex
: &hir
::Expr
) -> Ty
<'tcx
> {
1113 node_id_type(bcx
, ex
.id
)
1116 pub fn expr_ty_adjusted
<'blk
, 'tcx
>(bcx
: &BlockS
<'blk
, 'tcx
>, ex
: &hir
::Expr
) -> Ty
<'tcx
> {
1117 monomorphize_type(bcx
, bcx
.tcx().expr_ty_adjusted(ex
))
1120 /// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we
1121 /// do not (necessarily) resolve all nested obligations on the impl. Note that type check should
1122 /// guarantee to us that all nested obligations *could be* resolved if we wanted to.
1123 pub fn fulfill_obligation
<'a
, 'tcx
>(scx
: &SharedCrateContext
<'a
, 'tcx
>,
1125 trait_ref
: ty
::PolyTraitRef
<'tcx
>)
1126 -> traits
::Vtable
<'tcx
, ()>
1128 let tcx
= scx
.tcx();
1130 // Remove any references to regions; this helps improve caching.
1131 let trait_ref
= tcx
.erase_regions(&trait_ref
);
1133 scx
.trait_cache().memoize(trait_ref
, || {
1134 debug
!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
1135 trait_ref
, trait_ref
.def_id());
1137 // Do the initial selection for the obligation. This yields the
1138 // shallow result we are looking for -- that is, what specific impl.
1139 tcx
.normalizing_infer_ctxt(Reveal
::All
).enter(|infcx
| {
1140 let mut selcx
= SelectionContext
::new(&infcx
);
1142 let obligation_cause
= traits
::ObligationCause
::misc(span
,
1143 ast
::DUMMY_NODE_ID
);
1144 let obligation
= traits
::Obligation
::new(obligation_cause
,
1145 trait_ref
.to_poly_trait_predicate());
1147 let selection
= match selcx
.select(&obligation
) {
1148 Ok(Some(selection
)) => selection
,
1150 // Ambiguity can happen when monomorphizing during trans
1151 // expands to some humongo type that never occurred
1152 // statically -- this humongo type can then overflow,
1153 // leading to an ambiguous result. So report this as an
1154 // overflow bug, since I believe this is the only case
1155 // where ambiguity can result.
1156 debug
!("Encountered ambiguity selecting `{:?}` during trans, \
1157 presuming due to overflow",
1159 tcx
.sess
.span_fatal(span
,
1160 "reached the recursion limit during monomorphization \
1161 (selection ambiguity)");
1164 span_bug
!(span
, "Encountered error `{:?}` selecting `{:?}` during trans",
1169 debug
!("fulfill_obligation: selection={:?}", selection
);
1171 // Currently, we use a fulfillment context to completely resolve
1172 // all nested obligations. This is because they can inform the
1173 // inference of the impl's type parameters.
1174 let mut fulfill_cx
= traits
::FulfillmentContext
::new();
1175 let vtable
= selection
.map(|predicate
| {
1176 debug
!("fulfill_obligation: register_predicate_obligation {:?}", predicate
);
1177 fulfill_cx
.register_predicate_obligation(&infcx
, predicate
);
1179 let vtable
= infcx
.drain_fulfillment_cx_or_panic(span
, &mut fulfill_cx
, &vtable
);
1181 info
!("Cache miss: {:?} => {:?}", trait_ref
, vtable
);
1187 /// Normalizes the predicates and checks whether they hold. If this
1188 /// returns false, then either normalize encountered an error or one
1189 /// of the predicates did not hold. Used when creating vtables to
1190 /// check for unsatisfiable methods.
1191 pub fn normalize_and_test_predicates
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
1192 predicates
: Vec
<ty
::Predicate
<'tcx
>>)
1195 debug
!("normalize_and_test_predicates(predicates={:?})",
1198 tcx
.normalizing_infer_ctxt(Reveal
::All
).enter(|infcx
| {
1199 let mut selcx
= SelectionContext
::new(&infcx
);
1200 let mut fulfill_cx
= traits
::FulfillmentContext
::new();
1201 let cause
= traits
::ObligationCause
::dummy();
1202 let traits
::Normalized { value: predicates, obligations }
=
1203 traits
::normalize(&mut selcx
, cause
.clone(), &predicates
);
1204 for obligation
in obligations
{
1205 fulfill_cx
.register_predicate_obligation(&infcx
, obligation
);
1207 for predicate
in predicates
{
1208 let obligation
= traits
::Obligation
::new(cause
.clone(), predicate
);
1209 fulfill_cx
.register_predicate_obligation(&infcx
, obligation
);
1212 infcx
.drain_fulfillment_cx(&mut fulfill_cx
, &()).is_ok()
1216 pub fn langcall(tcx
: TyCtxt
,
1221 match tcx
.lang_items
.require(li
) {
1224 let msg
= format
!("{} {}", msg
, s
);
1226 Some(span
) => tcx
.sess
.span_fatal(span
, &msg
[..]),
1227 None
=> tcx
.sess
.fatal(&msg
[..]),
1233 /// Return the VariantDef corresponding to an inlined variant node
1234 pub fn inlined_variant_def
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
1235 inlined_vid
: ast
::NodeId
)
1236 -> ty
::VariantDef
<'tcx
>
1238 let ctor_ty
= ccx
.tcx().node_id_to_type(inlined_vid
);
1239 debug
!("inlined_variant_def: ctor_ty={:?} inlined_vid={:?}", ctor_ty
,
1241 let adt_def
= match ctor_ty
.sty
{
1242 ty
::TyFnDef(_
, _
, &ty
::BareFnTy
{ sig
: ty
::Binder(ty
::FnSig
{
1246 }.ty_adt_def().unwrap();
1247 let variant_def_id
= if ccx
.tcx().map
.is_inlined_node_id(inlined_vid
) {
1248 ccx
.defid_for_inlined_node(inlined_vid
).unwrap()
1250 ccx
.tcx().map
.local_def_id(inlined_vid
)
1255 .find(|v
| variant_def_id
== v
.did
)
1256 .unwrap_or_else(|| {
1257 bug
!("no variant for {:?}::{}", adt_def
, inlined_vid
)
1261 // To avoid UB from LLVM, these two functions mask RHS with an
1262 // appropriate mask unconditionally (i.e. the fallback behavior for
1263 // all shifts). For 32- and 64-bit types, this matches the semantics
1264 // of Java. (See related discussion on #1877 and #10183.)
1266 pub fn build_unchecked_lshift
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
1269 binop_debug_loc
: DebugLoc
) -> ValueRef
{
1270 let rhs
= base
::cast_shift_expr_rhs(bcx
, hir
::BinOp_
::BiShl
, lhs
, rhs
);
1271 // #1877, #10183: Ensure that input is always valid
1272 let rhs
= shift_mask_rhs(bcx
, rhs
, binop_debug_loc
);
1273 build
::Shl(bcx
, lhs
, rhs
, binop_debug_loc
)
1276 pub fn build_unchecked_rshift
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
1280 binop_debug_loc
: DebugLoc
) -> ValueRef
{
1281 let rhs
= base
::cast_shift_expr_rhs(bcx
, hir
::BinOp_
::BiShr
, lhs
, rhs
);
1282 // #1877, #10183: Ensure that input is always valid
1283 let rhs
= shift_mask_rhs(bcx
, rhs
, binop_debug_loc
);
1284 let is_signed
= lhs_t
.is_signed();
1286 build
::AShr(bcx
, lhs
, rhs
, binop_debug_loc
)
1288 build
::LShr(bcx
, lhs
, rhs
, binop_debug_loc
)
1292 fn shift_mask_rhs
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
1294 debug_loc
: DebugLoc
) -> ValueRef
{
1295 let rhs_llty
= val_ty(rhs
);
1296 build
::And(bcx
, rhs
, shift_mask_val(bcx
, rhs_llty
, rhs_llty
, false), debug_loc
)
1299 pub fn shift_mask_val
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
1302 invert
: bool
) -> ValueRef
{
1303 let kind
= llty
.kind();
1305 TypeKind
::Integer
=> {
1306 // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
1307 let val
= llty
.int_width() - 1;
1309 C_integral(mask_llty
, !val
, true)
1311 C_integral(mask_llty
, val
, false)
1314 TypeKind
::Vector
=> {
1315 let mask
= shift_mask_val(bcx
, llty
.element_type(), mask_llty
.element_type(), invert
);
1316 build
::VectorSplat(bcx
, mask_llty
.vector_length(), mask
)
1318 _
=> bug
!("shift_mask_val: expected Integer or Vector, found {:?}", kind
),