auto merge of #9109 : thestinger/rust/function, r=alexcrichton
This commit is contained in:
commit
38d4f48f0a
@ -174,6 +174,7 @@ impl<'self> Drop for StatRecorder<'self> {
|
||||
}
|
||||
}
|
||||
|
||||
// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
|
||||
pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
|
||||
let llfn: ValueRef = do name.with_c_str |buf| {
|
||||
unsafe {
|
||||
@ -185,18 +186,12 @@ pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type)
|
||||
return llfn;
|
||||
}
|
||||
|
||||
// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
|
||||
pub fn decl_cdecl_fn(llmod: ModuleRef, name: &str, ty: Type) -> ValueRef {
|
||||
return decl_fn(llmod, name, lib::llvm::CCallConv, ty);
|
||||
}
|
||||
|
||||
// Only use this if you are going to actually define the function. It's
|
||||
// not valid to simply declare a function as internal.
|
||||
pub fn decl_internal_cdecl_fn(llmod: ModuleRef, name: &str, ty: Type) -> ValueRef {
|
||||
let llfn = decl_cdecl_fn(llmod, name, ty);
|
||||
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
|
||||
return llfn;
|
||||
}
|
||||
|
||||
// only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
|
||||
pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef, name: &str,
|
||||
cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
|
||||
match externs.find_equiv(&name) {
|
||||
@ -205,7 +200,73 @@ pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef, name: &str,
|
||||
}
|
||||
let f = decl_fn(llmod, name, cc, ty);
|
||||
externs.insert(name.to_owned(), f);
|
||||
return f;
|
||||
f
|
||||
}
|
||||
|
||||
pub fn get_extern_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t,
|
||||
name: &str) -> ValueRef {
|
||||
match ccx.externs.find_equiv(&name) {
|
||||
Some(n) => return *n,
|
||||
None => ()
|
||||
}
|
||||
let f = decl_rust_fn(ccx, inputs, output, name);
|
||||
ccx.externs.insert(name.to_owned(), f);
|
||||
f
|
||||
}
|
||||
|
||||
pub fn decl_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t,
|
||||
name: &str) -> ValueRef {
|
||||
let llfty = type_of_rust_fn(ccx, inputs, output);
|
||||
let llfn = decl_cdecl_fn(ccx.llmod, name, llfty);
|
||||
|
||||
match ty::get(output).sty {
|
||||
// `~` pointer return values never alias because ownership is transferred
|
||||
ty::ty_uniq(*) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) => {
|
||||
unsafe {
|
||||
llvm::LLVMAddReturnAttribute(llfn, lib::llvm::NoAliasAttribute as c_uint);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
let uses_outptr = type_of::return_uses_outptr(ccx.tcx, output);
|
||||
let offset = if uses_outptr { 2 } else { 1 };
|
||||
|
||||
for (i, &arg_ty) in inputs.iter().enumerate() {
|
||||
let llarg = unsafe { llvm::LLVMGetParam(llfn, (offset + i) as c_uint) };
|
||||
match ty::get(arg_ty).sty {
|
||||
// `~` pointer parameters never alias because ownership is transferred
|
||||
ty::ty_uniq(*) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) |
|
||||
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
|
||||
unsafe {
|
||||
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
// The out pointer will never alias with any other pointers, as the object only exists at a
|
||||
// language level after the call. It can also be tagged with SRet to indicate that it is
|
||||
// guaranteed to point to a usable block of memory for the type.
|
||||
if uses_outptr {
|
||||
unsafe {
|
||||
let outptr = llvm::LLVMGetParam(llfn, 0);
|
||||
llvm::LLVMAddAttribute(outptr, lib::llvm::StructRetAttribute as c_uint);
|
||||
llvm::LLVMAddAttribute(outptr, lib::llvm::NoAliasAttribute as c_uint);
|
||||
}
|
||||
}
|
||||
|
||||
llfn
|
||||
}
|
||||
|
||||
pub fn decl_internal_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t,
|
||||
name: &str) -> ValueRef {
|
||||
let llfn = decl_rust_fn(ccx, inputs, output, name);
|
||||
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
|
||||
llfn
|
||||
}
|
||||
|
||||
pub fn get_extern_const(externs: &mut ExternMap, llmod: ModuleRef,
|
||||
@ -809,33 +870,30 @@ pub fn null_env_ptr(ccx: &CrateContext) -> ValueRef {
|
||||
C_null(Type::opaque_box(ccx).ptr_to())
|
||||
}
|
||||
|
||||
pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t)
|
||||
-> ValueRef {
|
||||
pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t) -> ValueRef {
|
||||
let name = csearch::get_symbol(ccx.sess.cstore, did);
|
||||
match ty::get(t).sty {
|
||||
ty::ty_bare_fn(ref fn_ty) => {
|
||||
// Currently llvm_calling_convention triggers unimpl/bug on
|
||||
// Rust/RustIntrinsic, so those two are handled specially here.
|
||||
let cconv = match fn_ty.abis.for_arch(ccx.sess.targ_cfg.arch) {
|
||||
Some(Rust) | Some(RustIntrinsic) => lib::llvm::CCallConv,
|
||||
match fn_ty.abis.for_arch(ccx.sess.targ_cfg.arch) {
|
||||
Some(Rust) | Some(RustIntrinsic) => {
|
||||
get_extern_rust_fn(ccx, fn_ty.sig.inputs, fn_ty.sig.output, name)
|
||||
}
|
||||
Some(*) | None => {
|
||||
let c = foreign::llvm_calling_convention(ccx, fn_ty.abis);
|
||||
c.unwrap_or(lib::llvm::CCallConv)
|
||||
let cconv = c.unwrap_or(lib::llvm::CCallConv);
|
||||
let llty = type_of_fn_from_ty(ccx, t);
|
||||
get_extern_fn(&mut ccx.externs, ccx.llmod, name, cconv, llty)
|
||||
}
|
||||
};
|
||||
let llty = type_of_fn_from_ty(ccx, t);
|
||||
return get_extern_fn(&mut ccx.externs, ccx.llmod, name, cconv, llty);
|
||||
}
|
||||
}
|
||||
ty::ty_closure(_) => {
|
||||
let llty = type_of_fn_from_ty(ccx, t);
|
||||
return get_extern_fn(&mut ccx.externs, ccx.llmod, name,
|
||||
lib::llvm::CCallConv, llty);
|
||||
ty::ty_closure(ref f) => {
|
||||
get_extern_rust_fn(ccx, f.sig.inputs, f.sig.output, name)
|
||||
}
|
||||
_ => {
|
||||
let llty = type_of(ccx, t);
|
||||
return get_extern_const(&mut ccx.externs, ccx.llmod, name, llty);
|
||||
get_extern_const(&mut ccx.externs, ccx.llmod, name, llty)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn invoke(bcx: @mut Block, llfn: ValueRef, llargs: ~[ValueRef],
|
||||
@ -868,7 +926,8 @@ pub fn invoke(bcx: @mut Block, llfn: ValueRef, llargs: ~[ValueRef],
|
||||
llfn,
|
||||
llargs,
|
||||
normal_bcx.llbb,
|
||||
get_landing_pad(bcx));
|
||||
get_landing_pad(bcx),
|
||||
attributes);
|
||||
return (llresult, normal_bcx);
|
||||
} else {
|
||||
unsafe {
|
||||
@ -1707,8 +1766,7 @@ pub fn new_fn_ctxt(ccx: @mut CrateContext,
|
||||
// field of the fn_ctxt with
|
||||
pub fn create_llargs_for_fn_args(cx: @mut FunctionContext,
|
||||
self_arg: self_arg,
|
||||
args: &[ast::arg],
|
||||
arg_tys: &[ty::t])
|
||||
args: &[ast::arg])
|
||||
-> ~[ValueRef] {
|
||||
let _icx = push_ctxt("create_llargs_for_fn_args");
|
||||
|
||||
@ -1726,23 +1784,7 @@ pub fn create_llargs_for_fn_args(cx: @mut FunctionContext,
|
||||
// Return an array containing the ValueRefs that we get from
|
||||
// llvm::LLVMGetParam for each argument.
|
||||
do vec::from_fn(args.len()) |i| {
|
||||
let arg_n = cx.arg_pos(i);
|
||||
let arg_ty = arg_tys[i];
|
||||
let llarg = unsafe {llvm::LLVMGetParam(cx.llfn, arg_n as c_uint) };
|
||||
|
||||
match ty::get(arg_ty).sty {
|
||||
// `~` pointer parameters never alias because ownership is transferred
|
||||
ty::ty_uniq(*) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) |
|
||||
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
|
||||
unsafe {
|
||||
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
llarg
|
||||
unsafe { llvm::LLVMGetParam(cx.llfn, cx.arg_pos(i) as c_uint) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1896,8 +1938,7 @@ pub fn trans_closure(ccx: @mut CrateContext,
|
||||
|
||||
// Set up arguments to the function.
|
||||
let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
|
||||
let raw_llargs = create_llargs_for_fn_args(fcx, self_arg,
|
||||
decl.inputs, arg_tys);
|
||||
let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs);
|
||||
|
||||
// Set the fixed stack segment flag if necessary.
|
||||
if attr::contains_name(attributes, "fixed_stack_segment") {
|
||||
@ -1961,18 +2002,6 @@ pub fn trans_fn(ccx: @mut CrateContext,
|
||||
param_substs.repr(ccx.tcx));
|
||||
let _icx = push_ctxt("trans_fn");
|
||||
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id));
|
||||
|
||||
match ty::get(output_type).sty {
|
||||
// `~` pointer return values never alias because ownership is transferred
|
||||
ty::ty_uniq(*) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) => {
|
||||
unsafe {
|
||||
llvm::LLVMAddReturnAttribute(llfndecl, lib::llvm::NoAliasAttribute as c_uint);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
trans_closure(ccx,
|
||||
path.clone(),
|
||||
decl,
|
||||
@ -2120,7 +2149,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
|
||||
|
||||
let arg_tys = ty::ty_fn_args(ctor_ty);
|
||||
|
||||
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args, arg_tys);
|
||||
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
|
||||
|
||||
let bcx = fcx.entry_bcx.unwrap();
|
||||
|
||||
@ -2298,10 +2327,28 @@ pub fn register_fn(ccx: @mut CrateContext,
|
||||
node_id: ast::NodeId,
|
||||
node_type: ty::t)
|
||||
-> ValueRef {
|
||||
let llfty = type_of_fn_from_ty(ccx, node_type);
|
||||
register_fn_llvmty(ccx, sp, sym, node_id, lib::llvm::CCallConv, llfty)
|
||||
let f = match ty::get(node_type).sty {
|
||||
ty::ty_bare_fn(ref f) => {
|
||||
assert!(f.abis.is_rust() || f.abis.is_intrinsic());
|
||||
f
|
||||
}
|
||||
_ => fail!("expected bare rust fn or an intrinsic")
|
||||
};
|
||||
|
||||
let llfn = decl_rust_fn(ccx, f.sig.inputs, f.sig.output, sym);
|
||||
ccx.item_symbols.insert(node_id, sym);
|
||||
|
||||
// FIXME #4404 android JNI hacks
|
||||
let is_entry = is_entry_fn(&ccx.sess, node_id) && (!*ccx.sess.building_library ||
|
||||
(*ccx.sess.building_library &&
|
||||
ccx.sess.targ_cfg.os == session::OsAndroid));
|
||||
if is_entry {
|
||||
create_entry_wrapper(ccx, sp, llfn);
|
||||
}
|
||||
llfn
|
||||
}
|
||||
|
||||
// only use this for foreign function ABIs and glue, use `register_fn` for Rust functions
|
||||
pub fn register_fn_llvmty(ccx: @mut CrateContext,
|
||||
sp: Span,
|
||||
sym: ~str,
|
||||
|
@ -109,7 +109,8 @@ pub fn Invoke(cx: @mut Block,
|
||||
Fn: ValueRef,
|
||||
Args: &[ValueRef],
|
||||
Then: BasicBlockRef,
|
||||
Catch: BasicBlockRef)
|
||||
Catch: BasicBlockRef,
|
||||
attributes: &[(uint, lib::llvm::Attribute)])
|
||||
-> ValueRef {
|
||||
if cx.unreachable {
|
||||
return C_null(Type::i8());
|
||||
@ -119,15 +120,7 @@ pub fn Invoke(cx: @mut Block,
|
||||
debug!("Invoke(%s with arguments (%s))",
|
||||
cx.val_to_str(Fn),
|
||||
Args.map(|a| cx.val_to_str(*a)).connect(", "));
|
||||
B(cx).invoke(Fn, Args, Then, Catch)
|
||||
}
|
||||
|
||||
pub fn FastInvoke(cx: @mut Block, Fn: ValueRef, Args: &[ValueRef],
|
||||
Then: BasicBlockRef, Catch: BasicBlockRef) {
|
||||
if cx.unreachable { return; }
|
||||
check_not_terminated(cx);
|
||||
terminate(cx, "FastInvoke");
|
||||
B(cx).fast_invoke(Fn, Args, Then, Catch);
|
||||
B(cx).invoke(Fn, Args, Then, Catch, attributes)
|
||||
}
|
||||
|
||||
pub fn Unreachable(cx: @mut Block) {
|
||||
|
@ -154,30 +154,25 @@ impl Builder {
|
||||
llfn: ValueRef,
|
||||
args: &[ValueRef],
|
||||
then: BasicBlockRef,
|
||||
catch: BasicBlockRef)
|
||||
catch: BasicBlockRef,
|
||||
attributes: &[(uint, lib::llvm::Attribute)])
|
||||
-> ValueRef {
|
||||
self.count_insn("invoke");
|
||||
unsafe {
|
||||
llvm::LLVMBuildInvoke(self.llbuilder,
|
||||
llfn,
|
||||
vec::raw::to_ptr(args),
|
||||
args.len() as c_uint,
|
||||
then,
|
||||
catch,
|
||||
noname())
|
||||
let v = llvm::LLVMBuildInvoke(self.llbuilder,
|
||||
llfn,
|
||||
vec::raw::to_ptr(args),
|
||||
args.len() as c_uint,
|
||||
then,
|
||||
catch,
|
||||
noname());
|
||||
for &(idx, attr) in attributes.iter() {
|
||||
llvm::LLVMAddInstrAttribute(v, idx as c_uint, attr as c_uint);
|
||||
}
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fast_invoke(&self,
|
||||
llfn: ValueRef,
|
||||
args: &[ValueRef],
|
||||
then: BasicBlockRef,
|
||||
catch: BasicBlockRef) {
|
||||
self.count_insn("fastinvoke");
|
||||
let v = self.invoke(llfn, args, then, catch);
|
||||
lib::llvm::SetInstructionCallConv(v, lib::llvm::FastCallConv);
|
||||
}
|
||||
|
||||
pub fn unreachable(&self) {
|
||||
self.count_insn("unreachable");
|
||||
unsafe {
|
||||
|
@ -20,7 +20,7 @@ use std::vec;
|
||||
|
||||
use back::abi;
|
||||
use driver::session;
|
||||
use lib::llvm::ValueRef;
|
||||
use lib::llvm::{ValueRef, NoAliasAttribute, StructRetAttribute};
|
||||
use lib::llvm::llvm;
|
||||
use metadata::csearch;
|
||||
use middle::trans::base;
|
||||
@ -706,8 +706,26 @@ pub fn trans_call_inner(in_cx: @mut Block,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// A function pointer is called without the declaration available, so we have to apply
|
||||
// any attributes with ABI implications directly to the call instruction. Right now, the
|
||||
// only attribute we need to worry about is `sret`.
|
||||
let mut attrs = ~[];
|
||||
if type_of::return_uses_outptr(in_cx.tcx(), ret_ty) {
|
||||
attrs.push((1, StructRetAttribute));
|
||||
}
|
||||
|
||||
// The `noalias` attribute on the return value is useful to a function ptr caller.
|
||||
match ty::get(ret_ty).sty {
|
||||
// `~` pointer return values never alias because ownership is transferred
|
||||
ty::ty_uniq(*) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) => {
|
||||
attrs.push((0, NoAliasAttribute));
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
// Invoke the actual rust fn and update bcx/llresult.
|
||||
let (llret, b) = base::invoke(bcx, llfn, llargs, []);
|
||||
let (llret, b) = base::invoke(bcx, llfn, llargs, attrs);
|
||||
bcx = b;
|
||||
llresult = llret;
|
||||
|
||||
|
@ -381,8 +381,10 @@ pub fn trans_expr_fn(bcx: @mut Block,
|
||||
|
||||
let ccx = bcx.ccx();
|
||||
let fty = node_id_type(bcx, outer_id);
|
||||
|
||||
let llfnty = type_of_fn_from_ty(ccx, fty);
|
||||
let f = match ty::get(fty).sty {
|
||||
ty::ty_closure(ref f) => f,
|
||||
_ => fail!("expected closure")
|
||||
};
|
||||
|
||||
let sub_path = vec::append_one(bcx.fcx.path.clone(),
|
||||
path_name(special_idents::anon));
|
||||
@ -390,7 +392,7 @@ pub fn trans_expr_fn(bcx: @mut Block,
|
||||
let s = mangle_internal_name_by_path_and_seq(ccx,
|
||||
sub_path.clone(),
|
||||
"expr_fn");
|
||||
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
|
||||
let llfn = decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, s);
|
||||
|
||||
// set an inline hint for all closures
|
||||
set_inline_hint(llfn);
|
||||
|
@ -21,7 +21,6 @@ use middle::trans::cabi;
|
||||
use middle::trans::build::*;
|
||||
use middle::trans::builder::noname;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::llrepr::LlvmRepr;
|
||||
use middle::trans::type_of::*;
|
||||
use middle::trans::type_of;
|
||||
use middle::ty;
|
||||
@ -265,6 +264,9 @@ pub fn trans_native_call(bcx: @mut Block,
|
||||
}
|
||||
};
|
||||
|
||||
// A function pointer is called without the declaration available, so we have to apply
|
||||
// any attributes with ABI implications directly to the call instruction. Right now, the
|
||||
// only attribute we need to worry about is `sret`.
|
||||
let attrs;
|
||||
if fn_type.sret {
|
||||
attrs = &[(1, StructRetAttribute)];
|
||||
@ -406,13 +408,12 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @mut CrateContext,
|
||||
special_idents::clownshoe_abi
|
||||
)));
|
||||
|
||||
// Compute the LLVM type that the function would have if it
|
||||
// were just a normal Rust function. This will be the type of
|
||||
// the wrappee fn.
|
||||
let llty = match ty::get(t).sty {
|
||||
// Compute the type that the function would have if it were just a
|
||||
// normal Rust function. This will be the type of the wrappee fn.
|
||||
let f = match ty::get(t).sty {
|
||||
ty::ty_bare_fn(ref f) => {
|
||||
assert!(!f.abis.is_rust() && !f.abis.is_intrinsic());
|
||||
type_of_rust_fn(ccx, f.sig.inputs, f.sig.output)
|
||||
f
|
||||
}
|
||||
_ => {
|
||||
ccx.sess.bug(fmt!("build_rust_fn: extern fn %s has ty %s, \
|
||||
@ -422,13 +423,12 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @mut CrateContext,
|
||||
}
|
||||
};
|
||||
|
||||
debug!("build_rust_fn: path=%s id=%? t=%s llty=%s",
|
||||
debug!("build_rust_fn: path=%s id=%? t=%s",
|
||||
path.repr(tcx),
|
||||
id,
|
||||
t.repr(tcx),
|
||||
llty.llrepr(ccx));
|
||||
t.repr(tcx));
|
||||
|
||||
let llfndecl = base::decl_internal_cdecl_fn(ccx.llmod, ps, llty);
|
||||
let llfndecl = base::decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, ps);
|
||||
base::trans_fn(ccx,
|
||||
(*path).clone(),
|
||||
decl,
|
||||
@ -500,7 +500,7 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @mut CrateContext,
|
||||
// Rust expects to use an outpointer. If the foreign fn
|
||||
// also uses an outpointer, we can reuse it, but the types
|
||||
// may vary, so cast first to the Rust type. If the
|
||||
// foriegn fn does NOT use an outpointer, we will have to
|
||||
// foreign fn does NOT use an outpointer, we will have to
|
||||
// alloca some scratch space on the stack.
|
||||
match foreign_outptr {
|
||||
Some(llforeign_outptr) => {
|
||||
|
@ -14,14 +14,13 @@ use driver::session;
|
||||
use lib::llvm::ValueRef;
|
||||
use middle::trans::base::{set_llvm_fn_attrs, set_inline_hint};
|
||||
use middle::trans::base::{trans_enum_variant,push_ctxt};
|
||||
use middle::trans::base::{trans_fn, decl_internal_cdecl_fn};
|
||||
use middle::trans::base::{trans_fn, decl_internal_rust_fn};
|
||||
use middle::trans::base::{get_item_val, no_self};
|
||||
use middle::trans::base;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::datum;
|
||||
use middle::trans::machine;
|
||||
use middle::trans::meth;
|
||||
use middle::trans::type_of::type_of_fn_from_ty;
|
||||
use middle::trans::type_of;
|
||||
use middle::trans::type_use;
|
||||
use middle::trans::intrinsic;
|
||||
@ -177,7 +176,14 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||
ty::subst_tps(ccx.tcx, substs, None, llitem_ty)
|
||||
}
|
||||
};
|
||||
let llfty = type_of_fn_from_ty(ccx, mono_ty);
|
||||
|
||||
let f = match ty::get(mono_ty).sty {
|
||||
ty::ty_bare_fn(ref f) => {
|
||||
assert!(f.abis.is_rust() || f.abis.is_intrinsic());
|
||||
f
|
||||
}
|
||||
_ => fail!("expected bare rust fn or an intrinsic")
|
||||
};
|
||||
|
||||
ccx.stats.n_monos += 1;
|
||||
|
||||
@ -200,7 +206,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||
debug!("monomorphize_fn mangled to %s", s);
|
||||
|
||||
let mk_lldecl = || {
|
||||
let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, llfty);
|
||||
let lldecl = decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, s);
|
||||
ccx.monomorphized.insert(hash_id, lldecl);
|
||||
lldecl
|
||||
};
|
||||
|
@ -293,8 +293,7 @@ impl Reflector {
|
||||
sub_path,
|
||||
"get_disr");
|
||||
|
||||
let llfty = type_of_rust_fn(ccx, [opaqueptrty], ty::mk_int());
|
||||
let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty);
|
||||
let llfdecl = decl_internal_rust_fn(ccx, [opaqueptrty], ty::mk_int(), sym);
|
||||
let fcx = new_fn_ctxt(ccx,
|
||||
~[],
|
||||
llfdecl,
|
||||
|
Loading…
x
Reference in New Issue
Block a user