toau2c 네이티브 코드젠 — ARM / RISC-V / WASM 백엔드 (2026-06-20)
개요
한선씨 TOAU 바이트코드를
호스트 C → 베어메탈 ARM·RISC-V → WebAssembly 까지
네이티브 컴파일하는 출구를 완성했다. 임베디드·웹·LLM의 공통 코드젠 토대.
crownyc.c 는 무수정. 신규 파일(런타임/플랫폼/빌드)만 추가.
.한선 → hanseonc_high → .toau → toau2c → prog.c ─┬─ cc → 호스트 네이티브
├─ arm-none-eabi-gcc → Cortex-M3 ELF (QEMU lm3s6965)
├─ riscv64-elf-gcc → rv32imac ELF (QEMU virt)
└─ llvm clang → wasm32 모듈 (node/deno/브라우저)
무엇을 했나
① 베어메탈 런타임 — 핵심 버그 수정
mcu/runtime_mcu.c 의 FRAME_LEAVE(opcode 79) 가 메모리를 회수하지 않아
피보(15) 재귀(~1973 콜)가 1024-큐브 윈도우를 넘쳐 전부 sink 로 붕괴 → 오답 -390.
- 수정: 정수 펌웨어는 프레임 너머 살아남는 힙 객체(배열/문자열/맵)가 없으므로
mem_count = frame_ptr 로
스택 규율 회수. 깊은 재귀가 유한 윈도우에서 동작.
feedback_crownyc_frame_reclaim_unsafe(crownyc 본체 회수 금지) 와 모순 아님 —
그 함정은 crownyc 아레나가 프레임+배열+문자열을 섞기 때문. MCU 정수코어엔 무관.
- 결과: 피보(15)=610 정답, oob=0.
② ARM 크로스컴파일 + QEMU
mcu/ (이전 세션 토대) —
startup_lm3s.c(Cortex-M3 부트+UART),
lm3s6965.ld,
toau2c-mcu-build.sh. QEMU lm3s6965evb 에서 출력이 인터프리터와 일치.
③ WASM 백엔드 (신규)
wasm/ — 베어메탈
runtime_mcu.c 를 그대로 재사용(freestanding).
platform_wasm.c: 출력을 선형메모리 버퍼에 누적(wasm_out_ptr/len),
입력 버퍼(
wasm_in_ptr/wasm_set_input), MMIO 시뮬,
wasm_run 익스포트.
run.mjs: node 하니스 (입력파일 → 선형메모리 적재 → 실행 → 출력 읽기).
toau2c-wasm-build.sh: llvm clang --target=wasm32 -nostdlib.
- 자족적 모듈(임포트 0개), 35KB. node v25 에서 인터프리터와 바이트 일치.
④ RISC-V 백엔드 (신규)
mcu_riscv/ — ARM 과 동일한
runtime_mcu.c 공유.
startup_riscv.c: _start(rv32) 부트, NS16550 UART, 프리스탠딩 mem*, MMIO 시뮬.
riscv_virt.ld: RAM @ 0x80000000 단일이미지(LMA=VMA → .data 복사 불요).
toau2c-riscv-build.sh: riscv64-elf-gcc -march=rv32imac -mabi=ilp32.
- QEMU virt(rv32) 에서 인터프리터와 일치.
④ 데모 + 왕복검증 하니스
mcu/demo_int.한선(제곱합·피보재귀·나눗셈·루프), mcu/blink.한선(GPIO MMIO),
mcu/echo.한선(UART RX→echo). blink/echo 는 동시 세션이 MMIO·문자열로 고도화.
wasm/verify-backends.sh: 1개 .한선 → 6개 출구 실행 → 출력 diff.
【A】 네이티브 합의: ③MCU = ④ARM = ⑤WASM = ⑥RISC-V (코드젠 정확성 — 항상 필수)
【B】 참조 VM 패리티: ①인터프리터 = ②호스트네이티브
【C】 전체 패리티(정보): MMIO/파일IO 오버로드 시 의도된 분기 표시.검증 결과 (직접 실행)
| 데모 | 6출구 결과 |
|---|
| demo_int (순수계산) | 4/4 PASS — 6출구 전부 바이트 일치 (385 610 14 2 -15) |
| blink (MMIO) | 4/4 PASS — 네이티브 4종 합의, 인터프리터는 파일IO로 의도분기 |
| echo (입력+문자열) | 4/4 PASS — 6출구 전부 일치 (UTF-8 안녕/crowny) |
핵심 함정 (다음 세션 필독)
- 쓰기/읽기(opcode 620/249) 의미 분기: 인터프리터/호스트네이티브=파일IO,
MCU/ARM/WASM/RISC-V=MMIO. MMIO 데모는 인터프리터와
비교 불가 —
네이티브 백엔드끼리 합의로 검증해야 함(harness 【A】).
- FRAME 회수: MCU/WASM/RISC-V 정수코어는 회수함(깊은 재귀). crownyc 본체는 금지.
- RISC-V/WASM 은 libc 없음 → 구조체 복사용 memcpy/memset 직접 제공 필수.
- Apple clang 은 wasm32 미지원 → homebrew llvm clang(
/opt/homebrew/opt/llvm) 사용.
관련 파일
crownyc/toau2c.c, runtime_stub.c/h (호스트)
crownyc/mcu/ — runtime_mcu.c/h, startup_lm3s.c, lm3s6965.ld, platform_host.c, demo_int/blink/echo.한선, trit_alu.한선
crownyc/wasm/ — platform_wasm.c, run.mjs, runtime_stub.h, toau2c-wasm-build.sh, verify-backends.sh
crownyc/mcu_riscv/ — startup_riscv.c, riscv_virt.ld, runtime_stub.h, toau2c-riscv-build.sh
잔여 이슈
- 문자열/버퍼 풀은 동시 세션이 MCU/WASM 에 확장 중(웹 스케일 -D 오버라이드).
- LLVM IR/네이티브 AOT(부동소수·libm)는 후속. MCU 코어는 정수 펌웨어 한정.
- 실제 하드웨어(RPi Pico/ESP32) 플래싱은 미검증(QEMU 까지).