gpt4 book ai didi

rust - 为什么 Rust 在 LLVM IR 闭包环境中将闭包捕获的 i64 存储为 i64*s?

转载 作者:行者123 更新时间:2023-11-29 07:57:38 24 4
gpt4 key购买 nike

在这个简单的例子中

#[inline(never)]
fn apply<F, A, B>(f: F, x: A) -> B
where F: FnOnce(A) -> B {
f(x)
}

fn main() {
let y: i64 = 1;
let z: i64 = 2;
let f = |x: i64| x + y + z;
print!("{}", apply(f, 42));
}

传递给 apply 的闭包作为 LLVM IR {i64*, i64*}* 传递:

%closure = type { i64*, i64* }
define internal fastcc i64 @apply(%closure* noalias nocapture readonly dereferenceable(16)) unnamed_addr #0 personality i32 (i32, i32, i64, %"8.unwind::libunwind::_Unwind_Exception"*, %"8.unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
entry-block:
%1 = getelementptr inbounds %closure, %closure* %0, i64 0, i32 1
%2 = getelementptr inbounds %closure, %closure* %0, i64 0, i32 0
%3 = load i64*, i64** %2, align 8
%4 = load i64*, i64** %1, align 8
%.idx.val.val.i = load i64, i64* %3, align 8, !noalias !1
%.idx1.val.val.i = load i64, i64* %4, align 8, !noalias !1
%5 = add i64 %.idx.val.val.i, 42
%6 = add i64 %5, %.idx1.val.val.i
ret i64 %6
}

(apply 在生成的 LLVM 代码中实际上有一个更复杂的名字。)

这会导致两个负载到达每个捕获的变量。为什么 %closure 不只是 {i64, i64} (这将使参数成为 apply {i64, i64}* )?

最佳答案

Closures默认情况下通过引用捕获。您可以通过在参数列表前添加 move 关键字来将该行为更改为按值捕获:

let f = move |x: i64| x + y + z;

这会生成更精简的代码:

define internal fastcc i64 @apply(i64 %.0.0.val, i64 %.0.1.val) unnamed_addr #0 personality i32 (i32, i32, i64, %"8.unwind::libunwind::_Unwind_Exception"*, %"8.unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
entry-block:
%0 = add i64 %.0.0.val, 42
%1 = add i64 %0, %.0.1.val
ret i64 %1
}

添加move 关键字意味着闭包使用的任何值都将被移动到闭包的环境中。对于整数,即 Copy,没有太大区别,但对于其他类型,如 String,这意味着你不能使用创建闭包后, String 不再位于外部范围内。这是一个孤注一掷的交易,但您可以在 move 闭包之外手动获取对单个变量的引用,并让闭包使用这些引用而不是原始值来获得手动捕获引用行为.

Can you observe the value vs ref difference somehow in this code?

If you take the address of the captured variable, you can observe the difference.请注意第一条和第二条输出线是如何相同的,而第三条是不同的。

关于rust - 为什么 Rust 在 LLVM IR 闭包环境中将闭包捕获的 i64 存储为 i64*s?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40230796/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com