DEV Community

Ignacio Peña
Ignacio Peña

Posted on

Tempo v1.0.0: We Built a Systems Language That Actually Replaces C

TL;DR

After building a real-time OS and hitting the limitations of C, we created Tempo - a systems programming language with memory safety, deterministic execution, and zero overhead. It's not a toy - we're using it to build AtomicOS.

The Problem

Every few months, someone announces a "C killer" that turns out to be either:
Too high-level for real systems programming
Too complex (looking at you, Rust)
Missing critical features like inline assembly
Just... not actually replacing C
We were building AtomicOS, a deterministic real-time security OS, and kept running into C's fundamental issues:
Memory unsafety is baked into the language
Undefined behavior everywhere
No way to guarantee execution time
The preprocessor is a footgun factory

Enter Tempo v1.0.0

Instead of complaining, we built the language we needed. Here's what makes Tempo different:

1. Structs That Actually Work for Systems Programming

struct DMADescriptor @packed @align(16) {
buffer: raw_ptr<int8>,
size: int32,
flags: int32,
next: ptr<DMADescriptor>
}

Real memory layout control. No hidden padding. No surprises.

2. A Pointer System That Makes Sense

// Safe by default - bounds checked at compile time
function process_buffer(data: ptr<int8, 256>) {
for i in 0..256 {
data[i] = transform(data[i]); // Can't overflow!
}
}
// Explicit unsafe when you need it
function mmio_read(addr: int32) -> int32 {
let p: raw_ptr<int32> = addr as raw_ptr<int32>;
return *p;
}

3. Inline Assembly as a First-Class Feature

`@interrupt
function timer_handler() {
asm volatile("push eax");
asm volatile("push ebx");

tick_count = tick_count + 1;

// Send EOI to PIC
outb(0x20, 0x20);

asm volatile("pop ebx");
asm volatile("pop eax");
asm volatile("iret");
Enter fullscreen mode Exit fullscreen mode

}`
No more writing separate assembly files and hoping your calling conventions match!

4. Deterministic by Design

Every loop must be bounded. Every operation has known timing:
function process_packets(packets: ptr<Packet, 64>) @wcet(6400) {
for i in 0..64 @wcet(100) {
if packets[i].valid {
handle_packet(&packets[i]);
}
}
}

The compiler proves this function completes in 6400 cycles or less.

Real-World Usage

This isn't theoretical. We're building an entire OS with Tempo:
Boot loader ✅
Interrupt handlers ✅
Memory management ✅
Process scheduler ✅
Device drivers ✅
Network stack 🚧
Check out our kernel written entirely in Tempo: kernel_in_tempo.tempo

Performance

Tempo compiles to the same assembly you'd write by hand:
function add(a: int32, b: int32) -> int32 {
return a + b;
}

Compiles to:
add:
mov eax, [esp+4]
add eax, [esp+8]
ret

No runtime. No hidden allocations. No surprises.
Getting Started

git clone https://github.com/ipenas-cl/AtomicOS.git
cd AtomicOS
make build/tempo_compiler
# Write your first Tempo program
echo 'function main() -> int32 { return 42; }' > hello.tempo
./build/tempo_compiler hello.tempo hello.s
Enter fullscreen mode Exit fullscreen mode

The Future

Tempo v1.0.0 is just the beginning. We're working on:
Generic types (without the complexity)
Async/await for interrupt-driven I/O
Formal verification integration
ARM and RISC-V backends

Join Us!

We need contributors! Whether you're interested in:
Compiler development
Language design

Systems programming
Documentation
Building cool stuff with Tempo
There's a place for you in the project.
🌐 Website: https://ipenas-cl.github.io/AtomicOS/tempo/
💻 GitHub: https://github.com/ipenas-cl/AtomicOS
💬 Discussions: https://github.com/ipenas-cl/AtomicOS/discussions
Let's build the future of systems programming together!

tempo #systemsprogramming #memorysafety #rustlang #clang #opensource

Top comments (0)