Skip to content

librustc: Mark unboxed closure calls and definitions with appropriate llvm return/argument attributes. #16656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 22, 2014
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 29 additions & 11 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2240,26 +2240,44 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
ty::ty_bare_fn(ref f) => (f.sig.clone(), f.abi, false),
ty::ty_unboxed_closure(closure_did, _) => {
let unboxed_closures = ccx.tcx.unboxed_closures.borrow();
let function_type = unboxed_closures.get(&closure_did)
.closure_type
.clone();
let ref function_type = unboxed_closures.get(&closure_did)
.closure_type;

(function_type.sig.clone(), RustCall, true)
}
_ => fail!("expected closure or function.")
_ => ccx.sess().bug("expected closure or function.")
};


// Since index 0 is the return value of the llvm func, we start
// at either 1 or 2 depending on whether there's an env slot or not
let mut first_arg_offset = if has_env { 2 } else { 1 };
let mut attrs = llvm::AttrBuilder::new();
let ret_ty = fn_sig.output;

// These have an odd calling convention, so we skip them for now.
//
// FIXME(pcwalton): We don't have to skip them; just untuple the result.
if abi == RustCall {
return attrs;
}
// These have an odd calling convention, so we need to manually
// unpack the input ty's
let input_tys = match ty::get(fn_ty).sty {
ty::ty_unboxed_closure(_, _) => {
assert!(abi == RustCall);

match ty::get(fn_sig.inputs[0]).sty {
ty::ty_nil => Vec::new(),
ty::ty_tup(ref inputs) => inputs.clone(),
_ => ccx.sess().bug("expected tuple'd inputs")
}
},
ty::ty_bare_fn(_) if abi == RustCall => {
let inputs = vec![fn_sig.inputs[0]];

match ty::get(fn_sig.inputs[1]).sty {
ty::ty_nil => inputs,
ty::ty_tup(ref t_in) => inputs.append(t_in.as_slice()),
_ => ccx.sess().bug("expected tuple'd inputs")
}
}
_ => fn_sig.inputs.clone()
};

// A function pointer is called without the declaration
// available, so we have to apply any attributes with ABI
Expand Down Expand Up @@ -2315,7 +2333,7 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
}
}

for (idx, &t) in fn_sig.inputs.iter().enumerate().map(|(i, v)| (i + first_arg_offset, v)) {
for (idx, &t) in input_tys.iter().enumerate().map(|(i, v)| (i + first_arg_offset, v)) {
match ty::get(t).sty {
// this needs to be first to prevent fat pointers from falling through
_ if !type_is_immediate(ccx, t) => {
Expand Down