我正在尝试通过编译 Rust 来学习汇编语言。我找到了一种将 Rust 代码编译为二进制机器码的方法,并且能够使用 objdump
命令查看生成的汇编代码。然而,如果我写下面这段代码:
#![no_main]
#[link_section = ".text.entry"]
#[no_mangle]
pub extern "C" fn _start() -> ! {
let a: u64 = 4;
let b: u64 = 7;
let c: u64 = a * b;
loop {}
}
我得到的汇编代码如下:
0000000000000000 <.data>:
0: 1101 addi sp,sp,-32
2: 4511 li a0,4
4: e42a sd a0,8(sp)
6: 451d li a0,7
8: e82a sd a0,16(sp)
a: 4571 li a0,28
c: ec2a sd a0,24(sp)
e: a009 j 0x10
10: a001 j 0x10
看起来rust正在将mul折叠成常数。我使用以下编译选项:
Cargo.toml:
[profile.dev]
opt-level = 0
mir-opt-level = 0
有没有办法阻止 Rust 进行优化?
LLVM 生成的代码如下:
; Function Attrs: noreturn nounwind
define dso_local void @_start() unnamed_addr #0 section ".text.entry" !dbg !22 {
start:
%c.dbg.spill = alloca i64, align 8
%b.dbg.spill = alloca i64, align 8
%a.dbg.spill = alloca i64, align 8
store i64 4, i64* %a.dbg.spill, align 8, !dbg !36
call void @llvm.dbg.declare(metadata i64* %a.dbg.spill, metadata !28, metadata !DIExpression()), !dbg !37
store i64 7, i64* %b.dbg.spill, align 8, !dbg !38
call void @llvm.dbg.declare(metadata i64* %b.dbg.spill, metadata !31, metadata !DIExpression()), !dbg !39
store i64 28, i64* %c.dbg.spill, align 8, !dbg !40
call void @llvm.dbg.declare(metadata i64* %c.dbg.spill, metadata !33, metadata !DIExpression()), !dbg !41
看起来优化是在LLVM pass之前进行的。
$ rustc --version
rustc 1.60.0-nightly (c5c610aad 2022-02-14)
构建命令:
RUSTFLAGS="--emit=llvm-bc" cargo build --target riscv64imac-unknown-none-elf --no-default-features
build.rs
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rustc-link-arg=-Tlink.ld");
}
link.ld
ENTRY(_start)
SECTIONS {
.text : { *(.text); *(.text.*) }
}