← 목록
기타 2026-06-20 5KB 읽기 5분

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 까지).