Rustc/LLVM 使用 opt-level=0 为 aarch64 生成错误代码

Rustc/LLVM generates faulty code for aarch64 with opt-level=0

我有两个文件 assembled/compiled/linked 进入简约内核。

start.s:

    .set CPACR_EL1_FPEN, 0b11 << 20

    .set BOOT_STACK_SIZE, 8 * 1024

    .global __boot_stack
    .global __start
    .global __halt

    .bss
    .align 16
__boot_stack:
    .fill BOOT_STACK_SIZE

    .text
__start:
    /* disable FP and SIMD traps */
    mov x0, #CPACR_EL1_FPEN
    msr cpacr_el1, x0

    /* set stack */
    adr x0, __boot_stack
    add sp, x0, #BOOT_STACK_SIZE

    /* call the Rust entry point */
    bl __boot

__halt:
    /* halt CPU */
    wfi
    b __halt

boot.rs:

#[no_mangle]
pub extern fn __boot() {
    unsafe {
        let ptr = 0x9000000 as *mut u8;
        *ptr = '!' as u8;
   }
}

对于 opt-level=3,生成的代码输出单个 '!'到串行端口(如预期的那样)。对于 opt-level=0 我有一个奇怪的无限循环(例如'!!!!!!!!....')。这是有问题的代码的反汇编转储:

0000000000000000 <__kernel_begin>:
   0:   d2a00600    mov x0, #0x300000               // #3145728
   4:   d5181040    msr cpacr_el1, x0
   8:   100007c0    adr x0, 100 <__boot_stack>
   c:   9140081f    add sp, x0, #0x2, lsl #12
  10:   94000003    bl  1c <__boot>

0000000000000014 <__halt>:
  14:   d503207f    wfi
  18:   17ffffff    b   14 <__halt>

000000000000001c <__boot>:
  1c:   a9bf7bfd    stp x29, x30, [sp,#-16]!
  20:   910003fd    mov x29, sp
  24:   94000003    bl  30 <aarch64::boot::__boot::__rust_abi>
  28:   a8c17bfd    ldp x29, x30, [sp],#16
  2c:   d65f03c0    ret

0000000000000030 <aarch64::boot::__boot::__rust_abi>:
  30:   d10043ff    sub sp, sp, #0x10
  34:   52a12008    mov w8, #0x9000000              // #150994944
  38:   2a0803e9    mov w9, w8
  3c:   f90007e9    str x9, [sp,#8]
  40:   52800428    mov w8, #0x21                   // #33
  44:   39000128    strb    w8, [x9]
  48:   910043ff    add sp, sp, #0x10
  4c:   d65f03c0    ret

代码使用 qemu-system-aarch64 测试。我没有看到它的严重问题(冗余除外)。你能提出这种异常行为的可能原因吗?

P.S。这是可以正常工作的优化版本:

0000000000000000 <__kernel_begin>:
   0:   d2a00600    mov x0, #0x300000               // #3145728
   4:   d5181040    msr cpacr_el1, x0
   8:   1007ffc0    adr x0, 10000 <__boot_stack>
   c:   9140081f    add sp, x0, #0x2, lsl #12
  10:   94000003    bl  1c <__boot>

0000000000000014 <__halt>:
  14:   d503207f    wfi
  18:   17ffffff    b   14 <__halt>

000000000000001c <__boot>:
  1c:   52a12008    mov w8, #0x9000000              // #150994944
  20:   52800429    mov w9, #0x21                   // #33
  24:   39000109    strb    w9, [x8]
  28:   d65f03c0    ret

我已经成功运行非优化代码没有异常。感谢 Notlikethat 的想法。我的堆栈刚刚映射到只读内存。

所以我刚刚将偏移量语句添加到我的链接描述文件 (".= 1024M;") 中,以便使所有符号从 1GiB(RAM 开始的位置)开始。修改后代码开始正常工作。