Skip to content

Commit ca29a70

Browse files
committed
---
yaml --- r: 273270 b: refs/heads/beta c: b63a5ee h: refs/heads/master
1 parent 7e2cc40 commit ca29a70

File tree

5 files changed

+55
-11
lines changed

5 files changed

+55
-11
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ refs/tags/0.9: 36870b185fc5f5486636d4515f0e22677493f225
2323
refs/tags/0.10: ac33f2b15782272ae348dbd7b14b8257b2148b5a
2424
refs/tags/0.11.0: e1247cb1d0d681be034adb4b558b5a0c0d5720f9
2525
refs/tags/0.12.0: f0c419429ef30723ceaf6b42f9b5a2aeb5d2e2d1
26-
refs/heads/beta: 92e485874e668fdc21855e0a288f526161576070
26+
refs/heads/beta: b63a5eed6e8a2379aabe4eb0328ad238c057c60f
2727
refs/tags/1.0.0-alpha: e42bd6d93a1d3433c486200587f8f9e12590a4d7
2828
refs/heads/tmp: e06d2ad9fcd5027bcaac5b08fc9aa39a49d0ecd3
2929
refs/tags/1.0.0-alpha.2: 4c705f6bc559886632d3871b04f58aab093bfa2f

branches/beta/src/librustc/mir/repr.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ pub struct TempDecl<'tcx> {
178178
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
179179
pub struct ArgDecl<'tcx> {
180180
pub ty: Ty<'tcx>,
181+
182+
/// If true, this argument is a tuple after monomorphization,
183+
/// and has to be collected from multiple actual arguments.
184+
pub spread: bool
181185
}
182186

183187
///////////////////////////////////////////////////////////////////////////

branches/beta/src/librustc_mir/build/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
149149
pattern,
150150
&lvalue));
151151
}
152-
ArgDecl { ty: ty }
152+
ArgDecl { ty: ty, spread: false }
153153
})
154154
.collect();
155155

branches/beta/src/librustc_mir/mir_map.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use rustc::util::common::ErrorReported;
3333
use rustc::util::nodemap::NodeMap;
3434
use rustc_front::hir;
3535
use rustc_front::intravisit::{self, Visitor};
36+
use syntax::abi::Abi;
3637
use syntax::ast;
3738
use syntax::attr::AttrMetaMethods;
3839
use syntax::codemap::Span;
@@ -181,13 +182,20 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
181182
let parameter_scope =
182183
cx.tcx().region_maps.lookup_code_extent(
183184
CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id });
184-
Ok(build::construct(cx,
185-
span,
186-
implicit_arg_tys,
187-
arguments,
188-
parameter_scope,
189-
fn_sig.output,
190-
body))
185+
let mut mir = build::construct(cx, span, implicit_arg_tys, arguments,
186+
parameter_scope, fn_sig.output, body);
187+
188+
match cx.tcx().node_id_to_type(fn_id).sty {
189+
ty::TyFnDef(_, _, f) if f.abi == Abi::RustCall => {
190+
// RustCall pseudo-ABI untuples the last argument.
191+
if let Some(arg_decl) = mir.arg_decls.last_mut() {
192+
arg_decl.spread = true;
193+
}
194+
}
195+
_ => {}
196+
}
197+
198+
Ok(mir)
191199
}
192200

193201
fn closure_self_ty<'a, 'tcx>(tcx: &TyCtxt<'tcx>,

branches/beta/src/librustc_trans/trans/mir/mod.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,47 @@ pub fn trans_mir<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
147147
fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
148148
mir: &mir::Mir<'tcx>)
149149
-> Vec<LvalueRef<'tcx>> {
150-
// FIXME tupled_args? I think I'd rather that mapping is done in MIR land though
151150
let fcx = bcx.fcx();
152151
let tcx = bcx.tcx();
153152
let mut idx = 0;
154153
let mut llarg_idx = fcx.fn_ty.ret.is_indirect() as usize;
155154
mir.arg_decls.iter().enumerate().map(|(arg_index, arg_decl)| {
155+
let arg_ty = bcx.monomorphize(&arg_decl.ty);
156+
if arg_decl.spread {
157+
// This argument (e.g. the last argument in the "rust-call" ABI)
158+
// is a tuple that was spread at the ABI level and now we have
159+
// to reconstruct it into a tuple local variable, from multiple
160+
// individual LLVM function arguments.
161+
162+
let tupled_arg_tys = match arg_ty.sty {
163+
ty::TyTuple(ref tys) => tys,
164+
_ => unreachable!("spread argument isn't a tuple?!")
165+
};
166+
167+
let llval = bcx.with_block(|bcx| {
168+
let lltemp = base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index));
169+
for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
170+
let dst = build::StructGEP(bcx, lltemp, i);
171+
let arg = &fcx.fn_ty.args[idx];
172+
idx += 1;
173+
if common::type_is_fat_ptr(tcx, tupled_arg_ty) {
174+
// We pass fat pointers as two words, but inside the tuple
175+
// they are the two sub-fields of a single aggregate field.
176+
let meta = &fcx.fn_ty.args[idx];
177+
idx += 1;
178+
arg.store_fn_arg(bcx, &mut llarg_idx, expr::get_dataptr(bcx, dst));
179+
meta.store_fn_arg(bcx, &mut llarg_idx, expr::get_meta(bcx, dst));
180+
} else {
181+
arg.store_fn_arg(bcx, &mut llarg_idx, dst);
182+
}
183+
}
184+
lltemp
185+
});
186+
return LvalueRef::new_sized(llval, LvalueTy::from_ty(arg_ty));
187+
}
188+
156189
let arg = &fcx.fn_ty.args[idx];
157190
idx += 1;
158-
let arg_ty = bcx.monomorphize(&arg_decl.ty);
159191
let llval = if arg.is_indirect() {
160192
// Don't copy an indirect argument to an alloca, the caller
161193
// already put it in a temporary alloca and gave it up, unless

0 commit comments

Comments
 (0)