Implement built-in native modules as an alternative to intrinsics
Issue #1981
This commit is contained in:
parent
73a0c17d77
commit
ea2e379e4f
@ -240,6 +240,9 @@ fn native_abi(attrs: [ast::attribute]) -> either<str, ast::native_abi> {
|
||||
option::some("rust-intrinsic") {
|
||||
either::right(ast::native_abi_rust_intrinsic)
|
||||
}
|
||||
option::some("rust-builtin") {
|
||||
either::right(ast::native_abi_rust_builtin)
|
||||
}
|
||||
option::some("cdecl") {
|
||||
either::right(ast::native_abi_cdecl)
|
||||
}
|
||||
|
@ -374,6 +374,9 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item {
|
||||
ast::ii_method(d, m) {
|
||||
ast::ii_method(d, fld.fold_method(m))
|
||||
}
|
||||
ast::ii_native(i) {
|
||||
ast::ii_native(fld.fold_native_item(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -398,6 +401,9 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item)
|
||||
ast::ii_method(d, m) {
|
||||
ast::ii_method(xcx.tr_def_id(d), fld.fold_method(m))
|
||||
}
|
||||
ast::ii_native(i) {
|
||||
ast::ii_native(fld.fold_native_item(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -681,7 +681,12 @@ fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
encode_type(ecx, ebml_w, node_id_to_type(ecx.ccx.tcx, nitem.id));
|
||||
encode_symbol(ecx, ebml_w, nitem.id);
|
||||
if abi == native_abi_rust_builtin {
|
||||
astencode::encode_inlined_item(ecx, ebml_w, path,
|
||||
ii_native(nitem));
|
||||
} else {
|
||||
encode_symbol(ecx, ebml_w, nitem.id);
|
||||
}
|
||||
encode_path(ebml_w, path, ast_map::path_name(nitem.ident));
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +91,10 @@ fn map_decoded_item(sess: session, map: map, path: path, ii: inlined_item) {
|
||||
// add it to the table now:
|
||||
alt ii {
|
||||
ii_item(i) { /* fallthrough */ }
|
||||
ii_native(i) {
|
||||
cx.map.insert(i.id, node_native_item(i, native_abi_rust_builtin,
|
||||
@path));
|
||||
}
|
||||
ii_method(impl_did, m) {
|
||||
map_method(impl_did, @path, m, cx);
|
||||
}
|
||||
|
@ -123,7 +123,8 @@ fn check_ctypes(tcx: ty::ctxt, crate: @ast::crate) {
|
||||
|
||||
fn check_item(tcx: ty::ctxt, it: @ast::item) {
|
||||
alt it.node {
|
||||
ast::item_native_mod(nmod) {
|
||||
ast::item_native_mod(nmod) if attr::native_abi(it.attrs) !=
|
||||
either::right(ast::native_abi_rust_builtin) {
|
||||
for ni in nmod.items {
|
||||
alt ni.node {
|
||||
ast::native_item_fn(decl, tps) {
|
||||
|
@ -337,7 +337,7 @@ fn trans_malloc_boxed_raw(bcx: block, t: ty::t,
|
||||
let llty = type_of(ccx, box_ptr);
|
||||
|
||||
// Get the tydesc for the body:
|
||||
let {bcx, val: lltydesc} = get_tydesc(bcx, t, static_ti);
|
||||
let lltydesc = get_tydesc(ccx, t, static_ti);
|
||||
lazily_emit_all_tydesc_glue(ccx, static_ti);
|
||||
|
||||
// Allocate space:
|
||||
@ -358,18 +358,18 @@ fn trans_malloc_boxed(bcx: block, t: ty::t) ->
|
||||
|
||||
// Type descriptor and type glue stuff
|
||||
|
||||
fn get_tydesc_simple(bcx: block, t: ty::t) -> result {
|
||||
fn get_tydesc_simple(ccx: @crate_ctxt, t: ty::t) -> ValueRef {
|
||||
let mut ti = none;
|
||||
get_tydesc(bcx, t, ti)
|
||||
get_tydesc(ccx, t, ti)
|
||||
}
|
||||
|
||||
fn get_tydesc(cx: block, t: ty::t,
|
||||
&static_ti: option<@tydesc_info>) -> result {
|
||||
fn get_tydesc(ccx: @crate_ctxt, t: ty::t,
|
||||
&static_ti: option<@tydesc_info>) -> ValueRef {
|
||||
assert !ty::type_has_params(t);
|
||||
// Otherwise, generate a tydesc if necessary, and return it.
|
||||
let info = get_static_tydesc(cx.ccx(), t);
|
||||
let info = get_static_tydesc(ccx, t);
|
||||
static_ti = some(info);
|
||||
ret rslt(cx, info.tydesc);
|
||||
info.tydesc
|
||||
}
|
||||
|
||||
fn get_static_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info {
|
||||
@ -699,7 +699,7 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, substs: [ty::t])
|
||||
maybe_instantiate_inline(ccx, did)
|
||||
} else { did };
|
||||
assert did.crate == ast::local_crate;
|
||||
monomorphic_fn(ccx, did, substs, none).val
|
||||
monomorphic_fn(ccx, did, substs, none, none).val
|
||||
}
|
||||
|
||||
fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
|
||||
@ -1074,10 +1074,10 @@ fn call_tydesc_glue_full(cx: block, v: ValueRef, tydesc: ValueRef,
|
||||
fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: int) ->
|
||||
block {
|
||||
let _icx = cx.insn_ctxt("call_tydesc_glue");
|
||||
let mut ti: option<@tydesc_info> = none;
|
||||
let {bcx: bcx, val: td} = get_tydesc(cx, t, ti);
|
||||
call_tydesc_glue_full(bcx, v, td, field, ti);
|
||||
ret bcx;
|
||||
let mut ti = none;
|
||||
let td = get_tydesc(cx.ccx(), t, ti);
|
||||
call_tydesc_glue_full(cx, v, td, field, ti);
|
||||
ret cx;
|
||||
}
|
||||
|
||||
fn call_cmp_glue(cx: block, lhs: ValueRef, rhs: ValueRef, t: ty::t,
|
||||
@ -1096,11 +1096,9 @@ fn call_cmp_glue(cx: block, lhs: ValueRef, rhs: ValueRef, t: ty::t,
|
||||
|
||||
let llrawlhsptr = BitCast(bcx, lllhs, T_ptr(T_i8()));
|
||||
let llrawrhsptr = BitCast(bcx, llrhs, T_ptr(T_i8()));
|
||||
let r = get_tydesc_simple(bcx, t);
|
||||
let lltydesc = r.val;
|
||||
let bcx = r.bcx;
|
||||
let lltydescs = GEPi(bcx, lltydesc, [0, abi::tydesc_field_first_param]);
|
||||
let lltydescs = Load(bcx, lltydescs);
|
||||
let lltydesc = get_tydesc_simple(bcx.ccx(), t);
|
||||
let lltydescs =
|
||||
Load(bcx, GEPi(bcx, lltydesc, [0, abi::tydesc_field_first_param]));
|
||||
|
||||
let llfn = bcx.ccx().upcalls.cmp_type;
|
||||
|
||||
@ -1171,9 +1169,7 @@ fn call_memmove(cx: block, dst: ValueRef, src: ValueRef,
|
||||
session::arch_x86 | session::arch_arm { "llvm.memmove.p0i8.p0i8.i32" }
|
||||
session::arch_x86_64 { "llvm.memmove.p0i8.p0i8.i64" }
|
||||
};
|
||||
let i = ccx.intrinsics;
|
||||
assert (i.contains_key(key));
|
||||
let memmove = i.get(key);
|
||||
let memmove = ccx.intrinsics.get(key);
|
||||
let src_ptr = PointerCast(cx, src, T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(cx, dst, T_ptr(T_i8()));
|
||||
let size = IntCast(cx, n_bytes, ccx.int_type);
|
||||
@ -1911,7 +1907,8 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: [ty::t],
|
||||
}
|
||||
|
||||
fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
|
||||
vtables: option<typeck::vtable_res>)
|
||||
vtables: option<typeck::vtable_res>,
|
||||
ref_id: option<ast::node_id>)
|
||||
-> {val: ValueRef, must_cast: bool, intrinsic: bool} {
|
||||
let _icx = ccx.insn_ctxt("monomorphic_fn");
|
||||
let mut must_cast = false;
|
||||
@ -1952,6 +1949,8 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
|
||||
}
|
||||
ast_map::node_variant(v, _, pt) { (pt, v.node.name) }
|
||||
ast_map::node_method(m, _, pt) { (pt, m.ident) }
|
||||
ast_map::node_native_item(i, ast::native_abi_rust_builtin, pt)
|
||||
{ (pt, i.ident) }
|
||||
ast_map::node_native_item(_, abi, _) {
|
||||
// Natives don't have to be monomorphized.
|
||||
ret {val: get_item_val(ccx, fn_id.node),
|
||||
@ -1984,6 +1983,10 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
|
||||
ast_map::node_item(@{node: ast::item_res(d, _, body, d_id, _), _}, _) {
|
||||
trans_fn(ccx, pt, d, body, lldecl, no_self, psubsts, d_id, none);
|
||||
}
|
||||
ast_map::node_native_item(i, _, _) {
|
||||
native::trans_builtin(ccx, lldecl, i, pt, option::get(psubsts),
|
||||
ref_id);
|
||||
}
|
||||
ast_map::node_variant(v, enum_item, _) {
|
||||
let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
|
||||
let this_tv = option::get(vec::find(*tvs, {|tv|
|
||||
@ -2036,6 +2039,10 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
|
||||
trans_item(ccx, *item);
|
||||
local_def(item.id)
|
||||
}
|
||||
csearch::found(ast::ii_native(item)) {
|
||||
ccx.external.insert(fn_id, some(item.id));
|
||||
local_def(item.id)
|
||||
}
|
||||
csearch::found_parent(parent_id, ast::ii_item(item)) {
|
||||
ccx.external.insert(parent_id, some(item.id));
|
||||
let mut my_id = 0;
|
||||
@ -2088,11 +2095,9 @@ fn lval_intrinsic_fn(bcx: block, val: ValueRef, tys: [ty::t],
|
||||
let mut bcx = bcx;
|
||||
let ccx = bcx.ccx();
|
||||
let tds = vec::map(tys, {|t|
|
||||
let mut ti = none;
|
||||
let td_res = get_tydesc(bcx, t, ti);
|
||||
bcx = td_res.bcx;
|
||||
let mut ti = none, td = get_tydesc(bcx.ccx(), t, ti);
|
||||
lazily_emit_all_tydesc_glue(ccx, ti);
|
||||
td_res.val
|
||||
td
|
||||
});
|
||||
let llfty = type_of_fn_from_ty(ccx, node_id_type(bcx, id));
|
||||
let val = PointerCast(bcx, val, T_ptr(add_tydesc_params(
|
||||
@ -2124,7 +2129,7 @@ fn lval_static_fn_inner(bcx: block, fn_id: ast::def_id, id: ast::node_id,
|
||||
|
||||
if fn_id.crate == ast::local_crate && tys.len() > 0u {
|
||||
let mut {val, must_cast, intrinsic} =
|
||||
monomorphic_fn(ccx, fn_id, tys, vtables);
|
||||
monomorphic_fn(ccx, fn_id, tys, vtables, some(id));
|
||||
if intrinsic { ret lval_intrinsic_fn(bcx, val, tys, id); }
|
||||
if must_cast {
|
||||
val = PointerCast(bcx, val, T_ptr(type_of_fn_from_ty(
|
||||
@ -3318,7 +3323,7 @@ fn trans_log(lvl: @ast::expr, bcx: block, e: @ast::expr) -> block {
|
||||
with_scope(bcx, "log") {|bcx|
|
||||
let {bcx, val, _} = trans_temp_expr(bcx, e);
|
||||
let e_ty = expr_ty(bcx, e);
|
||||
let {bcx, val: tydesc} = get_tydesc_simple(bcx, e_ty);
|
||||
let tydesc = get_tydesc_simple(ccx, e_ty);
|
||||
// Call the polymorphic log function.
|
||||
let {bcx, val} = spill_if_immediate(bcx, val, e_ty);
|
||||
let val = PointerCast(bcx, val, T_ptr(T_i8()));
|
||||
|
@ -164,7 +164,7 @@ fn allocate_cbox(bcx: block,
|
||||
box: ValueRef,
|
||||
&ti: option<@tydesc_info>) -> block {
|
||||
let bound_tydesc = GEPi(bcx, box, [0, abi::box_field_tydesc]);
|
||||
let {bcx, val: td} = base::get_tydesc(bcx, cdata_ty, ti);
|
||||
let td = base::get_tydesc(bcx.ccx(), cdata_ty, ti);
|
||||
Store(bcx, td, bound_tydesc);
|
||||
bcx
|
||||
}
|
||||
|
@ -804,6 +804,10 @@ fn C_shape(ccx: @crate_ctxt, bytes: [u8]) -> ValueRef {
|
||||
ret llvm::LLVMConstPointerCast(llglobal, T_ptr(T_i8()));
|
||||
}
|
||||
|
||||
fn get_param(fndecl: ValueRef, param: uint) -> ValueRef {
|
||||
llvm::LLVMGetParam(fndecl, param as c_uint)
|
||||
}
|
||||
|
||||
// Used to identify cached monomorphized functions and vtables
|
||||
enum mono_param_id {
|
||||
mono_precise(ty::t, option<[mono_id]>),
|
||||
|
@ -251,7 +251,7 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: [ty::t],
|
||||
} else {
|
||||
let m_id = method_with_name(ccx, impl_id, im.ident);
|
||||
if has_tps {
|
||||
monomorphic_fn(ccx, m_id, substs, some(vtables)).val
|
||||
monomorphic_fn(ccx, m_id, substs, some(vtables), none).val
|
||||
} else if m_id.crate == ast::local_crate {
|
||||
get_item_val(ccx, m_id.node)
|
||||
} else {
|
||||
|
@ -6,16 +6,17 @@ import lib::llvm::{ llvm, TypeRef, ValueRef,
|
||||
ModuleRef, CallConv, Attribute,
|
||||
StructRetAttribute, ByValAttribute
|
||||
};
|
||||
import syntax::ast;
|
||||
import syntax::{ast, ast_util};
|
||||
import back::link;
|
||||
import common::*;
|
||||
import build::*;
|
||||
import base::*;
|
||||
import type_of::*;
|
||||
import std::map::hashmap;
|
||||
import util::ppaux::ty_to_str;
|
||||
|
||||
export link_name, trans_native_mod, register_crust_fn, trans_crust_fn,
|
||||
decl_native_fn;
|
||||
decl_native_fn, trans_builtin;
|
||||
|
||||
enum x86_64_reg_class {
|
||||
no_class,
|
||||
@ -384,7 +385,7 @@ fn decl_x86_64_fn(tys: x86_64_tys,
|
||||
vec::iteri(tys.attrs) {|i, a|
|
||||
alt a {
|
||||
option::some(attr) {
|
||||
let llarg = llvm::LLVMGetParam(llfn, i as c_uint);
|
||||
let llarg = get_param(llfn, i);
|
||||
llvm::LLVMAddAttribute(llarg, attr as c_uint);
|
||||
}
|
||||
_ {}
|
||||
@ -462,7 +463,7 @@ fn build_shim_fn_(ccx: @crate_ctxt,
|
||||
let fcx = new_fn_ctxt(ccx, [], llshimfn, none);
|
||||
let bcx = top_scope_block(fcx, none);
|
||||
let lltop = bcx.llbb;
|
||||
let llargbundle = llvm::LLVMGetParam(llshimfn, 0 as c_uint);
|
||||
let llargbundle = get_param(llshimfn, 0u);
|
||||
let llargvals = arg_builder(bcx, tys, llargbundle);
|
||||
|
||||
// Create the call itself and store the return value:
|
||||
@ -683,13 +684,11 @@ fn trans_native_mod(ccx: @crate_ctxt,
|
||||
let n = vec::len(tys.arg_tys);
|
||||
let implicit_args = first_real_arg; // ret + env
|
||||
while i < n {
|
||||
let llargval = llvm::LLVMGetParam(
|
||||
llwrapfn,
|
||||
(i + implicit_args) as c_uint);
|
||||
let llargval = get_param(llwrapfn, i + implicit_args);
|
||||
store_inbounds(bcx, llargval, llargbundle, [0, i as int]);
|
||||
i += 1u;
|
||||
}
|
||||
let llretptr = llvm::LLVMGetParam(llwrapfn, 0 as c_uint);
|
||||
let llretptr = get_param(llwrapfn, 0u);
|
||||
store_inbounds(bcx, llretptr, llargbundle, [0, n as int]);
|
||||
}
|
||||
|
||||
@ -704,15 +703,15 @@ fn trans_native_mod(ccx: @crate_ctxt,
|
||||
build_args, build_ret);
|
||||
}
|
||||
|
||||
let mut cc = lib::llvm::CCallConv;
|
||||
alt abi {
|
||||
let mut cc = alt abi {
|
||||
ast::native_abi_rust_intrinsic {
|
||||
for item in native_mod.items { get_item_val(ccx, item.id); }
|
||||
ret;
|
||||
}
|
||||
ast::native_abi_cdecl { cc = lib::llvm::CCallConv; }
|
||||
ast::native_abi_stdcall { cc = lib::llvm::X86StdcallCallConv; }
|
||||
}
|
||||
ast::native_abi_rust_builtin { ret; }
|
||||
ast::native_abi_cdecl { lib::llvm::CCallConv }
|
||||
ast::native_abi_stdcall { lib::llvm::X86StdcallCallConv }
|
||||
};
|
||||
|
||||
for native_item in native_mod.items {
|
||||
alt native_item.node {
|
||||
@ -727,6 +726,58 @@ fn trans_native_mod(ccx: @crate_ctxt,
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_builtin(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item,
|
||||
path: ast_map::path, substs: param_substs,
|
||||
ref_id: option<ast::node_id>) {
|
||||
let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id, none,
|
||||
some(substs), some(item.span));
|
||||
let bcx = top_scope_block(fcx, none), lltop = bcx.llbb;
|
||||
let tp_ty = substs.tys[0], lltp_ty = type_of::type_of(ccx, tp_ty);
|
||||
alt check item.ident {
|
||||
"size_of" {
|
||||
Store(bcx, C_uint(ccx, shape::llsize_of_real(ccx, lltp_ty)),
|
||||
fcx.llretptr);
|
||||
}
|
||||
"align_of" {
|
||||
Store(bcx, C_uint(ccx, shape::llalign_of_real(ccx, lltp_ty)),
|
||||
fcx.llretptr);
|
||||
}
|
||||
"get_tydesc" {
|
||||
let td = get_tydesc_simple(ccx, tp_ty);
|
||||
Store(bcx, PointerCast(bcx, td, T_ptr(T_nil())), fcx.llretptr);
|
||||
}
|
||||
"init" {
|
||||
if !ty::type_is_nil(tp_ty) {
|
||||
Store(bcx, C_null(lltp_ty), fcx.llretptr);
|
||||
}
|
||||
}
|
||||
"forget" {}
|
||||
"reinterpret_cast" {
|
||||
let llout_ty = type_of::type_of(ccx, substs.tys[1]);
|
||||
if shape::llsize_of_real(ccx, lltp_ty) !=
|
||||
shape::llsize_of_real(ccx, llout_ty) {
|
||||
let sp = alt check ccx.tcx.items.get(option::get(ref_id)) {
|
||||
ast_map::node_expr(e) { e.span }
|
||||
};
|
||||
ccx.sess.span_fatal(sp, "reinterpret_cast called on types \
|
||||
with different size: " +
|
||||
ty_to_str(ccx.tcx, tp_ty) + " to " +
|
||||
ty_to_str(ccx.tcx, substs.tys[1]));
|
||||
}
|
||||
if !ty::type_is_nil(substs.tys[1]) {
|
||||
let cast = PointerCast(bcx, get_param(decl, first_real_arg),
|
||||
T_ptr(llout_ty));
|
||||
Store(bcx, Load(bcx, cast), fcx.llretptr);
|
||||
}
|
||||
}
|
||||
"addr_of" {
|
||||
Store(bcx, get_param(decl, first_real_arg), fcx.llretptr);
|
||||
}
|
||||
}
|
||||
build_return(bcx);
|
||||
finish_fn(fcx, lltop);
|
||||
}
|
||||
|
||||
fn trans_crust_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl,
|
||||
body: ast::blk, llwrapfn: ValueRef, id: ast::node_id) {
|
||||
|
||||
@ -799,7 +850,7 @@ fn trans_crust_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl,
|
||||
atys = vec::tail(atys);
|
||||
attrs = vec::tail(attrs);
|
||||
j = 1u;
|
||||
llvm::LLVMGetParam(llwrapfn, 0 as c_uint)
|
||||
get_param(llwrapfn, 0u)
|
||||
} else if x86_64.ret_ty.cast {
|
||||
let retptr = alloca(bcx, x86_64.ret_ty.ty);
|
||||
BitCast(bcx, retptr, T_ptr(tys.ret_ty))
|
||||
@ -810,8 +861,7 @@ fn trans_crust_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl,
|
||||
let mut i = 0u;
|
||||
let n = vec::len(atys);
|
||||
while i < n {
|
||||
let mut argval =
|
||||
llvm::LLVMGetParam(llwrapfn, (i + j) as c_uint);
|
||||
let mut argval = get_param(llwrapfn, i + j);
|
||||
if option::is_some(attrs[i]) {
|
||||
argval = Load(bcx, argval);
|
||||
store_inbounds(bcx, argval, llargbundle,
|
||||
@ -835,8 +885,7 @@ fn trans_crust_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl,
|
||||
let mut i = 0u;
|
||||
let n = vec::len(tys.arg_tys);
|
||||
while i < n {
|
||||
let llargval = llvm::LLVMGetParam(llwrapfn,
|
||||
i as c_uint);
|
||||
let llargval = get_param(llwrapfn, i);
|
||||
store_inbounds(bcx, llargval, llargbundle,
|
||||
[0, i as int]);
|
||||
i += 1u;
|
||||
@ -944,8 +993,8 @@ fn decl_native_fn(ccx: @crate_ctxt, i: @ast::native_item,
|
||||
get_extern_fn(ccx.externs, ccx.llmod, ri_name,
|
||||
lib::llvm::CCallConv, fn_type)
|
||||
}
|
||||
|
||||
ast::native_abi_cdecl | ast::native_abi_stdcall {
|
||||
ast::native_abi_cdecl | ast::native_abi_stdcall |
|
||||
ast::native_abi_rust_builtin {
|
||||
// For true external functions: create a rust wrapper
|
||||
// and link to that. The rust wrapper will handle
|
||||
// switching to the C stack.
|
||||
|
@ -183,10 +183,10 @@ fn trans_append(bcx: block, vec_ty: ty::t, lhsptr: ValueRef,
|
||||
fn trans_append_literal(bcx: block, vptrptr: ValueRef, vec_ty: ty::t,
|
||||
vals: [@ast::expr]) -> block {
|
||||
let _icx = bcx.insn_ctxt("tvec::trans_append_literal");
|
||||
let ccx = bcx.ccx();
|
||||
let mut bcx = bcx, ccx = bcx.ccx();
|
||||
let elt_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
||||
let mut ti = none;
|
||||
let mut {bcx: bcx, val: td} = get_tydesc(bcx, elt_ty, ti);
|
||||
let td = get_tydesc(ccx, elt_ty, ti);
|
||||
base::lazily_emit_tydesc_glue(ccx, abi::tydesc_field_take_glue, ti);
|
||||
let opaque_v = PointerCast(bcx, vptrptr,
|
||||
T_ptr(T_ptr(ccx.opaque_vec_type)));
|
||||
|
@ -71,9 +71,17 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
|
||||
ast_map::node_variant(_, _, _) {
|
||||
uint::range(0u, n_tps) {|n| cx.uses[n] |= use_repr;}
|
||||
}
|
||||
ast_map::node_native_item(@{node: native_item_fn(_, _), _}, abi, _) {
|
||||
ast_map::node_native_item(i@@{node: native_item_fn(_, _), _}, abi, _) {
|
||||
if abi == native_abi_rust_intrinsic {
|
||||
uint::range(0u, n_tps) {|n| cx.uses[n] |= use_tydesc;}
|
||||
} else if abi == native_abi_rust_builtin {
|
||||
let flags = alt check i.ident {
|
||||
"size_of" | "align_of" | "init" |
|
||||
"reinterpret_cast" { use_repr }
|
||||
"get_tydesc" { use_tydesc }
|
||||
"forget" | "addr_of" { 0u }
|
||||
};
|
||||
uint::range(0u, n_tps) {|n| cx.uses[n] |= flags;}
|
||||
}
|
||||
}
|
||||
ast_map::node_ctor(@{node: item_class(_, _, ctor), _}, _) {
|
||||
|
@ -81,7 +81,7 @@ export ty_nil, mk_nil, type_is_nil;
|
||||
export ty_iface, mk_iface;
|
||||
export ty_res, mk_res;
|
||||
export ty_param, mk_param;
|
||||
export ty_ptr, mk_ptr, mk_mut_ptr, mk_nil_ptr, type_is_unsafe_ptr;
|
||||
export ty_ptr, mk_ptr, mk_mut_ptr, mk_imm_ptr, mk_nil_ptr, type_is_unsafe_ptr;
|
||||
export ty_rptr, mk_rptr;
|
||||
export ty_rec, mk_rec;
|
||||
export ty_enum, mk_enum, type_is_enum;
|
||||
@ -492,6 +492,10 @@ fn mk_rptr(cx: ctxt, r: region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) }
|
||||
fn mk_mut_ptr(cx: ctxt, ty: t) -> t { mk_ptr(cx, {ty: ty,
|
||||
mutbl: ast::m_mutbl}) }
|
||||
|
||||
fn mk_imm_ptr(cx: ctxt, ty: t) -> t {
|
||||
mk_ptr(cx, {ty: ty, mutbl: ast::m_imm})
|
||||
}
|
||||
|
||||
fn mk_nil_ptr(cx: ctxt) -> t {
|
||||
mk_ptr(cx, {ty: mk_nil(cx), mutbl: ast::m_imm})
|
||||
}
|
||||
|
@ -945,7 +945,13 @@ mod collect {
|
||||
fn convert(tcx: ty::ctxt, it: @ast::item) {
|
||||
alt it.node {
|
||||
// These don't define types.
|
||||
ast::item_mod(_) | ast::item_native_mod(_) {}
|
||||
ast::item_mod(_) {}
|
||||
ast::item_native_mod(m) {
|
||||
if front::attr::native_abi(it.attrs) ==
|
||||
either::right(ast::native_abi_rust_builtin) {
|
||||
for item in m.items { check_builtin_type(tcx, item); }
|
||||
}
|
||||
}
|
||||
ast::item_enum(variants, ty_params) {
|
||||
let tpt = ty_of_item(tcx, m_collect, it);
|
||||
write_ty(tcx, it.id, tpt.ty);
|
||||
@ -1408,6 +1414,44 @@ mod writeback {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_builtin_type(tcx: ty::ctxt, it: @ast::native_item) {
|
||||
fn param(tcx: ty::ctxt, n: uint) -> ty::t {
|
||||
ty::mk_param(tcx, n, local_def(0))
|
||||
}
|
||||
fn arg(m: ast::rmode, ty: ty::t) -> ty::arg {
|
||||
{mode: ast::expl(m), ty: ty}
|
||||
}
|
||||
let (n_tps, inputs, output) = alt it.ident {
|
||||
"size_of" | "align_of" { (1u, [], ty::mk_uint(tcx)) }
|
||||
"get_tydesc" { (1u, [], ty::mk_nil_ptr(tcx)) }
|
||||
"init" { (1u, [], param(tcx, 0u)) }
|
||||
"forget" { (1u, [arg(ast::by_move, param(tcx, 0u))],
|
||||
ty::mk_nil(tcx)) }
|
||||
"reinterpret_cast" { (2u, [arg(ast::by_ref, param(tcx, 0u))],
|
||||
param(tcx, 1u)) }
|
||||
"addr_of" { (1u, [arg(ast::by_ref, param(tcx, 0u))],
|
||||
ty::mk_imm_ptr(tcx, param(tcx, 0u))) }
|
||||
other {
|
||||
tcx.sess.span_err(it.span, "unrecognized builtin function: `" +
|
||||
other + "`");
|
||||
ret;
|
||||
}
|
||||
};
|
||||
let fty = ty::mk_fn(tcx, {proto: ast::proto_bare,
|
||||
inputs: inputs, output: output,
|
||||
ret_style: ast::return_val,
|
||||
constraints: []});
|
||||
let i_ty = ty_of_native_item(tcx, m_collect, it);
|
||||
let i_n_tps = (*i_ty.bounds).len();
|
||||
if i_n_tps != n_tps {
|
||||
tcx.sess.span_err(it.span, #fmt("builtin function has wrong number \
|
||||
of type parameters. found %u, \
|
||||
expected %u", i_n_tps, n_tps));
|
||||
} else if !ty::same_type(tcx, i_ty.ty, fty) {
|
||||
tcx.sess.span_err(it.span, #fmt("builtin function has wrong type. \
|
||||
expected %s", ty_to_str(tcx, fty)));
|
||||
}
|
||||
}
|
||||
|
||||
// Local variable gathering. We gather up all locals and create variable IDs
|
||||
// for them before typechecking the function.
|
||||
|
@ -557,6 +557,7 @@ type _mod = {view_items: [@view_item], items: [@item]};
|
||||
#[auto_serialize]
|
||||
enum native_abi {
|
||||
native_abi_rust_intrinsic,
|
||||
native_abi_rust_builtin,
|
||||
native_abi_cdecl,
|
||||
native_abi_stdcall,
|
||||
}
|
||||
@ -702,7 +703,8 @@ enum native_item_ {
|
||||
#[auto_serialize]
|
||||
enum inlined_item {
|
||||
ii_item(@item),
|
||||
ii_method(def_id /* impl id */, @method)
|
||||
ii_method(def_id /* impl id */, @method),
|
||||
ii_native(@native_item),
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -454,6 +454,7 @@ impl inlined_item_methods for inlined_item {
|
||||
fn ident() -> ident {
|
||||
alt self {
|
||||
ii_item(i) { i.ident }
|
||||
ii_native(i) { i.ident }
|
||||
ii_method(_, m) { m.ident }
|
||||
}
|
||||
}
|
||||
@ -461,6 +462,7 @@ impl inlined_item_methods for inlined_item {
|
||||
fn id() -> ast::node_id {
|
||||
alt self {
|
||||
ii_item(i) { i.id }
|
||||
ii_native(i) { i.id }
|
||||
ii_method(_, m) { m.id }
|
||||
}
|
||||
}
|
||||
@ -468,6 +470,7 @@ impl inlined_item_methods for inlined_item {
|
||||
fn accept<E>(e: E, v: visit::vt<E>) {
|
||||
alt self {
|
||||
ii_item(i) { v.visit_item(i, e, v) }
|
||||
ii_native(i) { v.visit_native_item(i, e, v) }
|
||||
ii_method(_, m) { visit::visit_method_helper(m, e, v) }
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user