1010
1111use hair:: cx:: Cx ;
1212use rustc:: middle:: region:: { CodeExtent , CodeExtentData } ;
13- use rustc:: ty:: { self , FnOutput , Ty } ;
13+ use rustc:: ty:: { self , Ty } ;
1414use rustc:: mir:: repr:: * ;
1515use rustc_data_structures:: fnv:: FnvHashMap ;
1616use rustc:: hir;
1717use rustc:: hir:: pat_util:: pat_is_binding;
1818use std:: ops:: { Index , IndexMut } ;
19+ use syntax:: abi:: Abi ;
1920use syntax:: ast;
2021use syntax:: codemap:: Span ;
2122use syntax:: parse:: token:: keywords;
@@ -159,74 +160,51 @@ macro_rules! unpack {
159160///////////////////////////////////////////////////////////////////////////
160161/// the main entry point for building MIR for a function
161162
162- pub fn construct < ' a , ' tcx > ( hir : Cx < ' a , ' tcx > ,
163- span : Span ,
164- fn_id : ast:: NodeId ,
165- body_id : ast:: NodeId ,
166- implicit_arguments : Vec < Ty < ' tcx > > ,
167- explicit_arguments : Vec < ( Ty < ' tcx > , & ' tcx hir:: Pat ) > ,
168- return_ty : FnOutput < ' tcx > ,
169- ast_block : & ' tcx hir:: Block )
170- -> ( Mir < ' tcx > , ScopeAuxiliaryVec ) {
163+ pub fn construct_fn < ' a , ' tcx , A > ( hir : Cx < ' a , ' tcx > ,
164+ fn_id : ast:: NodeId ,
165+ arguments : A ,
166+ return_ty : ty:: FnOutput < ' tcx > ,
167+ ast_block : & ' tcx hir:: Block )
168+ -> ( Mir < ' tcx > , ScopeAuxiliaryVec )
169+ where A : Iterator < Item =( Ty < ' tcx > , Option < & ' tcx hir:: Pat > ) >
170+ {
171171 let tcx = hir. tcx ( ) ;
172- let cfg = CFG { basic_blocks : vec ! [ ] } ;
173-
174- let mut builder = Builder {
175- hir : hir,
176- cfg : cfg,
177- fn_span : span,
178- scopes : vec ! [ ] ,
179- scope_datas : vec ! [ ] ,
180- scope_auxiliary : ScopeAuxiliaryVec { vec : vec ! [ ] } ,
181- loop_scopes : vec ! [ ] ,
182- temp_decls : vec ! [ ] ,
183- var_decls : vec ! [ ] ,
184- var_indices : FnvHashMap ( ) ,
185- unit_temp : None ,
186- cached_resume_block : None ,
187- cached_return_block : None
188- } ;
189-
190- assert_eq ! ( builder. cfg. start_new_block( ) , START_BLOCK ) ;
172+ let span = tcx. map . span ( fn_id) ;
173+ let mut builder = Builder :: new ( hir, span) ;
191174
192- let mut arg_decls = None ; // assigned to `Some` in closures below
175+ let body_id = ast_block . id ;
193176 let call_site_extent =
194177 tcx. region_maps . lookup_code_extent (
195178 CodeExtentData :: CallSiteScope { fn_id : fn_id, body_id : body_id } ) ;
196- let _ = builder. in_scope ( call_site_extent, START_BLOCK , |builder, call_site_scope_id| {
197- let mut block = START_BLOCK ;
198- let arg_extent =
199- tcx. region_maps . lookup_code_extent (
200- CodeExtentData :: ParameterScope { fn_id : fn_id, body_id : body_id } ) ;
201- unpack ! ( block = builder. in_scope( arg_extent, block, |builder, arg_scope_id| {
202- arg_decls = Some ( unpack!( block = builder. args_and_body( block,
203- return_ty,
204- implicit_arguments,
205- explicit_arguments,
206- arg_scope_id,
207- ast_block) ) ) ;
208- block. unit( )
179+ let arg_extent =
180+ tcx. region_maps . lookup_code_extent (
181+ CodeExtentData :: ParameterScope { fn_id : fn_id, body_id : body_id } ) ;
182+ let mut block = START_BLOCK ;
183+ let mut arg_decls = unpack ! ( block = builder. in_scope( call_site_extent, block,
184+ |builder, call_site_scope_id| {
185+ let arg_decls = unpack!( block = builder. in_scope( arg_extent, block,
186+ |builder, arg_scope_id| {
187+ builder. args_and_body( block, return_ty, arguments, arg_scope_id, ast_block)
209188 } ) ) ;
210189
211190 let return_block = builder. return_block( ) ;
212191 builder. cfg. terminate( block, call_site_scope_id, span,
213192 TerminatorKind :: Goto { target: return_block } ) ;
214193 builder. cfg. terminate( return_block, call_site_scope_id, span,
215194 TerminatorKind :: Return ) ;
216- return_block. unit ( )
217- } ) ;
218-
219- assert ! (
220- builder. cfg. basic_blocks
221- . iter( )
222- . enumerate( )
223- . all( |( index, block) | {
224- if block. terminator. is_none( ) {
225- bug!( "no terminator on block {:?} in fn {:?}" ,
226- index, fn_id)
227- }
228- true
229- } ) ) ;
195+ return_block. and( arg_decls)
196+ } ) ) ;
197+ assert_eq ! ( block, builder. return_block( ) ) ;
198+
199+ match tcx. node_id_to_type ( fn_id) . sty {
200+ ty:: TyFnDef ( _, _, f) if f. abi == Abi :: RustCall => {
201+ // RustCall pseudo-ABI untuples the last argument.
202+ if let Some ( arg_decl) = arg_decls. last_mut ( ) {
203+ arg_decl. spread = true ;
204+ }
205+ }
206+ _ => { }
207+ }
230208
231209 // Gather the upvars of a closure, if any.
232210 let upvar_decls: Vec < _ > = tcx. with_freevars ( fn_id, |freevars| {
@@ -251,72 +229,98 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
251229 } ) . collect ( )
252230 } ) ;
253231
254- (
255- Mir {
256- basic_blocks : builder. cfg . basic_blocks ,
257- scopes : builder. scope_datas ,
258- var_decls : builder. var_decls ,
259- arg_decls : arg_decls. take ( ) . expect ( "args never built?" ) ,
260- temp_decls : builder. temp_decls ,
261- upvar_decls : upvar_decls,
262- return_ty : return_ty,
263- span : span
264- } ,
265- builder. scope_auxiliary ,
266- )
232+ builder. finish ( upvar_decls, arg_decls, return_ty)
267233}
268234
269235impl < ' a , ' tcx > Builder < ' a , ' tcx > {
270- fn args_and_body ( & mut self ,
271- mut block : BasicBlock ,
272- return_ty : FnOutput < ' tcx > ,
273- implicit_arguments : Vec < Ty < ' tcx > > ,
274- explicit_arguments : Vec < ( Ty < ' tcx > , & ' tcx hir:: Pat ) > ,
275- argument_scope_id : ScopeId ,
276- ast_block : & ' tcx hir:: Block )
277- -> BlockAnd < Vec < ArgDecl < ' tcx > > >
236+ fn new ( hir : Cx < ' a , ' tcx > , span : Span ) -> Builder < ' a , ' tcx > {
237+ let mut builder = Builder {
238+ hir : hir,
239+ cfg : CFG { basic_blocks : vec ! [ ] } ,
240+ fn_span : span,
241+ scopes : vec ! [ ] ,
242+ scope_datas : vec ! [ ] ,
243+ scope_auxiliary : ScopeAuxiliaryVec { vec : vec ! [ ] } ,
244+ loop_scopes : vec ! [ ] ,
245+ temp_decls : vec ! [ ] ,
246+ var_decls : vec ! [ ] ,
247+ var_indices : FnvHashMap ( ) ,
248+ unit_temp : None ,
249+ cached_resume_block : None ,
250+ cached_return_block : None
251+ } ;
252+
253+ assert_eq ! ( builder. cfg. start_new_block( ) , START_BLOCK ) ;
254+
255+ builder
256+ }
257+
258+ fn finish ( self ,
259+ upvar_decls : Vec < UpvarDecl > ,
260+ arg_decls : Vec < ArgDecl < ' tcx > > ,
261+ return_ty : ty:: FnOutput < ' tcx > )
262+ -> ( Mir < ' tcx > , ScopeAuxiliaryVec ) {
263+ for ( index, block) in self . cfg . basic_blocks . iter ( ) . enumerate ( ) {
264+ if block. terminator . is_none ( ) {
265+ span_bug ! ( self . fn_span, "no terminator on block {:?}" , index) ;
266+ }
267+ }
268+
269+ ( Mir {
270+ basic_blocks : self . cfg . basic_blocks ,
271+ scopes : self . scope_datas ,
272+ var_decls : self . var_decls ,
273+ arg_decls : arg_decls,
274+ temp_decls : self . temp_decls ,
275+ upvar_decls : upvar_decls,
276+ return_ty : return_ty,
277+ span : self . fn_span
278+ } , self . scope_auxiliary )
279+ }
280+
281+ fn args_and_body < A > ( & mut self ,
282+ mut block : BasicBlock ,
283+ return_ty : ty:: FnOutput < ' tcx > ,
284+ arguments : A ,
285+ argument_scope_id : ScopeId ,
286+ ast_block : & ' tcx hir:: Block )
287+ -> BlockAnd < Vec < ArgDecl < ' tcx > > >
288+ where A : Iterator < Item =( Ty < ' tcx > , Option < & ' tcx hir:: Pat > ) >
278289 {
279290 // to start, translate the argument patterns and collect the argument types.
280- let implicits = implicit_arguments. into_iter ( ) . map ( |ty| ( ty, None ) ) ;
281- let explicits = explicit_arguments. into_iter ( ) . map ( |( ty, pat) | ( ty, Some ( pat) ) ) ;
282- let arg_decls =
283- implicits
284- . chain ( explicits)
285- . enumerate ( )
286- . map ( |( index, ( ty, pattern) ) | {
287- let lvalue = Lvalue :: Arg ( index as u32 ) ;
288- if let Some ( pattern) = pattern {
289- let pattern = self . hir . irrefutable_pat ( pattern) ;
290- unpack ! ( block = self . lvalue_into_pattern( block,
291- argument_scope_id,
292- pattern,
293- & lvalue) ) ;
294- }
291+ let arg_decls = arguments. enumerate ( ) . map ( |( index, ( ty, pattern) ) | {
292+ let lvalue = Lvalue :: Arg ( index as u32 ) ;
293+ if let Some ( pattern) = pattern {
294+ let pattern = self . hir . irrefutable_pat ( pattern) ;
295+ unpack ! ( block = self . lvalue_into_pattern( block,
296+ argument_scope_id,
297+ pattern,
298+ & lvalue) ) ;
299+ }
295300
296- // Make sure we drop (parts of) the argument even when not matched on.
297- let argument_extent = self . scope_auxiliary [ argument_scope_id] . extent ;
298- self . schedule_drop ( pattern. as_ref ( ) . map_or ( ast_block. span , |pat| pat. span ) ,
299- argument_extent, & lvalue, ty) ;
300-
301- let mut name = keywords:: Invalid . name ( ) ;
302- if let Some ( pat) = pattern {
303- if let hir:: PatKind :: Ident ( _, ref ident, _) = pat. node {
304- if pat_is_binding ( & self . hir . tcx ( ) . def_map . borrow ( ) , pat) {
305- name = ident. node . name ;
306- }
301+ // Make sure we drop (parts of) the argument even when not matched on.
302+ let argument_extent = self . scope_auxiliary [ argument_scope_id] . extent ;
303+ self . schedule_drop ( pattern. as_ref ( ) . map_or ( ast_block. span , |pat| pat. span ) ,
304+ argument_extent, & lvalue, ty) ;
305+
306+ let mut name = keywords:: Invalid . name ( ) ;
307+ if let Some ( pat) = pattern {
308+ if let hir:: PatKind :: Ident ( _, ref ident, _) = pat. node {
309+ if pat_is_binding ( & self . hir . tcx ( ) . def_map . borrow ( ) , pat) {
310+ name = ident. node . name ;
307311 }
308312 }
313+ }
309314
310- ArgDecl {
311- ty : ty,
312- spread : false ,
313- debug_name : name
314- }
315- } )
316- . collect ( ) ;
315+ ArgDecl {
316+ ty : ty,
317+ spread : false ,
318+ debug_name : name
319+ }
320+ } ) . collect ( ) ;
317321
318322 // FIXME(#32959): temporary hack for the issue at hand
319- let return_is_unit = if let FnOutput :: FnConverging ( t) = return_ty {
323+ let return_is_unit = if let ty :: FnConverging ( t) = return_ty {
320324 t. is_nil ( )
321325 } else {
322326 false
0 commit comments