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 use common
::{C_i32, C_null}
;
13 use llvm
::{self, ValueRef, BasicBlockRef}
;
14 use llvm
::debuginfo
::DIScope
;
15 use rustc
::ty
::{self, Ty, TypeFoldable}
;
16 use rustc
::ty
::layout
::{LayoutOf, TyLayout}
;
17 use rustc
::mir
::{self, Mir}
;
18 use rustc
::ty
::subst
::Substs
;
19 use rustc
::session
::config
::FullDebugInfo
;
22 use common
::{CodegenCx, Funclet}
;
23 use debuginfo
::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext}
;
24 use monomorphize
::Instance
;
25 use abi
::{ArgAttribute, ArgTypeExt, FnType, FnTypeExt, PassMode}
;
28 use syntax_pos
::{DUMMY_SP, NO_EXPANSION, BytePos, Span}
;
29 use syntax
::symbol
::keywords
;
33 use rustc_data_structures
::bitvec
::BitVector
;
34 use rustc_data_structures
::indexed_vec
::{IndexVec, Idx}
;
36 pub use self::constant
::trans_static_initializer
;
38 use self::analyze
::CleanupKind
;
39 use self::place
::PlaceRef
;
40 use rustc
::mir
::traversal
;
42 use self::operand
::{OperandRef, OperandValue}
;
44 /// Master context for translating MIR.
45 pub struct FunctionCx
<'a
, 'tcx
:'a
> {
46 instance
: Instance
<'tcx
>,
48 mir
: &'a mir
::Mir
<'tcx
>,
50 debug_context
: debuginfo
::FunctionDebugContext
,
54 cx
: &'a CodegenCx
<'a
, 'tcx
>,
56 fn_ty
: FnType
<'tcx
, Ty
<'tcx
>>,
58 /// When unwinding is initiated, we have to store this personality
59 /// value somewhere so that we can load it and re-use it in the
60 /// resume instruction. The personality is (afaik) some kind of
61 /// value used for C++ unwinding, which must filter by type: we
62 /// don't really care about it very much. Anyway, this value
63 /// contains an alloca into which the personality is stored and
64 /// then later loaded when generating the DIVERGE_BLOCK.
65 personality_slot
: Option
<PlaceRef
<'tcx
>>,
67 /// A `Block` for each MIR `BasicBlock`
68 blocks
: IndexVec
<mir
::BasicBlock
, BasicBlockRef
>,
70 /// The funclet status of each basic block
71 cleanup_kinds
: IndexVec
<mir
::BasicBlock
, analyze
::CleanupKind
>,
73 /// When targeting MSVC, this stores the cleanup info for each funclet
74 /// BB. This is initialized as we compute the funclets' head block in RPO.
75 funclets
: &'a IndexVec
<mir
::BasicBlock
, Option
<Funclet
>>,
77 /// This stores the landing-pad block for a given BB, computed lazily on GNU
78 /// and eagerly on MSVC.
79 landing_pads
: IndexVec
<mir
::BasicBlock
, Option
<BasicBlockRef
>>,
81 /// Cached unreachable block
82 unreachable_block
: Option
<BasicBlockRef
>,
84 /// The location where each MIR arg/var/tmp/ret is stored. This is
85 /// usually an `PlaceRef` representing an alloca, but not always:
86 /// sometimes we can skip the alloca and just store the value
87 /// directly using an `OperandRef`, which makes for tighter LLVM
88 /// IR. The conditions for using an `OperandRef` are as follows:
90 /// - the type of the local must be judged "immediate" by `is_llvm_immediate`
91 /// - the operand must never be referenced indirectly
92 /// - we should not take its address using the `&` operator
93 /// - nor should it appear in a place path like `tmp.a`
94 /// - the operand must be defined by an rvalue that can generate immediate
97 /// Avoiding allocs can also be important for certain intrinsics,
99 locals
: IndexVec
<mir
::Local
, LocalRef
<'tcx
>>,
101 /// Debug information for MIR scopes.
102 scopes
: IndexVec
<mir
::VisibilityScope
, debuginfo
::MirDebugScope
>,
104 /// If this function is being monomorphized, this contains the type substitutions used.
105 param_substs
: &'tcx Substs
<'tcx
>,
108 impl<'a
, 'tcx
> FunctionCx
<'a
, 'tcx
> {
109 pub fn monomorphize
<T
>(&self, value
: &T
) -> T
110 where T
: TypeFoldable
<'tcx
>
112 self.cx
.tcx
.subst_and_normalize_erasing_regions(
114 ty
::ParamEnv
::reveal_all(),
119 pub fn set_debug_loc(&mut self, bx
: &Builder
, source_info
: mir
::SourceInfo
) {
120 let (scope
, span
) = self.debug_loc(source_info
);
121 debuginfo
::set_source_location(&self.debug_context
, bx
, scope
, span
);
124 pub fn debug_loc(&mut self, source_info
: mir
::SourceInfo
) -> (DIScope
, Span
) {
125 // Bail out if debug info emission is not enabled.
126 match self.debug_context
{
127 FunctionDebugContext
::DebugInfoDisabled
|
128 FunctionDebugContext
::FunctionWithoutDebugInfo
=> {
129 return (self.scopes
[source_info
.scope
].scope_metadata
, source_info
.span
);
131 FunctionDebugContext
::RegularContext(_
) =>{}
134 // In order to have a good line stepping behavior in debugger, we overwrite debug
135 // locations of macro expansions with that of the outermost expansion site
136 // (unless the crate is being compiled with `-Z debug-macros`).
137 if source_info
.span
.ctxt() == NO_EXPANSION
||
138 self.cx
.sess().opts
.debugging_opts
.debug_macros
{
139 let scope
= self.scope_metadata_for_loc(source_info
.scope
, source_info
.span
.lo());
140 (scope
, source_info
.span
)
142 // Walk up the macro expansion chain until we reach a non-expanded span.
143 // We also stop at the function body level because no line stepping can occur
144 // at the level above that.
145 let mut span
= source_info
.span
;
146 while span
.ctxt() != NO_EXPANSION
&& span
.ctxt() != self.mir
.span
.ctxt() {
147 if let Some(info
) = span
.ctxt().outer().expn_info() {
148 span
= info
.call_site
;
153 let scope
= self.scope_metadata_for_loc(source_info
.scope
, span
.lo());
154 // Use span of the outermost expansion site, while keeping the original lexical scope.
159 // DILocations inherit source file name from the parent DIScope. Due to macro expansions
160 // it may so happen that the current span belongs to a different file than the DIScope
161 // corresponding to span's containing visibility scope. If so, we need to create a DIScope
162 // "extension" into that file.
163 fn scope_metadata_for_loc(&self, scope_id
: mir
::VisibilityScope
, pos
: BytePos
)
164 -> llvm
::debuginfo
::DIScope
{
165 let scope_metadata
= self.scopes
[scope_id
].scope_metadata
;
166 if pos
< self.scopes
[scope_id
].file_start_pos
||
167 pos
>= self.scopes
[scope_id
].file_end_pos
{
168 let cm
= self.cx
.sess().codemap();
169 let defining_crate
= self.debug_context
.get_ref(DUMMY_SP
).defining_crate
;
170 debuginfo
::extend_scope_to_file(self.cx
,
172 &cm
.lookup_char_pos(pos
).file
,
180 enum LocalRef
<'tcx
> {
181 Place(PlaceRef
<'tcx
>),
182 Operand(Option
<OperandRef
<'tcx
>>),
185 impl<'a
, 'tcx
> LocalRef
<'tcx
> {
186 fn new_operand(cx
: &CodegenCx
<'a
, 'tcx
>, layout
: TyLayout
<'tcx
>) -> LocalRef
<'tcx
> {
188 // Zero-size temporaries aren't always initialized, which
189 // doesn't matter because they don't contain data, but
190 // we need something in the operand.
191 LocalRef
::Operand(Some(OperandRef
::new_zst(cx
, layout
)))
193 LocalRef
::Operand(None
)
198 ///////////////////////////////////////////////////////////////////////////
200 pub fn trans_mir
<'a
, 'tcx
: 'a
>(
201 cx
: &'a CodegenCx
<'a
, 'tcx
>,
204 instance
: Instance
<'tcx
>,
205 sig
: ty
::FnSig
<'tcx
>,
207 let fn_ty
= FnType
::new(cx
, sig
, &[]);
208 debug
!("fn_ty: {:?}", fn_ty
);
210 debuginfo
::create_function_debug_context(cx
, instance
, sig
, llfn
, mir
);
211 let bx
= Builder
::new_block(cx
, llfn
, "start");
213 if mir
.basic_blocks().iter().any(|bb
| bb
.is_cleanup
) {
214 bx
.set_personality_fn(cx
.eh_personality());
217 let cleanup_kinds
= analyze
::cleanup_kinds(&mir
);
218 // Allocate a `Block` for every basic block, except
219 // the start block, if nothing loops back to it.
220 let reentrant_start_block
= !mir
.predecessors_for(mir
::START_BLOCK
).is_empty();
221 let block_bxs
: IndexVec
<mir
::BasicBlock
, BasicBlockRef
> =
222 mir
.basic_blocks().indices().map(|bb
| {
223 if bb
== mir
::START_BLOCK
&& !reentrant_start_block
{
226 bx
.build_sibling_block(&format
!("{:?}", bb
)).llbb()
230 // Compute debuginfo scopes from MIR scopes.
231 let scopes
= debuginfo
::create_mir_scopes(cx
, mir
, &debug_context
);
232 let (landing_pads
, funclets
) = create_funclets(mir
, &bx
, &cleanup_kinds
, &block_bxs
);
234 let mut fx
= FunctionCx
{
240 personality_slot
: None
,
242 unreachable_block
: None
,
247 locals
: IndexVec
::new(),
250 assert
!(!instance
.substs
.needs_infer());
255 let memory_locals
= analyze
::non_ssa_locals(&fx
);
257 // Allocate variable and temp allocas
259 let args
= arg_local_refs(&bx
, &fx
, &fx
.scopes
, &memory_locals
);
261 let mut allocate_local
= |local
| {
262 let decl
= &mir
.local_decls
[local
];
263 let layout
= bx
.cx
.layout_of(fx
.monomorphize(&decl
.ty
));
264 assert
!(!layout
.ty
.has_erasable_regions());
266 if let Some(name
) = decl
.name
{
268 let debug_scope
= fx
.scopes
[decl
.source_info
.scope
];
269 let dbg
= debug_scope
.is_valid() && bx
.sess().opts
.debuginfo
== FullDebugInfo
;
271 if !memory_locals
.contains(local
.index()) && !dbg
{
272 debug
!("alloc: {:?} ({}) -> operand", local
, name
);
273 return LocalRef
::new_operand(bx
.cx
, layout
);
276 debug
!("alloc: {:?} ({}) -> place", local
, name
);
277 let place
= PlaceRef
::alloca(&bx
, layout
, &name
.as_str());
279 let (scope
, span
) = fx
.debug_loc(decl
.source_info
);
280 declare_local(&bx
, &fx
.debug_context
, name
, layout
.ty
, scope
,
281 VariableAccess
::DirectVariable { alloca: place.llval }
,
282 VariableKind
::LocalVariable
, span
);
284 LocalRef
::Place(place
)
286 // Temporary or return place
287 if local
== mir
::RETURN_PLACE
&& fx
.fn_ty
.ret
.is_indirect() {
288 debug
!("alloc: {:?} (return place) -> place", local
);
289 let llretptr
= llvm
::get_param(llfn
, 0);
290 LocalRef
::Place(PlaceRef
::new_sized(llretptr
, layout
, layout
.align
))
291 } else if memory_locals
.contains(local
.index()) {
292 debug
!("alloc: {:?} -> place", local
);
293 LocalRef
::Place(PlaceRef
::alloca(&bx
, layout
, &format
!("{:?}", local
)))
295 // If this is an immediate local, we do not create an
296 // alloca in advance. Instead we wait until we see the
297 // definition and update the operand there.
298 debug
!("alloc: {:?} -> operand", local
);
299 LocalRef
::new_operand(bx
.cx
, layout
)
304 let retptr
= allocate_local(mir
::RETURN_PLACE
);
306 .chain(args
.into_iter())
307 .chain(mir
.vars_and_temps_iter().map(allocate_local
))
311 // Branch to the START block, if it's not the entry block.
312 if reentrant_start_block
{
313 bx
.br(fx
.blocks
[mir
::START_BLOCK
]);
316 // Up until here, IR instructions for this function have explicitly not been annotated with
317 // source code location, so we don't step into call setup code. From here on, source location
318 // emitting should be enabled.
319 debuginfo
::start_emitting_source_locations(&fx
.debug_context
);
321 let rpo
= traversal
::reverse_postorder(&mir
);
322 let mut visited
= BitVector
::new(mir
.basic_blocks().len());
324 // Translate the body of each block using reverse postorder
326 visited
.insert(bb
.index());
330 // Remove blocks that haven't been visited, or have no
332 for bb
in mir
.basic_blocks().indices() {
334 if !visited
.contains(bb
.index()) {
335 debug
!("trans_mir: block {:?} was not visited", bb
);
337 llvm
::LLVMDeleteBasicBlock(fx
.blocks
[bb
]);
343 fn create_funclets
<'a
, 'tcx
>(
345 bx
: &Builder
<'a
, 'tcx
>,
346 cleanup_kinds
: &IndexVec
<mir
::BasicBlock
, CleanupKind
>,
347 block_bxs
: &IndexVec
<mir
::BasicBlock
, BasicBlockRef
>)
348 -> (IndexVec
<mir
::BasicBlock
, Option
<BasicBlockRef
>>,
349 IndexVec
<mir
::BasicBlock
, Option
<Funclet
>>)
351 block_bxs
.iter_enumerated().zip(cleanup_kinds
).map(|((bb
, &llbb
), cleanup_kind
)| {
352 match *cleanup_kind
{
353 CleanupKind
::Funclet
if base
::wants_msvc_seh(bx
.sess()) => {}
354 _
=> return (None
, None
)
359 match mir
[bb
].terminator
.as_ref().map(|t
| &t
.kind
) {
360 // This is a basic block that we're aborting the program for,
361 // notably in an `extern` function. These basic blocks are inserted
362 // so that we assert that `extern` functions do indeed not panic,
363 // and if they do we abort the process.
365 // On MSVC these are tricky though (where we're doing funclets). If
366 // we were to do a cleanuppad (like below) the normal functions like
367 // `longjmp` would trigger the abort logic, terminating the
368 // program. Instead we insert the equivalent of `catch(...)` for C++
369 // which magically doesn't trigger when `longjmp` files over this
372 // Lots more discussion can be found on #48251 but this codegen is
373 // modeled after clang's for:
380 Some(&mir
::TerminatorKind
::Abort
) => {
381 let cs_bx
= bx
.build_sibling_block(&format
!("cs_funclet{:?}", bb
));
382 let cp_bx
= bx
.build_sibling_block(&format
!("cp_funclet{:?}", bb
));
383 ret_llbb
= cs_bx
.llbb();
385 let cs
= cs_bx
.catch_switch(None
, None
, 1);
386 cs_bx
.add_handler(cs
, cp_bx
.llbb());
388 // The "null" here is actually a RTTI type descriptor for the
389 // C++ personality function, but `catch (...)` has no type so
390 // it's null. The 64 here is actually a bitfield which
391 // represents that this is a catch-all block.
392 let null
= C_null(Type
::i8p(bx
.cx
));
393 let sixty_four
= C_i32(bx
.cx
, 64);
394 cleanup
= cp_bx
.catch_pad(cs
, &[null
, sixty_four
, null
]);
398 let cleanup_bx
= bx
.build_sibling_block(&format
!("funclet_{:?}", bb
));
399 ret_llbb
= cleanup_bx
.llbb();
400 cleanup
= cleanup_bx
.cleanup_pad(None
, &[]);
405 (Some(ret_llbb
), Some(Funclet
::new(cleanup
)))
409 /// Produce, for each argument, a `ValueRef` pointing at the
410 /// argument's value. As arguments are places, these are always
412 fn arg_local_refs
<'a
, 'tcx
>(bx
: &Builder
<'a
, 'tcx
>,
413 fx
: &FunctionCx
<'a
, 'tcx
>,
414 scopes
: &IndexVec
<mir
::VisibilityScope
, debuginfo
::MirDebugScope
>,
415 memory_locals
: &BitVector
)
416 -> Vec
<LocalRef
<'tcx
>> {
420 let mut llarg_idx
= fx
.fn_ty
.ret
.is_indirect() as usize;
422 // Get the argument scope, if it exists and if we need it.
423 let arg_scope
= scopes
[mir
::ARGUMENT_VISIBILITY_SCOPE
];
424 let arg_scope
= if arg_scope
.is_valid() && bx
.sess().opts
.debuginfo
== FullDebugInfo
{
425 Some(arg_scope
.scope_metadata
)
430 let deref_op
= unsafe {
431 [llvm
::LLVMRustDIBuilderCreateOpDeref()]
434 mir
.args_iter().enumerate().map(|(arg_index
, local
)| {
435 let arg_decl
= &mir
.local_decls
[local
];
437 let name
= if let Some(name
) = arg_decl
.name
{
438 name
.as_str().to_string()
440 format
!("arg{}", arg_index
)
443 if Some(local
) == mir
.spread_arg
{
444 // This argument (e.g. the last argument in the "rust-call" ABI)
445 // is a tuple that was spread at the ABI level and now we have
446 // to reconstruct it into a tuple local variable, from multiple
447 // individual LLVM function arguments.
449 let arg_ty
= fx
.monomorphize(&arg_decl
.ty
);
450 let tupled_arg_tys
= match arg_ty
.sty
{
451 ty
::TyTuple(ref tys
) => tys
,
452 _
=> bug
!("spread argument isn't a tuple?!")
455 let place
= PlaceRef
::alloca(bx
, bx
.cx
.layout_of(arg_ty
), &name
);
456 for i
in 0..tupled_arg_tys
.len() {
457 let arg
= &fx
.fn_ty
.args
[idx
];
459 if arg
.pad
.is_some() {
462 arg
.store_fn_arg(bx
, &mut llarg_idx
, place
.project_field(bx
, i
));
465 // Now that we have one alloca that contains the aggregate value,
466 // we can create one debuginfo entry for the argument.
467 arg_scope
.map(|scope
| {
468 let variable_access
= VariableAccess
::DirectVariable
{
474 arg_decl
.name
.unwrap_or(keywords
::Invalid
.name()),
477 VariableKind
::ArgumentVariable(arg_index
+ 1),
482 return LocalRef
::Place(place
);
485 let arg
= &fx
.fn_ty
.args
[idx
];
487 if arg
.pad
.is_some() {
491 if arg_scope
.is_none() && !memory_locals
.contains(local
.index()) {
492 // We don't have to cast or keep the argument in the alloca.
493 // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
494 // of putting everything in allocas just so we can use llvm.dbg.declare.
495 let local
= |op
| LocalRef
::Operand(Some(op
));
497 PassMode
::Ignore
=> {
498 return local(OperandRef
::new_zst(bx
.cx
, arg
.layout
));
500 PassMode
::Direct(_
) => {
501 let llarg
= llvm
::get_param(bx
.llfn(), llarg_idx
as c_uint
);
502 bx
.set_value_name(llarg
, &name
);
505 OperandRef
::from_immediate_or_packed_pair(bx
, llarg
, arg
.layout
));
507 PassMode
::Pair(..) => {
508 let a
= llvm
::get_param(bx
.llfn(), llarg_idx
as c_uint
);
509 bx
.set_value_name(a
, &(name
.clone() + ".0"));
512 let b
= llvm
::get_param(bx
.llfn(), llarg_idx
as c_uint
);
513 bx
.set_value_name(b
, &(name
+ ".1"));
516 return local(OperandRef
{
517 val
: OperandValue
::Pair(a
, b
),
525 let place
= if arg
.is_indirect() {
526 // Don't copy an indirect argument to an alloca, the caller
527 // already put it in a temporary alloca and gave it up.
529 let llarg
= llvm
::get_param(bx
.llfn(), llarg_idx
as c_uint
);
530 bx
.set_value_name(llarg
, &name
);
532 PlaceRef
::new_sized(llarg
, arg
.layout
, arg
.layout
.align
)
534 let tmp
= PlaceRef
::alloca(bx
, arg
.layout
, &name
);
535 arg
.store_fn_arg(bx
, &mut llarg_idx
, tmp
);
538 arg_scope
.map(|scope
| {
539 // Is this a regular argument?
540 if arg_index
> 0 || mir
.upvar_decls
.is_empty() {
541 // The Rust ABI passes indirect variables using a pointer and a manual copy, so we
542 // need to insert a deref here, but the C ABI uses a pointer and a copy using the
543 // byval attribute, for which LLVM does the deref itself, so we must not add it.
544 // Starting with D31439 in LLVM 5, it *always* does the deref itself.
545 let mut variable_access
= VariableAccess
::DirectVariable
{
548 if unsafe { llvm::LLVMRustVersionMajor() < 5 }
{
549 if let PassMode
::Indirect(ref attrs
) = arg
.mode
{
550 if !attrs
.contains(ArgAttribute
::ByVal
) {
551 variable_access
= VariableAccess
::IndirectVariable
{
553 address_operations
: &deref_op
,
562 arg_decl
.name
.unwrap_or(keywords
::Invalid
.name()),
566 VariableKind
::ArgumentVariable(arg_index
+ 1),
572 // Or is it the closure environment?
573 let (closure_layout
, env_ref
) = match arg
.layout
.ty
.sty
{
574 ty
::TyRef(_
, mt
) | ty
::TyRawPtr(mt
) => (bx
.cx
.layout_of(mt
.ty
), true),
575 _
=> (arg
.layout
, false)
578 let upvar_tys
= match closure_layout
.ty
.sty
{
579 ty
::TyClosure(def_id
, substs
) |
580 ty
::TyGenerator(def_id
, substs
, _
) => substs
.upvar_tys(def_id
, tcx
),
581 _
=> bug
!("upvar_decls with non-closure arg0 type `{}`", closure_layout
.ty
)
584 // Store the pointer to closure data in an alloca for debuginfo
585 // because that's what the llvm.dbg.declare intrinsic expects.
587 // FIXME(eddyb) this shouldn't be necessary but SROA seems to
588 // mishandle DW_OP_plus not preceded by DW_OP_deref, i.e. it
589 // doesn't actually strip the offset when splitting the closure
590 // environment into its components so it ends up out of bounds.
591 let env_ptr
= if !env_ref
{
592 let scratch
= PlaceRef
::alloca(bx
,
593 bx
.cx
.layout_of(tcx
.mk_mut_ptr(arg
.layout
.ty
)),
594 "__debuginfo_env_ptr");
595 bx
.store(place
.llval
, scratch
.llval
, scratch
.align
);
601 for (i
, (decl
, ty
)) in mir
.upvar_decls
.iter().zip(upvar_tys
).enumerate() {
602 let byte_offset_of_var_in_env
= closure_layout
.fields
.offset(i
).bytes();
605 [llvm
::LLVMRustDIBuilderCreateOpDeref(),
606 llvm
::LLVMRustDIBuilderCreateOpPlusUconst(),
607 byte_offset_of_var_in_env
as i64,
608 llvm
::LLVMRustDIBuilderCreateOpDeref()]
611 // The environment and the capture can each be indirect.
613 // FIXME(eddyb) see above why we have to keep
614 // a pointer in an alloca for debuginfo atm.
615 let mut ops
= if env_ref
|| true { &ops[..] }
else { &ops[1..] }
;
617 let ty
= if let (true, &ty
::TyRef(_
, mt
)) = (decl
.by_ref
, &ty
.sty
) {
620 ops
= &ops
[..ops
.len() - 1];
624 let variable_access
= VariableAccess
::IndirectVariable
{
626 address_operations
: &ops
635 VariableKind
::CapturedVariable
,
640 LocalRef
::Place(place
)