diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index b1dbd80e54a..c4c1a56b6ef 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -346,6 +346,7 @@ type _mod = rec(vec[@view_item] view_items, tag native_abi { native_abi_rust; native_abi_cdecl; + native_abi_llvm; } type native_mod = rec(str native_name, diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs index 6a864053dbb..f1003cb646a 100644 --- a/src/comp/front/creader.rs +++ b/src/comp/front/creader.rs @@ -162,6 +162,7 @@ impure fn parse_sty(@pstate st, str_def sd) -> ty.sty { alt (next(st) as char) { case ('r') {abi = ast.native_abi_rust;} case ('c') {abi = ast.native_abi_cdecl;} + case ('l') {abi = ast.native_abi_llvm;} } auto func = parse_ty_fn(st, sd); ret ty.ty_native_fn(abi,func._0,func._1); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index c8130b0b965..4a9f37f09e2 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1964,6 +1964,8 @@ impure fn parse_item_native_mod(parser p) -> @ast.item { if (_str.eq(t, "cdecl")) { } else if (_str.eq(t, "rust")) { abi = ast.native_abi_rust; + } else if (_str.eq(t, "llvm")) { + abi = ast.native_abi_llvm; } else { p.err("unsupported abi: " + t); fail; diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs index 9313bcb7e19..44c62a47548 100644 --- a/src/comp/middle/metadata.rs +++ b/src/comp/middle/metadata.rs @@ -108,6 +108,7 @@ fn sty_str(ty.sty st, def_str ds) -> str { alt (abi) { case (ast.native_abi_rust) {abistr = "r";} case (ast.native_abi_cdecl) {abistr = "c";} + case (ast.native_abi_llvm) {abistr = "l";} } ret "N" + abistr + ty_fn_str(args, out, ds); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9eb208597e0..8216ab7a873 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5884,18 +5884,44 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, case (ast.native_abi_cdecl) { pass_task = false; } - } - auto args = ty.ty_fn_args(fn_type); - for (ty.arg arg in args) { - auto llarg = llvm.LLVMGetParam(fcx.llfn, arg_n); - check (llarg as int != 0); - call_args += vec(bcx.build.PointerCast(llarg, T_i32())); - arg_n += 1u; + case (ast.native_abi_llvm) { + pass_task = false; + // We handle this case below. + } + } + + auto r; + auto rptr; + auto args = ty.ty_fn_args(fn_type); + if (abi == ast.native_abi_llvm) { + let vec[ValueRef] call_args = vec(); + let vec[TypeRef] call_arg_tys = vec(); + auto i = 0u; + while (i < _vec.len[ty.arg](args)) { + auto call_arg = llvm.LLVMGetParam(fcx.llfn, i + 3u); + call_args += vec(call_arg); + call_arg_tys += vec(val_ty(call_arg)); + i += 1u; + } + auto llnativefnty = T_fn(call_arg_tys, + type_of(cx, ty.ty_fn_ret(fn_type))); + auto llnativefn = get_extern_fn(cx.externs, cx.llmod, name, + lib.llvm.LLVMCCallConv, llnativefnty); + r = bcx.build.Call(llnativefn, call_args); + rptr = fcx.llretptr; + } else { + for (ty.arg arg in args) { + auto llarg = llvm.LLVMGetParam(fcx.llfn, arg_n); + check (llarg as int != 0); + call_args += vec(bcx.build.PointerCast(llarg, T_i32())); + arg_n += 1u; + } + + r = trans_native(bcx.build, cx.glues, lltaskptr, cx.externs, + cx.tn, cx.llmod, name, pass_task, call_args); + rptr = bcx.build.BitCast(fcx.llretptr, T_ptr(T_i32())); } - auto r = trans_native(bcx.build, cx.glues, lltaskptr, cx.externs, cx.tn, - cx.llmod, name, pass_task, call_args); - auto rptr = bcx.build.BitCast(fcx.llretptr, T_ptr(T_i32())); bcx.build.Store(r, rptr); bcx.build.RetVoid(); }