Skip to content

Commit 3b0c318

Browse files
Make spreading use Option<Local>
1 parent 894c083 commit 3b0c318

File tree

3 files changed

+57
-54
lines changed

3 files changed

+57
-54
lines changed

src/librustc/mir/repr.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,11 @@ pub struct Mir<'tcx> {
9595
/// the first argument is either the closure or a reference to it.
9696
pub upvar_decls: Vec<UpvarDecl>,
9797

98-
/// A boolean indicating whether the last argument (which must be a tuple)
99-
/// is passed as its individual components at the LLVM level.
98+
/// Mark an argument local (which must be a tuple) as getting passed as
99+
/// its individual components at the LLVM level.
100100
///
101101
/// This is used for the "rust-call" ABI.
102-
pub spread_last_arg: bool,
102+
pub spread_arg: Option<Local>,
103103

104104
/// A span representing this MIR, for error reporting
105105
pub span: Span,
@@ -134,7 +134,7 @@ impl<'tcx> Mir<'tcx> {
134134
local_decls: local_decls,
135135
arg_count: arg_count,
136136
upvar_decls: upvar_decls,
137-
spread_last_arg: false,
137+
spread_arg: None,
138138
span: span,
139139
cache: Cache::new()
140140
}

src/librustc_mir/build/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,11 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
187187
}));
188188
assert_eq!(block, builder.return_block());
189189

190-
let mut spread_last_arg = false;
190+
let mut spread_arg = None;
191191
match tcx.node_id_to_type(fn_id).sty {
192192
ty::TyFnDef(_, _, f) if f.abi == Abi::RustCall => {
193193
// RustCall pseudo-ABI untuples the last argument.
194-
spread_last_arg = true;
194+
spread_arg = Some(Local::new(arguments.len()));
195195
}
196196
_ => {}
197197
}
@@ -221,7 +221,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
221221
});
222222

223223
let (mut mir, aux) = builder.finish(upvar_decls, return_ty);
224-
mir.spread_last_arg = spread_last_arg;
224+
mir.spread_arg = spread_arg;
225225
(mir, aux)
226226
}
227227

src/librustc_trans/mir/mod.rs

Lines changed: 50 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -359,57 +359,60 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
359359
mir.arg_iter().enumerate().map(|(arg_index, local)| {
360360
let arg_decl = &mir.local_decls[local];
361361
let arg_ty = bcx.monomorphize(&arg_decl.ty);
362-
if mir.spread_last_arg && arg_index == mir.arg_count - 1 {
363-
// This argument (e.g. the last argument in the "rust-call" ABI)
364-
// is a tuple that was spread at the ABI level and now we have
365-
// to reconstruct it into a tuple local variable, from multiple
366-
// individual LLVM function arguments.
367-
368-
let tupled_arg_tys = match arg_ty.sty {
369-
ty::TyTuple(ref tys) => tys,
370-
_ => bug!("spread argument isn't a tuple?!")
371-
};
372362

373-
let lltuplety = type_of::type_of(bcx.ccx(), arg_ty);
374-
let lltemp = bcx.with_block(|bcx| {
375-
base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index))
376-
});
377-
for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
378-
let dst = bcx.struct_gep(lltemp, i);
379-
let arg = &fcx.fn_ty.args[idx];
380-
idx += 1;
381-
if common::type_is_fat_ptr(tcx, tupled_arg_ty) {
382-
// We pass fat pointers as two words, but inside the tuple
383-
// they are the two sub-fields of a single aggregate field.
384-
let meta = &fcx.fn_ty.args[idx];
363+
if let Some(spread_local) = mir.spread_arg {
364+
if local == spread_local {
365+
// This argument (e.g. the last argument in the "rust-call" ABI)
366+
// is a tuple that was spread at the ABI level and now we have
367+
// to reconstruct it into a tuple local variable, from multiple
368+
// individual LLVM function arguments.
369+
370+
let tupled_arg_tys = match arg_ty.sty {
371+
ty::TyTuple(ref tys) => tys,
372+
_ => bug!("spread argument isn't a tuple?!")
373+
};
374+
375+
let lltuplety = type_of::type_of(bcx.ccx(), arg_ty);
376+
let lltemp = bcx.with_block(|bcx| {
377+
base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index))
378+
});
379+
for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
380+
let dst = bcx.struct_gep(lltemp, i);
381+
let arg = &fcx.fn_ty.args[idx];
385382
idx += 1;
386-
arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, dst));
387-
meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, dst));
388-
} else {
389-
arg.store_fn_arg(bcx, &mut llarg_idx, dst);
390-
}
383+
if common::type_is_fat_ptr(tcx, tupled_arg_ty) {
384+
// We pass fat pointers as two words, but inside the tuple
385+
// they are the two sub-fields of a single aggregate field.
386+
let meta = &fcx.fn_ty.args[idx];
387+
idx += 1;
388+
arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, dst));
389+
meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, dst));
390+
} else {
391+
arg.store_fn_arg(bcx, &mut llarg_idx, dst);
392+
}
391393

392-
bcx.with_block(|bcx| arg_scope.map(|scope| {
393-
let byte_offset_of_var_in_tuple =
394-
machine::llelement_offset(bcx.ccx(), lltuplety, i);
395-
396-
let ops = unsafe {
397-
[llvm::LLVMRustDIBuilderCreateOpDeref(),
398-
llvm::LLVMRustDIBuilderCreateOpPlus(),
399-
byte_offset_of_var_in_tuple as i64]
400-
};
401-
402-
let variable_access = VariableAccess::IndirectVariable {
403-
alloca: lltemp,
404-
address_operations: &ops
405-
};
406-
declare_local(bcx, keywords::Invalid.name(),
407-
tupled_arg_ty, scope, variable_access,
408-
VariableKind::ArgumentVariable(arg_index + i + 1),
409-
bcx.fcx().span.unwrap_or(DUMMY_SP));
410-
}));
394+
bcx.with_block(|bcx| arg_scope.map(|scope| {
395+
let byte_offset_of_var_in_tuple =
396+
machine::llelement_offset(bcx.ccx(), lltuplety, i);
397+
398+
let ops = unsafe {
399+
[llvm::LLVMRustDIBuilderCreateOpDeref(),
400+
llvm::LLVMRustDIBuilderCreateOpPlus(),
401+
byte_offset_of_var_in_tuple as i64]
402+
};
403+
404+
let variable_access = VariableAccess::IndirectVariable {
405+
alloca: lltemp,
406+
address_operations: &ops
407+
};
408+
declare_local(bcx, keywords::Invalid.name(),
409+
tupled_arg_ty, scope, variable_access,
410+
VariableKind::ArgumentVariable(arg_index + i + 1),
411+
bcx.fcx().span.unwrap_or(DUMMY_SP));
412+
}));
413+
}
414+
return LocalRef::Lvalue(LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty)));
411415
}
412-
return LocalRef::Lvalue(LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty)));
413416
}
414417

415418
let arg = &fcx.fn_ty.args[idx];

0 commit comments

Comments
 (0)