Files
tms-c-compiler/README.md
T

5.1 KiB
Raw Blame History

tms-c-compiler

A modern C toolchain for the DEC VT1200 / TI TMS34010, built as a small fork of upstream LLVM.

Status: M0. Clang understands the tms34010-unknown-none target, the TI data model, and bit-addressed pointers. There is no machine-code backend yet: M0 stops at LLVM IR. The backend, TI ABI, ROM calls, Xlib and real clients are M1–M5 and are separate plans (see the design spec).

Repositories

The compiler fork is the canonical source for LLVM changes. patches/llvm here is a lightweight mirror used by scripts/build-llvm.sh, so the project can be built without cloning 3 GB of LLVM; keep it in sync with the fork's tms34010 branch.

What M0 provides

  • clang --target=tms34010-unknown-none: 32-bit bit-addressed pointers, 8-bit signed char, 16-bit short, 32-bit int/long, packed structs, sizeof(struct { char; int; void*; }) == 9.
  • Pointer arithmetic scaled by 8; pointer difference divided by 8 (char * → /8, int * → /32), while (int)(p+1) - (int)p stays an integer subtraction.
  • tools/tms-bitaddr: GEP --scale and late --normalize passes, including constant-expression GEPs.
  • scripts/tms-clang: the M0 pipeline clang -O0 → tms-bitaddr --scale → opt -O2 → tms-bitaddr --normalize.
  • Lit tests for the triple, data model and pointer difference; an integration test over a real Xlib client IR.

Repository layout

build/llvm-src/          local fork (ignored; created by build-llvm.sh or manually)
build/llvm-build/        Ninja build of the fork (ignored)
build/llvm-clean*/       clean CI clone/build (ignored)
patches/llvm/            the complete fork delta against llvmorg-23.1.5
tools/tms-bitaddr/       GEP scale/normalize tool
scripts/tms-clang        M0 pipeline wrapper
scripts/tests/m0/        M0 integration tests
scripts/build-llvm.sh    clean clone + patches + build
scripts/fetch-vt1200.sh  fetch the VT1200 RE tree at its pinned commit
spike/                   measurement corpus and reports
symbols/                 per-ROM import tables (v2.2 subset)
vendor/                  fetched assets and LLVM sources (ignored)
docs/                    design and plans

Prerequisites

cmake, ninja-build, ccache, a C++17 host compiler (GCC 14 is used here), Python 3, and about 20 GB of disk for the LLVM source and build. On Debian:

sudo apt-get install -y cmake ninja-build ccache

Fetch the VT1200 assets

The compiler contract is checked against the VT1200 tree (TI hello.s, the Xlib call sequence, as34, dis34, SDKs, manuals). It is not vendored:

./scripts/fetch-vt1200.sh          # -> vendor/vt1200, pinned 17dfd24...

Build the pinned fork

./scripts/build-llvm.sh
# binaries: build/llvm-clean-build/bin/{clang,opt,llvm-config,FileCheck,llvm-lit}

The script clones llvmorg-23.1.5, applies patches/llvm/*.patch, and builds clang/opt with X86 (host) and TMS34010. A first build takes roughly 20–40 minutes; rebuilds are incremental.

For development, build/llvm-src is the working fork and build/llvm-build is its build tree. scripts/export-patches.sh regenerates the committed patch series with git diff (including new files via git add -N).

Build the M0 tool and run the tests

LLVM_CONFIG=$PWD/build/llvm-clean-build/bin/llvm-config \
  tools/tms-bitaddr/build.sh

TMS_CLANG=$PWD/build/llvm-clean-build/bin/clang \
TMS_OPT=$PWD/build/llvm-clean-build/bin/opt \
TMS_BITADDR=$PWD/tools/tms-bitaddr/tms-bitaddr \
  ./scripts/tests/m0/run.sh
# -> M0 pipeline: PASS

build/llvm-clean-build/bin/llvm-lit -v \
  build/llvm-clean-build/tools/clang/test --filter='TMS34010'
# -> 3 passed

Use

scripts/tms-clang -O2 -I spike -o /tmp/client.ll spike/xclient.c

The output is LLVM IR in which every address is a bit address. It is not assembly or an object file; llc support is M1.

What is deliberately missing

  • TMS34010 instruction selection, registers, frame lowering, asm/MC output.
  • The TI ABI: A8 return, A13/A14/A15 dual stack, RETS 2, FS1 = 32.
  • ROM import symbols beyond the subset in symbols/.
  • Xlib headers/clients on the target, memcpy/byval/varargs/float/bitfield lowering, native COFF.

These are M1–M5 in the design spec, written as separate plans because their tasks depend on what M0/M1 measure.