Skip to content

feat(cc): extern-call fallback for libbboeos exports#448

Merged
bboe merged 1 commit into
mainfrom
bboe/cc-libbboeos-extern-call
May 20, 2026
Merged

feat(cc): extern-call fallback for libbboeos exports#448
bboe merged 1 commit into
mainfrom
bboe/cc-libbboeos-extern-call

Conversation

@bboe
Copy link
Copy Markdown
Owner

@bboe bboe commented May 20, 2026

Summary

Phase 3 step 2 of the shared-libbboeos design (spec). cc.py's `Call` AST visitor previously raised `unknown function: ` whenever a called identifier wasn't a builtin / user function / function pointer / inline body. When the called name matches a defined `FUNCTION__PTR` constant in `kernel/include/constants.asm` under `--target user`, emit a cdecl indirect call through the libbboeos pointer table:

```
push ... push
call [FUNCTION__PTR]
add esp, N * 4
```

The pointer table lives at user-virt `0x10800` in the libbboeos blob (populated by `user/libbboeos/libbboeos.ld`'s `LONG()` entries); each `FUNCTION__PTR` is the absolute address of its slot. Same clobber accounting as a user-function call (full register-pool caller-saves charged) so the auto-pin allocator schedules around the call site correctly.

Self-host assembler

The self-hosted assembler in `user/programs/asm.c` gains the matching `call [absolute]` form — `FF 15 abs32` under bits=32, `FF 16 abs16` under bits=16 — so `tests/test_asm.py`'s NASM-vs-self-host byte-equivalence harness keeps clean across the seven programs that now use the new emission.

Cleanups

Per-program `strcmp` reimplementations in:

  • `user/programs/fd_helpers.c`
  • `user/programs/ls.c`
  • `user/programs/pipe_consumer.c`
  • `user/programs/pipe_producer.c`
  • `user/programs/pipe_spam.c`
  • `user/programs/shell.c`
  • `user/programs/sort.c` (both the forward decl + body)

…are deleted; those calls now resolve to the libbboeos shared `strcmp` via `FUNCTION_STRCMP_PTR`.

Kernel-mode compilation keeps the strict unknown-function error (the kernel must not reach into the user shared blob).

Test plan

  • `./make_os.sh` clean
  • `tests/test_asm.py` — 42/42 pass (round-trip including `call [FUNCTION_STRCMP_PTR]`)
  • `tests/test_programs.py` — 89/89
  • `tests/test_bboefs.py` — 6/6
  • `tests/test_pipeline_*.py` — 7/7 (the shell + pipe programs are the heaviest strcmp users)
  • `tests/test_cc_compatibility.py` — 57/57 (clang's strcmp prototype from `<string.h>` matches the call sites)
  • `pytest tests/unit/` — 456/456

🤖 Generated with Claude Code

@bboe bboe force-pushed the bboe/cc-libbboeos-extern-call branch from a7b6efd to 6c176e9 Compare May 20, 2026 13:41
Phase 3 step 2 of the shared-libbboeos design.  cc.py's Call AST
visitor previously raised `unknown function: <name>` whenever a
called identifier wasn't a builtin / user function / function
pointer / inline body.  When the called name matches a defined
`FUNCTION_<NAME>_PTR` constant in `kernel/include/constants.asm`
under `--target user`, emit a cdecl indirect call through the
libbboeos pointer table.

The self-hosted assembler in `user/programs/asm.c` gains the
matching `call [absolute]` form (FF 15 abs32 / FF 16 abs16) so the
existing `tests/test_asm.py` NASM-vs-self-host byte-equivalence
harness keeps clean across the seven programs that now use the new
emission.

Per-program `strcmp` reimplementations in
`user/programs/{fd_helpers,ls,pipe_consumer,pipe_producer,
pipe_spam,shell,sort}.c` are deleted — those calls now resolve to
the libbboeos shared `strcmp` via `FUNCTION_STRCMP_PTR`.

Kernel-mode compilation keeps the strict unknown-function error
(the kernel must not reach into the user shared blob).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bboe bboe force-pushed the bboe/cc-libbboeos-extern-call branch from 6c176e9 to a27b4d5 Compare May 20, 2026 13:45
@bboe bboe merged commit 42c5423 into main May 20, 2026
27 checks passed
@bboe bboe deleted the bboe/cc-libbboeos-extern-call branch May 20, 2026 13:59
bboe added a commit that referenced this pull request May 20, 2026
Add memchr/memcmp/memcpy/memmove/memset/strcasecmp/strcat/strchr/
strcmp/strcpy/strdup/strerror/strlen/strncasecmp/strncat/strncmp/
strncpy/strrchr/strstr to the libbboeos pointer table.  Phase 4
clang-built consumers (and future cc.py callers needing a non-builtin
string fn) can now dispatch through [FUNCTION_<NAME>_PTR] instead of
statically linking each body.

cc.py-built programs are unchanged: the builtin path (rep movsb /
repne scasb) still wins for memcpy/memcmp/memset/strlen because the
extern-dispatch path only fires when no builtin matches.

Relocates FUNCTION_POINTER_TABLE from FUNCTION_TABLE + 0x800 to
+ 0xE00 so .libbboeos.text + .rodata (~2.8 KB with all 18 new
bodies pulled in) doesn't overlap the table.  The whole user-space
rebuilds against the new offset on each make_os.sh run, so the
block sorts cleanly alphabetically — strcmp slides from PR #448's
pinned offset 52 into its natural slot at +84.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant