markdown · 4125 bytes Raw Blame History

afs-as

(noun): a barrel of shifted registers

Standalone ARM64 assembler for macOS. Reads .s assembly text, encodes ARM64 instructions, and emits Mach-O object files linkable with Apple's ld.

Part of ARMFORTAS, a bespoke ARM64 Fortran compiler.

Usage

# Assemble
afs-as hello.s -o hello.o

# Or let afs-as derive hello.o automatically
afs-as hello.s

# Assemble from stdin to stdout
cat hello.s | afs-as - -o - > hello.o

# Inspect CLI help
afs-as --help

# Link and run
ld hello.o -o hello -lSystem -syslibroot $(xcrun --show-sdk-path) -e _main
./hello

CLI behavior is intentionally small and explicit:

  • --help and --version print to stdout and exit 0
  • usage errors exit 2
  • parse / assembly failures exit 1 with file, line, column, source line, and caret diagnostics
  • -- stops option parsing
  • - can be used for stdin input or stdout output
  • stdin input requires explicit -o <output.o> or -o -

Standalone Support Matrix

The public standalone surface is intentionally small and explicit.

CLI:

  • one input file
  • default .o derivation from the input path
  • -- stops option parsing
  • - may be used for stdin input or stdout output
  • stdin requires explicit -o <path> or -o -
  • usage errors exit 2; parse or assembly failures exit 1

Supported section surface:

  • __TEXT,__text
  • __TEXT,__cstring
  • __TEXT,__literal16
  • __TEXT,__const
  • __DATA,__data
  • __DATA,__thread_data
  • __DATA,__thread_vars
  • __DATA,__thread_bss
  • __DATA,__bss

Supported directive families include:

  • symbol directives: .global / .globl, .extern, .private_extern, .weak_reference, .weak_definition, .set, .equ
  • data/layout directives: .byte, .short, .word, .long, .quad, .ascii, .asciz, .string, .space, .skip, .zero, .fill, .align, .p2align, .comm, .zerofill, .tbss
  • section-selection directives: .text, .data, .cstring, and .section for the supported section set
  • metadata directives: .subsections_via_symbols, .build_version for macos
  • linker-optimization hints: .loh AdrpAdd, .loh AdrpLdr, .loh AdrpLdrGot, .loh AdrpLdrGotLdr
  • CFI subset: .cfi_startproc, .cfi_endproc, .cfi_def_cfa, .cfi_def_cfa_offset, .cfi_def_cfa_register, .cfi_offset, .cfi_restore, .cfi_adjust_cfa_offset

Unsupported forms are expected to fail explicitly rather than assemble silently.

Release gates for a standalone claim:

  • cargo test -p afs-as
  • cargo clippy -p afs-as --all-targets -- -D warnings
  • green differential, corpus, CLI, diagnostic, dashboard, stress, fuzz, malformed-input, and perf suites in CI

Library API

use afs_as::assemble;
use afs_as::encode::Inst;
use afs_as::reg::*;

// From source text
let obj = assemble::assemble_source(".global _main\n_main:\nret\n").unwrap();

// From pre-built instructions (no parsing)
let obj = assemble::assemble_instructions(
    &[Inst::Ret { rn: X30 }],
    &["_main"],
);

assemble_instructions is the compiler-facing fast path. It assumes callers build valid Inst values; source-level validation and diagnostics live in assemble_source. Passing an Inst that fails encoder preconditions (for example, a logical-immediate AndImm with an unencodable bit pattern) will panic rather than return an error — the contract is that the compiler is responsible for emitting only valid instructions on this path.

Tests

afs-as is validated through layered coverage rather than a single golden path:

  • unit tests for parsing, encoding, expression classification, Mach-O writing, and diagnostics
  • differential tests against Apple as
  • raw-object parity corpus tests
  • linker / runtime end-to-end tests
  • CLI smoke tests for user-facing behavior
cargo test -p afs-as

Building

cargo build -p afs-as          # build
cargo test -p afs-as           # test
cargo clippy -p afs-as         # lint

Requires macOS on ARM64 (Apple Silicon) for integration tests that invoke the system assembler and linker.

License

GPL-3.0

View source
1 # afs-as
2
3 *(noun): a barrel of shifted registers*
4
5 Standalone ARM64 assembler for macOS. Reads `.s` assembly text, encodes ARM64 instructions, and emits Mach-O object files linkable with Apple's `ld`.
6
7 Part of [ARMFORTAS](https://github.com/FortranGoingOnForty/armfortas), a bespoke ARM64 Fortran compiler.
8
9 ## Usage
10
11 ```bash
12 # Assemble
13 afs-as hello.s -o hello.o
14
15 # Or let afs-as derive hello.o automatically
16 afs-as hello.s
17
18 # Assemble from stdin to stdout
19 cat hello.s | afs-as - -o - > hello.o
20
21 # Inspect CLI help
22 afs-as --help
23
24 # Link and run
25 ld hello.o -o hello -lSystem -syslibroot $(xcrun --show-sdk-path) -e _main
26 ./hello
27 ```
28
29 CLI behavior is intentionally small and explicit:
30
31 - `--help` and `--version` print to stdout and exit `0`
32 - usage errors exit `2`
33 - parse / assembly failures exit `1` with file, line, column, source line, and caret diagnostics
34 - `--` stops option parsing
35 - `-` can be used for stdin input or stdout output
36 - stdin input requires explicit `-o <output.o>` or `-o -`
37
38 ## Standalone Support Matrix
39
40 The public standalone surface is intentionally small and explicit.
41
42 CLI:
43
44 - one input file
45 - default `.o` derivation from the input path
46 - `--` stops option parsing
47 - `-` may be used for stdin input or stdout output
48 - stdin requires explicit `-o <path>` or `-o -`
49 - usage errors exit `2`; parse or assembly failures exit `1`
50
51 Supported section surface:
52
53 - `__TEXT,__text`
54 - `__TEXT,__cstring`
55 - `__TEXT,__literal16`
56 - `__TEXT,__const`
57 - `__DATA,__data`
58 - `__DATA,__thread_data`
59 - `__DATA,__thread_vars`
60 - `__DATA,__thread_bss`
61 - `__DATA,__bss`
62
63 Supported directive families include:
64
65 - symbol directives: `.global` / `.globl`, `.extern`, `.private_extern`, `.weak_reference`, `.weak_definition`, `.set`, `.equ`
66 - data/layout directives: `.byte`, `.short`, `.word`, `.long`, `.quad`, `.ascii`, `.asciz`, `.string`, `.space`, `.skip`, `.zero`, `.fill`, `.align`, `.p2align`, `.comm`, `.zerofill`, `.tbss`
67 - section-selection directives: `.text`, `.data`, `.cstring`, and `.section` for the supported section set
68 - metadata directives: `.subsections_via_symbols`, `.build_version` for `macos`
69 - linker-optimization hints: `.loh AdrpAdd`, `.loh AdrpLdr`, `.loh AdrpLdrGot`, `.loh AdrpLdrGotLdr`
70 - CFI subset: `.cfi_startproc`, `.cfi_endproc`, `.cfi_def_cfa`, `.cfi_def_cfa_offset`, `.cfi_def_cfa_register`, `.cfi_offset`, `.cfi_restore`, `.cfi_adjust_cfa_offset`
71
72 Unsupported forms are expected to fail explicitly rather than assemble silently.
73
74 Release gates for a standalone claim:
75
76 - `cargo test -p afs-as`
77 - `cargo clippy -p afs-as --all-targets -- -D warnings`
78 - green differential, corpus, CLI, diagnostic, dashboard, stress, fuzz, malformed-input, and perf suites in CI
79
80 ## Library API
81
82 ```rust
83 use afs_as::assemble;
84 use afs_as::encode::Inst;
85 use afs_as::reg::*;
86
87 // From source text
88 let obj = assemble::assemble_source(".global _main\n_main:\nret\n").unwrap();
89
90 // From pre-built instructions (no parsing)
91 let obj = assemble::assemble_instructions(
92 &[Inst::Ret { rn: X30 }],
93 &["_main"],
94 );
95 ```
96
97 `assemble_instructions` is the compiler-facing fast path. It assumes callers build valid
98 `Inst` values; source-level validation and diagnostics live in `assemble_source`. Passing an
99 `Inst` that fails encoder preconditions (for example, a logical-immediate `AndImm` with an
100 unencodable bit pattern) will **panic** rather than return an error — the contract is that
101 the compiler is responsible for emitting only valid instructions on this path.
102
103 ## Tests
104
105 `afs-as` is validated through layered coverage rather than a single golden path:
106
107 - unit tests for parsing, encoding, expression classification, Mach-O writing, and diagnostics
108 - differential tests against Apple `as`
109 - raw-object parity corpus tests
110 - linker / runtime end-to-end tests
111 - CLI smoke tests for user-facing behavior
112
113 ```bash
114 cargo test -p afs-as
115 ```
116
117 ## Building
118
119 ```bash
120 cargo build -p afs-as # build
121 cargo test -p afs-as # test
122 cargo clippy -p afs-as # lint
123 ```
124
125 Requires macOS on ARM64 (Apple Silicon) for integration tests that invoke the system assembler and linker.
126
127 ## License
128
129 GPL-3.0