Skip to content

vbxq/tpcpu-cc

Repository files navigation

tpcpu-cc

C cross-compiler for the TPCPU virtual CPU

#pragma tpcpu mem_pow2 24

#include <stdio.h>

int main() {
    printf("Hello, TPCPU!\n");
    return 0;
}
tpcpu-cc build hello.c   # -> hello.bin
tpcpu-cc run hello.c     # compile + run

Installation

Requirements: Rust stable, libclang.

Windows support should work but haven't been tested by us (you would have to install clang/LLVM yourself!)

# Arch Linux
pacman -S clang

# Debian / Ubuntu
apt install libclang-dev

git clone https://github.com/vbxq/tpcpu-cc && cd tpcpu-cc
git submodule update --init --recursive
cargo install --path tpcpu_cc_driver

Targets

tpcpu-cc supports two execution targets with different capabilities:

Standalone Phobos
Runtime Bare-metal TPCPU emulator Phobos Workstation OS
I/O** putchar / getchar only Terminal, files, directories, IPC
fopen / fread** Always returns NULL / 0 Full file I/O via syscalls
Directories Not available tpcpu_fs.h
Process / IPC Not available tpcpu_process.h, phobos.h
Default memory 16 MiB 512 MiB
__PHOBOS__ not defined defined automatically

You can use standalone for quick iteration and programs that only need terminal I/O, and Phobos (OS) when you need a filesystem, command-line arguments, or IPC.

Getting Started

Standalone project

tpcpu-cc new hello
cd hello
make build    # produces main.bin
make run      # build + run in emulator

For multi-file builds, edit the Makefile to include the other source file, use make build and run the emulator separately.
The emulator is located at .tpcpu/bin/tpcpu_emu, in the root of your project folder.
Build cache is in .tpcpu/cache/ (keyed by ASM hash). Clear with rm -rf .tpcpu.

Phobos (OS) project

tpcpu-cc new myapp --target phobos
cd myapp
make install  # compile and copy binary into the Phobos disk image
make phobos   # boot Phobos Workstation
              # then type: myapp

make install uses tpcpu-cc --phobos-bin-path to locate the Phobos bin/ directory automatically.

Commands

tpcpu-cc new <name>                   # scaffold project (standalone)
tpcpu-cc new <name> --target phobos   # scaffold Phobos project
tpcpu-cc build main.c                 # compile to main.bin
tpcpu-cc build a.c b.c --output app.bin
tpcpu-cc build main.c --target phobos
tpcpu-cc run main.c                   # compile + run (single file only)
tpcpu-cc phobos                       # boot Phobos Workstation

Options

Flag Default
--target <t> standalone standalone or phobos
--emit <mode> bin bin, asm (TPCPU assembly), c32 (IR)
-o, --output <file> <first_input>.bin output path
-D <name>[=value] preprocessor define
-I <dir> include search path
--no-libc skip automatic libc
--trom-asm TROM assembler (required for --optimize)
--optimize peephole optimizer (requires --trom-asm)

Makefile targets

Both standalone and phobos projects ship with a Makefile.

Standalone:

make build    # tpcpu-cc build $(SRCS) -> main.bin
make run      # tpcpu-cc run $(SRCS)   (single file only)
make clean    # rm *.bin .tpcpu/

Phobos:

make build    # tpcpu-cc build $(SRCS) --target phobos -> main.bin
make install  # build + copy binary to phobos_workstation/bin/<name>
make phobos   # boot Phobos (tpcpu-cc phobos)
make clean    # rm *.bin .tpcpu/

Pragmas

#pragma tpcpu mem_pow2 <n>        // total memory = 2^n bytes  (5..32)
                                  //   standalone default: 24 (16 MiB)
                                  //   phobos default:     29 (512 MiB)
#pragma tpcpu stacksize <bytes>   // default: 2097152 (2 MiB)
#pragma tpcpu init_fixedprec <n>  // fixed-point precision (0..31, default: 15)

Memory layout:

[code + globals] [stack -->] [<-- heap]
                 ^                    ^
           stack_start          2^mem_pow2

C Subset

All integers and pointers are 32-bit. double and long long are compile errors.

Types: char (1), short (2), int / long / pointer (4), float (4 IEEE 754 soft-float), struct (packed), union, enum

Expressions: arithmetic, bitwise, logical, all assignment forms, ++/--, ternary, casts, & / *, a[i] / a[i][j], . / ->, function pointers, sizeof, comma

Statements: if, while, do, for, switch, break, continue, return

Declarations: static, extern, const, typedef, arrays, structs with designated initializers (in-order), va_list / va_arg, setjmp / longjmp

