]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/shim.rs
move Instance to rustc and use it in the collector
[rust.git] / src / librustc_mir / shim.rs
1 // Copyright 2016 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.
4 //
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.
10
11 use rustc::hir;
12 use rustc::infer;
13 use rustc::mir::*;
14 use rustc::mir::transform::MirSource;
15 use rustc::ty;
16 use rustc::ty::maps::Providers;
17
18 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
19
20 use syntax::ast;
21 use syntax_pos::Span;
22
23 use std::cell::RefCell;
24 use std::iter;
25
26 pub fn provide(providers: &mut Providers) {
27     providers.mir_shims = make_shim;
28 }
29
30 fn make_shim<'a, 'tcx>(_tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
31                        instance: ty::InstanceDef<'tcx>)
32                        -> &'tcx RefCell<Mir<'tcx>>
33 {
34     match instance {
35         ty::InstanceDef::Item(..) =>
36             bug!("item {:?} passed to make_shim", instance),
37         ty::InstanceDef::FnPtrShim(..) => unimplemented!()
38     }
39 }
40
41 fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>)
42     -> IndexVec<Local, LocalDecl<'tcx>>
43 {
44     iter::once(LocalDecl {
45         mutability: Mutability::Mut,
46         ty: sig.output(),
47         name: None,
48         source_info: None
49     }).chain(sig.inputs().iter().map(|ity| LocalDecl {
50         mutability: Mutability::Not,
51         ty: *ity,
52         name: None,
53         source_info: None,
54     })).collect()
55 }
56
57 pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
58                                       ctor_id: ast::NodeId,
59                                       fields: &[hir::StructField],
60                                       span: Span)
61                                       -> (Mir<'tcx>, MirSource)
62 {
63     let tcx = infcx.tcx;
64     let def_id = tcx.hir.local_def_id(ctor_id);
65     let sig = match tcx.item_type(def_id).sty {
66         ty::TyFnDef(_, _, fty) => tcx.no_late_bound_regions(&fty)
67             .expect("LBR in ADT constructor signature"),
68         _ => bug!("unexpected type for ctor {:?}", def_id)
69     };
70     let sig = tcx.erase_regions(&sig);
71
72     let (adt_def, substs) = match sig.output().sty {
73         ty::TyAdt(adt_def, substs) => (adt_def, substs),
74         _ => bug!("unexpected type for ADT ctor {:?}", sig.output())
75     };
76
77     debug!("build_ctor: def_id={:?} sig={:?} fields={:?}", def_id, sig, fields);
78
79     let local_decls = local_decls_for_sig(&sig);
80
81     let source_info = SourceInfo {
82         span: span,
83         scope: ARGUMENT_VISIBILITY_SCOPE
84     };
85
86     let variant_no = if adt_def.is_enum() {
87         adt_def.variant_index_with_id(def_id)
88     } else {
89         0
90     };
91
92     // return = ADT(arg0, arg1, ...); return
93     let start_block = BasicBlockData {
94         statements: vec![Statement {
95             source_info: source_info,
96             kind: StatementKind::Assign(
97                 Lvalue::Local(RETURN_POINTER),
98                 Rvalue::Aggregate(
99                     AggregateKind::Adt(adt_def, variant_no, substs, None),
100                     (1..sig.inputs().len()+1).map(|i| {
101                         Operand::Consume(Lvalue::Local(Local::new(i)))
102                     }).collect()
103                 )
104             )
105         }],
106         terminator: Some(Terminator {
107             source_info: source_info,
108             kind: TerminatorKind::Return,
109         }),
110         is_cleanup: false
111     };
112
113     let mir = Mir::new(
114         IndexVec::from_elem_n(start_block, 1),
115         IndexVec::from_elem_n(
116             VisibilityScopeData { span: span, parent_scope: None }, 1
117         ),
118         IndexVec::new(),
119         sig.output(),
120         local_decls,
121         sig.inputs().len(),
122         vec![],
123         span
124     );
125     (mir, MirSource::Fn(ctor_id))
126 }