]> git.lizzy.rs Git - rust.git/commitdiff
Make spreading use `Option<Local>`
authorJonas Schievink <jonasschievink@gmail.com>
Mon, 26 Sep 2016 20:44:01 +0000 (22:44 +0200)
committerJonas Schievink <jonasschievink@gmail.com>
Mon, 26 Sep 2016 20:44:01 +0000 (22:44 +0200)
src/librustc/mir/repr.rs
src/librustc_mir/build/mod.rs
src/librustc_trans/mir/mod.rs

index 1c8f1dc1525f4685c71bef9e80423864ca6f1901..128d0d21da597c72c9e6d882a862ee5cb42767be 100644 (file)
@@ -95,11 +95,11 @@ pub struct Mir<'tcx> {
     /// the first argument is either the closure or a reference to it.
     pub upvar_decls: Vec<UpvarDecl>,
 
-    /// A boolean indicating whether the last argument (which must be a tuple)
-    /// is passed as its individual components at the LLVM level.
+    /// Mark an argument local (which must be a tuple) as getting passed as
+    /// its individual components at the LLVM level.
     ///
     /// This is used for the "rust-call" ABI.
-    pub spread_last_arg: bool,
+    pub spread_arg: Option<Local>,
 
     /// A span representing this MIR, for error reporting
     pub span: Span,
@@ -134,7 +134,7 @@ pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
             local_decls: local_decls,
             arg_count: arg_count,
             upvar_decls: upvar_decls,
-            spread_last_arg: false,
+            spread_arg: None,
             span: span,
             cache: Cache::new()
         }
index 4f531c9a2f88787f7df8d8fff2713ddcff542e7f..353aaaa45e18bed2d9f9bc9c9794ac37404edf55 100644 (file)
@@ -187,11 +187,11 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
     }));
     assert_eq!(block, builder.return_block());
 
-    let mut spread_last_arg = false;
+    let mut spread_arg = None;
     match tcx.node_id_to_type(fn_id).sty {
         ty::TyFnDef(_, _, f) if f.abi == Abi::RustCall => {
             // RustCall pseudo-ABI untuples the last argument.
-            spread_last_arg = true;
+            spread_arg = Some(Local::new(arguments.len()));
         }
         _ => {}
     }
@@ -221,7 +221,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
     });
 
     let (mut mir, aux) = builder.finish(upvar_decls, return_ty);
-    mir.spread_last_arg = spread_last_arg;
+    mir.spread_arg = spread_arg;
     (mir, aux)
 }
 
index 699900dc4cbac8d99eaa0785def660af038edd84..2bd258059ad25a4a0b56fd96234c3fa647accbe2 100644 (file)
@@ -359,57 +359,60 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
     mir.arg_iter().enumerate().map(|(arg_index, local)| {
         let arg_decl = &mir.local_decls[local];
         let arg_ty = bcx.monomorphize(&arg_decl.ty);
-        if mir.spread_last_arg && arg_index == mir.arg_count - 1 {
-            // This argument (e.g. the last argument in the "rust-call" ABI)
-            // is a tuple that was spread at the ABI level and now we have
-            // to reconstruct it into a tuple local variable, from multiple
-            // individual LLVM function arguments.
-
-            let tupled_arg_tys = match arg_ty.sty {
-                ty::TyTuple(ref tys) => tys,
-                _ => bug!("spread argument isn't a tuple?!")
-            };
 
-            let lltuplety = type_of::type_of(bcx.ccx(), arg_ty);
-            let lltemp = bcx.with_block(|bcx| {
-                base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index))
-            });
-            for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
-                let dst = bcx.struct_gep(lltemp, i);
-                let arg = &fcx.fn_ty.args[idx];
-                idx += 1;
-                if common::type_is_fat_ptr(tcx, tupled_arg_ty) {
-                    // We pass fat pointers as two words, but inside the tuple
-                    // they are the two sub-fields of a single aggregate field.
-                    let meta = &fcx.fn_ty.args[idx];
+        if let Some(spread_local) = mir.spread_arg {
+            if local == spread_local {
+                // This argument (e.g. the last argument in the "rust-call" ABI)
+                // is a tuple that was spread at the ABI level and now we have
+                // to reconstruct it into a tuple local variable, from multiple
+                // individual LLVM function arguments.
+
+                let tupled_arg_tys = match arg_ty.sty {
+                    ty::TyTuple(ref tys) => tys,
+                    _ => bug!("spread argument isn't a tuple?!")
+                };
+
+                let lltuplety = type_of::type_of(bcx.ccx(), arg_ty);
+                let lltemp = bcx.with_block(|bcx| {
+                    base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index))
+                });
+                for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
+                    let dst = bcx.struct_gep(lltemp, i);
+                    let arg = &fcx.fn_ty.args[idx];
                     idx += 1;
-                    arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, dst));
-                    meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, dst));
-                } else {
-                    arg.store_fn_arg(bcx, &mut llarg_idx, dst);
-                }
+                    if common::type_is_fat_ptr(tcx, tupled_arg_ty) {
+                        // We pass fat pointers as two words, but inside the tuple
+                        // they are the two sub-fields of a single aggregate field.
+                        let meta = &fcx.fn_ty.args[idx];
+                        idx += 1;
+                        arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, dst));
+                        meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, dst));
+                    } else {
+                        arg.store_fn_arg(bcx, &mut llarg_idx, dst);
+                    }
 
-                bcx.with_block(|bcx| arg_scope.map(|scope| {
-                    let byte_offset_of_var_in_tuple =
-                        machine::llelement_offset(bcx.ccx(), lltuplety, i);
-
-                    let ops = unsafe {
-                        [llvm::LLVMRustDIBuilderCreateOpDeref(),
-                         llvm::LLVMRustDIBuilderCreateOpPlus(),
-                         byte_offset_of_var_in_tuple as i64]
-                    };
-
-                    let variable_access = VariableAccess::IndirectVariable {
-                        alloca: lltemp,
-                        address_operations: &ops
-                    };
-                    declare_local(bcx, keywords::Invalid.name(),
-                                  tupled_arg_ty, scope, variable_access,
-                                  VariableKind::ArgumentVariable(arg_index + i + 1),
-                                  bcx.fcx().span.unwrap_or(DUMMY_SP));
-                }));
+                    bcx.with_block(|bcx| arg_scope.map(|scope| {
+                        let byte_offset_of_var_in_tuple =
+                            machine::llelement_offset(bcx.ccx(), lltuplety, i);
+
+                        let ops = unsafe {
+                            [llvm::LLVMRustDIBuilderCreateOpDeref(),
+                             llvm::LLVMRustDIBuilderCreateOpPlus(),
+                             byte_offset_of_var_in_tuple as i64]
+                        };
+
+                        let variable_access = VariableAccess::IndirectVariable {
+                            alloca: lltemp,
+                            address_operations: &ops
+                        };
+                        declare_local(bcx, keywords::Invalid.name(),
+                                      tupled_arg_ty, scope, variable_access,
+                                      VariableKind::ArgumentVariable(arg_index + i + 1),
+                                      bcx.fcx().span.unwrap_or(DUMMY_SP));
+                    }));
+                }
+                return LocalRef::Lvalue(LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty)));
             }
-            return LocalRef::Lvalue(LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty)));
         }
 
         let arg = &fcx.fn_ty.args[idx];