Inline assembly: __asm__("instruction") or __tpcpu_asm("instruction"), emits verbatim

Not supported: double, long long, VLA, goto, bitfields, out-of-order designated initializers.

Standard Library

Headers live in include/ and are linked automatically.

Available everywhere

Header Provides
<stdio.h> printf / fprintf / sprintf, fopen / fclose / fread / fwrite / fseek, stdin / stdout / stderr
<stdlib.h> malloc / free / realloc / calloc, atoi, strtol, strtof, qsort, rand
<string.h> mem*, str*, strdup
<math.h> sinf, cosf, sqrtf, powf, logf, and all *f variants no double
<ctype.h> isdigit, isalpha, toupper, tolower, ...
<stdarg.h> va_list, va_start, va_arg, va_end
<setjmp.h> setjmp, longjmp

On standalone, fopen always returns NULL. Only stdin / stdout / stderr work. On Phobos, full file I/O is available via syscalls.

Phobos only

Header Provides
<tpcpu_fs.h> Directory operations: tpcpu_mkdir, tpcpu_rmdir, tpcpu_dir_nentries, tpcpu_dir_entry, tpcpu_dir_exists
<tpcpu_process.h> tpcpu_spawn, tpcpu_murder, tpcpu_getpid, tpcpu_ntasks
<tpcpu_time.h> tpcpu_time_millis, tpcpu_time_seconds, tpcpu_time_micros
<tpcpu_term.h> tpcpu_flush_stdout, tpcpu_clear_term
<tpcpu_fg.h> tpcpu_claim_foreground, tpcpu_relinquish_foreground
<phobos.h> struct kmailbox, IPC syscalls (__sys_declare_mailbox, __sys_sendmail, __sys_undeclare_mailbox)

Float

float is IEEE 754 single-precision implemented in software. All float operations compile transparently to __sf_* calls. Literals are converted to bit patterns at compile time.

float x = 1.5f;      // 0x3FC00000 no runtime cost
float y = x * 2.0f;  // lowers to __sf_mul(x, 2.0f)
int n  = (int)x;     // lowers to __sf_f2i(x)

double is a compile error. Use float everywhere.

Lua 5.4

lua-tpcpu (examples/ports/lua54) is a full Lua 5.4.6 port running on Phobos with all 10 standard libraries. It is the primary real-world validation of the compiler.

cd examples/ports/lua54 && make install && make phobos
# in Phobos: lua -i -v

Libc and include headers

The C standard library lives in libc/ (.c source files compiled as part of each program) and include/ (.h headers).

When building from source (cargo install --path tpcpu_cc_driver from the repo root), the compiler finds these directories relative to the workspace root automatically.

When installed as a standalone binary, the compiler embeds libc/, include/, and the required vendor files at compile time and extracts them to the platform data directory on first use:

Platform Default location
Linux $XDG_DATA_HOME/tpcpu-cc -> ~/.local/share/tpcpu-cc
macOS ~/Library/Application Support/tpcpu-cc
Windows %LOCALAPPDATA%\tpcpu-cc

Windows and macOS support haven't been tested yet.

To modify the libc (e.g. add a new function), edit the files in libc/ or include/ in the repository, then reinstall with cargo install --path tpcpu_cc_driver. The updated files are re-embedded into the binary.

Environment variable overrides (take precedence over auto-detection):

Variable Effect
TPCPU_CC_LIBC=<path> Use this directory as the libc source root
TPCPU_CC_INCLUDE=<path> Use this directory as the include root
TPCPU_CC_DATA_DIR=<path> Override the entire data directory

Testing

cargo test

Architecture

flowchart TD
    subgraph Input
        C[C source files]
        P[pragma extraction]
    end
    subgraph Frontend
        CL[clang / libclang\nAST parsing]
        LO[c32_lowering\nAST -> C32 IR]
    end
    subgraph IR["C32 IR"]
        VAL[validation]
        MULTI[multi-file\nreconcile + merge]
    end
    subgraph Backend
        BE[c32_backend_tpcpu\nTPCPU assembly]
        RT[c32_runtime_tpcpu_min\nlibc ASM bundling]
    end
    subgraph Assemble
        BST[bootstrap assembler\ndefault]
        TROM[as.trom\n--trom-asm]
    end
    subgraph Targets
        SA[Standalone]
        PH[Phobos]
    end
    C --> P --> CL --> LO --> VAL --> MULTI --> BE --> RT
    RT --> BST & TROM
    BST & TROM --> SA & PH
Loading

License

Public domain. vendor/TPCPU is public domain as well, examples/ports/lua54 is MIT.

About

Public domain C cross-compiler targeting the TPCPU virtual CPU and the Phobos Operating System.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors