Make spreading use Option<Local>
This commit is contained in:
parent
894c083c40
commit
3b0c318a5f
@ -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 @@ impl<'tcx> Mir<'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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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?!")
|
||||
};
|
||||
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 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];
|
||||
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];
|
||||
|
Loading…
x
Reference in New Issue
Block a user