mrk-its / rust-mos

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
55 stars 7 forks source link

Help Needed: Attempt to compile `rust-mos-hello-world` for new target outputs gibberish binaries, likely only data sections #22

Closed TheHans255 closed 1 year ago

TheHans255 commented 1 year ago

Related: https://github.com/llvm-mos/llvm-mos-sdk/issues/102

I'm attempting to use rust-mos to write some Rust code for the Apple //e. I've managed to create a new target triple file and get some code running in C, but I have not accomplished the same in Rust - instead, the binary that Rust generates is mostly gibberish.

Starting from https://github.com/mrk-its/rust-mos-hello-world and using the provided devcontainer, I added the following files:

mos-apple-iie-none.json:

{
  "arch": "mos",
  "atomic-cas": false,
  "cpu": "mos6502",
  "data-layout": "e-m:e-p:16:8-i16:8-i32:8-i64:8-f32:8-f64:8-a:8-Fi8-n8",
  "disable-redzone": true,
  "linker": "mos-common-clang",
  "llvm-args": [
    "--force-precise-rotation-cost",
    "--jump-inst-cost=6",
    "--force-loop-cold-block",
    "--phi-node-folding-threshold=0",
    "--two-entry-phi-node-folding-threshold=0",
    "--align-large-globals=false",
    "--disable-spill-hoist"
  ],
  "llvm-target": "mos-unknown-none",
  "max-atomic-width": 8,
  "min-atomic-width": 8,
  "no-default-libraries": false,
  "panic-strategy": "abort",
  "requires-lto": true,
  "singlethread": true,
  "supports-stack-protector": false,
  "target-c-int-width": "16",
  "target-pointer-width": "16",
  "trap-unreachable": false,
  "vendor": "apple"
}

appleiielinker.ld:

/*
 * Apple //e linker script
 */

/* Available RAM goes from 0x0800 to 0x9600, skipping 0x2000-0x5fff
 * for HIRES graphics. The program will be loaded at 0x6000,
 * and the 6K below HIRES will be reserved for the soft stack
 */
MEMORY {
    ram (rw) : ORIGIN = 0x6000, LENGTH = 0x35ff
}

__rc0 = 0x0002;
INCLUDE imag-regs.ld
ASSERT(__rc31 == 0x0021, "Inconsistent zero page map.")

MEMORY { zp : ORIGIN = __rc31 + 1, LENGTH = 0x90 - (__rc31 + 1) }

SECTIONS {
    INCLUDE c.ld
}

/* Set the operand stack to the 6K memory region below HIRES
 */
__stack = 0x1FFF;

OUTPUT_FORMAT {
    TRIM(ram)
}

Additions to .cargo/config.toml:

[target.mos-apple-iie-none]
rustflags = ["-Clink-arg=-Tappleiielinker.ld"]

Additions to src/main.rs:

#[no_mangle]
fn __putchar(c: u8) -> () {
    // basic putchar implementation, linked to by llvm-mos-sdk
}

Building this binary with the command $ cargo build --release --target=mos-apple-iie-none.json produces an approximately 200B file that is mostly gibberish, with the text "Hello 6502" somewhat visible (with control characters in between) and "gdb_load_rust_pretty_printers.py" clearly visible.

By contrast, building this comparable C file:

#include <stdio.h>

// putchar() on the Apple II system
void __putchar(char c) {
  // basic __putchar implementation
}

int main(void) { 
    for (int x = 0; x < 100; x++) {
        printf("Hello %d!\r", 6502); 
    }
}

with $ mos-common-clang -o main -Os -flto -T appleiielinker.ld main.c produces a binary that runs as expected.

TheHans255 commented 1 year ago

Never mind - upon further investigation, it was apparent that this was a combination of Rust producing extremely efficient printout code compared to C, as well as the putchar implementation having a bug that made it far less complex than it should have been.