From 3b0c318a5f4a5ef8c027326f7566b5f3ce7380d6 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 26 Sep 2016 22:44:01 +0200 Subject: [PATCH] Make spreading use `Option` --- src/librustc/mir/repr.rs | 8 +-- src/librustc_mir/build/mod.rs | 6 +-- src/librustc_trans/mir/mod.rs | 97 ++++++++++++++++++----------------- 3 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 1c8f1dc1525..128d0d21da5 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -95,11 +95,11 @@ pub struct Mir<'tcx> { /// the first argument is either the closure or a reference to it. pub upvar_decls: Vec, - /// 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, /// A span representing this MIR, for error reporting pub span: Span, @@ -134,7 +134,7 @@ pub fn new(basic_blocks: IndexVec>, local_decls: local_decls, arg_count: arg_count, upvar_decls: upvar_decls, - spread_last_arg: false, + spread_arg: None, span: span, cache: Cache::new() } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 4f531c9a2f8..353aaaa45e1 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -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) } diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 699900dc4cb..2bd258059ad 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -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]; -- 2.44.0