Rust内置函数"transmute"实际上是在哪里实现的?

4

我正在寻找Rust内置函数的实现,特别是具有一个参数的“transmute”内置函数。

我在cast.rs中看到了以下代码,但正如您所看到的,它只是将其委托给其他transmute的实现。

#[inline]
pub unsafe fn transmute<L, G>(thing: L) -> G {
    intrinsics::transmute(thing)
}

实现intrinsic函数的代码在哪里,特别是transmute intrinsic函数的实现?
1个回答

3
cast::transmute 委托给 intrinsics::transmute。有一个名为 intrinsics(现在位于 libcore 中)的模块,其中包含了对几个函数的extern绑定,其中就包括transmute。从该模块文档中可以看出,内置函数的实现位于librustc/middle/trans/foreign.rs中。

不过,据我所见,内置函数的实际实现位于librustc/middle/trans/intrinsic.rs中。你可以搜索transmute,然后在一个非常大的 match 语句中找到一段代码,它看起来像这样:

    "transmute" => {
        let (in_type, out_type) = (*substs.substs.tps.get(0),
                                   *substs.substs.tps.get(1));
        let llintype = type_of::type_of(ccx, in_type);
        let llouttype = type_of::type_of(ccx, out_type);

        let in_type_size = machine::llbitsize_of_real(ccx, llintype);
        let out_type_size = machine::llbitsize_of_real(ccx, llouttype);
        if in_type_size != out_type_size {
            let sp = match ccx.tcx.map.get(ref_id.unwrap()) {
                ast_map::NodeExpr(e) => e.span,
                _ => fail!("transmute has non-expr arg"),
            };
            ccx.sess().span_fatal(sp,
                format!("transmute called on types with different sizes: \
                         {intype} ({insize, plural, =1{# bit} other{# bits}}) to \
                         {outtype} ({outsize, plural, =1{# bit} other{# bits}})",
                        intype = ty_to_str(ccx.tcx(), in_type),
                        insize = in_type_size as uint,
                        outtype = ty_to_str(ccx.tcx(), out_type),
                        outsize = out_type_size as uint));
        }

        if !return_type_is_void(ccx, out_type) {
            let llsrcval = get_param(decl, first_real_arg);
            if type_is_immediate(ccx, in_type) {
                match fcx.llretptr.get() {
                    Some(llretptr) => {
                        Store(bcx, llsrcval, PointerCast(bcx, llretptr, llintype.ptr_to()));
                        RetVoid(bcx);
                    }
                    None => match (llintype.kind(), llouttype.kind()) {
                        (Pointer, other) | (other, Pointer) if other != Pointer => {
                            let tmp = Alloca(bcx, llouttype, "");
                            Store(bcx, llsrcval, PointerCast(bcx, tmp, llintype.ptr_to()));
                            Ret(bcx, Load(bcx, tmp));
                        }
                        (Array, _) | (_, Array) | (Struct, _) | (_, Struct) => {
                            let tmp = Alloca(bcx, llouttype, "");
                            Store(bcx, llsrcval, PointerCast(bcx, tmp, llintype.ptr_to()));
                            Ret(bcx, Load(bcx, tmp));
                        }
                        _ => {
                            let llbitcast = BitCast(bcx, llsrcval, llouttype);
                            Ret(bcx, llbitcast)
                        }
                    }
                }
            } else if type_is_immediate(ccx, out_type) {
                let llsrcptr = PointerCast(bcx, llsrcval, llouttype.ptr_to());
                let ll_load = Load(bcx, llsrcptr);
                Ret(bcx, ll_load);
            } else {
                // NB: Do not use a Load and Store here. This causes massive
                // code bloat when `transmute` is used on large structural
                // types.
                let lldestptr = fcx.llretptr.get().unwrap();
                let lldestptr = PointerCast(bcx, lldestptr, Type::i8p(ccx));
                let llsrcptr = PointerCast(bcx, llsrcval, Type::i8p(ccx));

                let llsize = llsize_of(ccx, llintype);
                call_memcpy(bcx, lldestptr, llsrcptr, llsize, 1);
                RetVoid(bcx);
            };
        } else {
            RetVoid(bcx);
        }
    }

看起来这是一个生成代码的代码,这个代码将被插入到 transmute 的调用位置。我不是编译器专家,如果我说错了,请有经验的人纠正我。


从我的LLVM知识和我对Rust代码生成策略的了解来看,你的解释似乎是正确的。 - user395760

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接