an ultra-fast, lightweight c++ compiler for x86_64 linux
pure c11 implementation • zero llvm bloat • sub-millisecond compilation
winds is a small, focused c++ compiler built from the ground up in strict c11. it targets x86_64 linux with direct native code emission, skipping multi-gigabyte backends to turn c++ into assembly in a fraction of a millisecond.
designed for rapid iteration, modular systems programming, and instant feedback, winds gives you real object-oriented c++ without the waiting time.
get up and running in seconds:
# build winds with make
make -j4
# or build with cmake
mkdir -p build && cd build && cmake .. && cmake --build .
# run a c++ file directly like a script
./bin/winds -run tests/01_basics.cpp
# or compile to an executable binary
./bin/winds tests/03_classes.cpp -o app
./appbenchmarks measured on x86_64 linux across 20 iterations:
| metric | clang++ (llvm 22.1) | winds | advantage |
|---|---|---|---|
frontend + codegen (-s) |
11.89 ms ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ |
0.53 ms ▰ |
~22.3x faster |
| compiler footprint | ~196 mb ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ |
267 kb ▰ |
~751x lighter |
| runtime dependencies | libllvm, libclang-cpp, libc++ | glibc only | 100% self-contained |
| memory teardown | recursive reference counting | contiguous bump arena | instant constant-time exit |
winds end-to-end compilation, assembly, and linking: 14.49 ms minimum, 15.85 ms average.
compiling <iostream>, <string>, <vector>, <utility>, <algorithm>, <cstdint>, <cassert>:
| compiler | compile time (-s) |
advantage |
|---|---|---|
| clang++ (system libc++) | 173.70 ms ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ |
baseline |
| winds (self-contained std) | 2.55 ms ▰ |
~68.0x faster |
modern compilers often feel sluggish because they carry decades of legacy intermediate representation transformations, heavy class hierarchies, and massive dynamic libraries. winds takes a simpler, more deliberate path:
- bump arena allocation: all abstract syntax tree nodes, symbol entries, and intermediate instructions live in contiguous 128 kb blocks. memory allocations take a single pointer bump with zero lock contention, and process cleanup takes one single free call.
- linear scan register allocator: instead of costly graph coloring algorithms with complex spill-reloading passes, winds runs a fast linear scan over live intervals with loop extension and automatic callee-saved register tracking.
- zero llvm dependencies: no massive shared libraries to load into memory on each invocation. the entire compiler binary is only 255 kb.
- direct native code emission: the intermediate representation lowers straight to system v amd64 assembly without intermediate serialization steps.
winds transforms c++ into native machine code through a streamlined multi-stage pipeline:
source code (.cpp)
│
▼
lexer & string intern fast tokenization, fnv-1a identifier pool
│
▼
recursive descent parser operator-precedence expression grammar
│
▼
abstract syntax tree compact node structures in arena memory
│
▼
semantic analyzer type checking, namespaces, method resolution
│
▼
three-address code ir linearized instruction stream
│
▼
optimizer passes constant folding, copy prop, cfg simplification
│
▼
linear scan regalloc physical register mapping & loop extension
│
▼
native codegen system v amd64 assembly emission (.s)
│
▼
assembler & linker gnu as and gcc/ld executable linking (.out)
winds supports core object-oriented c++ features out of the box:
#include <stdio.h>
class counter {
private:
int count;
public:
counter(int start) {
this->count = start;
}
~counter() {
printf("counter finished at %d
", this->count);
}
void step(int delta) {
this->count = this->count + delta;
}
int value() {
return this->count;
}
};
int main() {
counter c(10);
c.step(5);
printf("current: %d
", c.value());
return 0;
}make your c++ code runnable without a separate build step:
#!/usr/bin/env winds -run
#include <stdio.h>
int main(int argc, char **argv) {
printf("executed directly via winds script mode!
");
for (int i = 1; i < argc; i = i + 1) {
printf("argument %d: %s
", i, argv[i]);
}
return 0;
}void swap(int &first, int &second) {
int temp = first;
first = second;
second = temp;
}explore the underlying compiler components by expanding the sections below:
templates & bespoke standard library
- on-demand template class monomorphization (
template <typename t> class name { ... };) - variadic templates and parameter pack expansion (
template <typename... args>) - recursive template monomorphization and pack unrolling
- standard
<tuple>(std::tuple,std::make_tuple) with contiguous stack layout - self-contained
<iostream>with stream chaining (std::cout << val << std::endl;) - heap-managed
<string>with dynamic resizing, concatenation, and streaming - dynamic
<vector<t>>container withpush_back,pop_back, and array indexing - generic
<utility>(std::pair,std::make_pair,std::swap) and<algorithm>(std::min,std::max,std::sort) - zero external compiler runtime dependencies
function pointers & pointers to members
- first-class function pointer declarations (
ret (*fp)(args)) and indirect calls - function pointer arrays, lookup tables, and callback dispatch architectures
- pointers to class data members (
type class::*ptr) and member dereference operators (.*,->*) - pointers to member functions (
ret (class::*mfp)(args)) and indirect method invocation
preprocessor & macro expansion
- parameterized macros (
#define fn(x, y) ...) - macro argument stringification (
#param) - token pasting and concatenation (
##) - multiline macro continuation via backslash (
\) - macro undefinition via
#undef - preprocessor conditional branches (
#if,#elif,#else,#endif,#ifdef,#ifndef)
object-oriented programming & memory lifecycle
classandstructdeclarations with member offset alignments- access modifiers:
public,private,protected - stack constructors and automatic destructors on scope exit
- dynamic heap allocation with
newanddelete - member methods with implicit and explicit
thispointer resolution - out-of-line method definitions (
classname::method(...)) - pass-by-reference (
type&) and pass-by-pointer (type*) - parameter-count and type-aware function and method overloading
system v amd64 calling convention compliance
- full support for functions with 7 or more arguments: the first six arguments travel in registers (
%rdi,%rsi,%rdx,%rcx,%r8,%r9), while arguments 7 and beyond are passed on the stack frame (16(%rbp),24(%rbp), etc.) - 16-byte caller stack alignment (
subq/addq) for crash-free compatibility with glibc vector and variadic functions - callee-saved register preservation (
%rbx,%r12through%r15) across deep recursion and call sites
optimizer passes (-o1, -o2)
- control-flow graph simplification: branch inversion over jumps, identical branch target folding, consecutive label deduplication, and dead block elimination
- constant propagation & folding: evaluates compile-time arithmetic and prunes conditional branches
- copy propagation: removes redundant register assignments and assignment chains
- algebraic simplification: applies mathematical identities (
x + 0,x * 0,x * 1,x - x,x ^ x,x & 0,x == x) - unreachable block removal: computes basic block reachability and discards code after returns or unconditional branches
developer diagnostics & error reporting
- visual diagnostics with line gutters (
|) and precise column underline markers (^^^^^) - actionable help notes suggesting missing semicolons, delimiters, or include flags
- levenshtein distance suggestions for typos in variable names and class members (e.g. suggesting
counterwhen you typecountr) - warning controls:
-wall,-wextrafor unused variable detection, and-werrorto treat warnings as hard build errors - colored output support via
-fdiagnostics-color=always|never|auto
build system integration & scripting
- direct script execution via
-runwith argument forwarding and exit code propagation - automatic makefile dependency generation via
-mmd,-mp, and-mf <file> - header include path management with
-i <dir> - single-inclusion protection with
#pragma onceand#ifndefguards - cross-compilation toolchain dispatching via
--target=<triple>,--sysroot=<path>, and--cross-prefix=<prefix>
command-line reference
| flag | description |
|---|---|
-o <file> |
write output binary or object file to <file> |
-e |
run preprocessor only and output to stdout or <file> |
-s |
compile only to assembly (.s) |
-c |
compile and assemble without linking (.o) |
-run |
compile and execute directly as a script |
-mmd |
generate makefile dependency file (.d) |
-mp |
add phony targets for header dependencies |
-mf <file> |
write dependency output to specified <file> |
-wall, -wextra |
enable compiler warnings (such as unused variables) |
-werror |
treat warnings as hard compilation errors |
-o0, -o1, -o2 |
set optimization level (default: -o1) |
-i <dir> |
add directory to header search path |
-Dname[=value], -Uname |
define or undefine a preprocessor macro |
-L<dir>, -l<name>, -Wl,... |
pass library search and linker options |
--target=<triple> |
specify target architecture (default: x86_64-linux-gnu) |
--sysroot=<path> |
specify system root directory for headers and libraries |
--cross-prefix=<p> |
specify cross-toolchain binary prefix |
--print-target-triple |
display target triple and exit |
--emit-ast |
dump abstract syntax tree to stdout |
--emit-ir |
dump three-address intermediate code to stdout |
-v, --verbose |
print stage execution details and timing |
--help |
print help summary |
--version |
print compiler version |
- gcc or clang (to build the compiler binary itself)
- standard gnu assembler (
as) and linker (gccorld) - cmake 3.16+ (optional, standard make is supported)
# build binary to bin/winds
make -j4
# run automated test suites
make test
# run benchmark against clang++
make benchmark
# install binary to ~/.local/bin
make install# configure and build
mkdir -p build && cd build && cmake .. && cmake --build .
# execute all test cases via ctest
ctest --test-dir build --output-on-failurewinds includes 29 automated test suites covering syntax, semantics, standard library, and code generation:
01_basics.cpp— variables, arithmetic precedence, loops, and branches02_functions.cpp— function overloading, pass-by-reference, and recursion03_classes.cpp— classes, access modifiers, member methods, andthis04_ctor_dtor.cpp— constructors, destructors,new, anddelete05_namespace.cpp— namespaces, nested scopes, andusing namespace06_headers.cpp—#include,#pragma once, and guard macros07_optimizations.cpp— constant folding, copy propagation, algebraic simplification, and control-flow jumps08_diagnostics.sh— caret underline diagnostics and typo suggestions09_abi.cpp— 7+ argument passing, callee-saved preservation, and 16-byte stack alignment10_dependencies.sh—-mmd,-mp, and-mfdependency rules11_warnings_and_run.sh—-wallwarnings,-werrorescalation, and-runexecution12_operator_overload.cpp— member and stream operator overloading (<<,>>,[],+,==)13_typedef.cpp— type aliases viatypedefandusing14_templates.cpp— template class monomorphization (box<t>,pair<t1, t2>)15_std_library.cpp— self-contained standard library containers and streams16_function_pointers.cpp— function pointers, indirect calls, and callback dispatch tables17_pointers_to_members.cpp— pointers to data members and member functions (.*,->*)18_macros.cpp— parameterized macros, stringification (#), token pasting (##),#undef,#if/#elif19_variadic_templates.cpp— variadic templates, parameter packs, recursive monomorphization, and standard<tuple>20_multifile.sh— multiple translation units, command-line macros, external objects, and c abi linking21_c_compat.c— c linkage,doloops, conditional/comma expressions, and curated c headers22_multidim_arrays.c— multidimensional arrays, nested initializers, and row pointer decay23_unions_and_enums.c— cunionlayout, anonymous/standaloneenumdefinitions, andregister/autospecifiers24_branch_fusion.c— fused compare-and-branch codegen and algebraic strength reduction25_preprocessor_e.sh—-etoken emission, default output naming, and toolchain flags26_varargs.c— system v amd64 variable argument abi (va_list,va_start,va_arg,va_copy,va_end)27_floating.c— native floating-point literals, arithmetic, conversions, comparisons, and system v amd64 calls28_struct_copy.c— whole-struct assignment for locals, globals, members, and returned values29_cpp_compat.cpp— anonymous namespaces, placement new, named casts, qualified types, and legacy c++ syntax
make corpus-test builds unchanged, pinned releases of full zlib, cJSON, and SQLite, links them to small gcc-built c harnesses, and compiles pugixml without exceptions, RTTI, or the system c++ standard library. Set ZLIB_SOURCE, CJSON_SOURCE, SQLITE_SOURCE, and PUGIXML_SOURCE to verified source directories for an offline run. CMake exposes the same gate with -DWINDS_ENABLE_CORPUS_TESTS=ON.
- phase 1: script execution mode (
-run), shebang support, makefile dependency tracking (-mmd,-mp,-mf), warning controls (-wall,-wextra,-werror), colored diagnostics - phase 2: operator overloading, type aliases (
typedef,using), template class monomorphization, 12 self-contained standard library headers (<iostream>,<string>,<vector>, etc.) - phase 3: function pointers, pointers to members, parameterized preprocessor macros, variadic templates and standard tuple
- phase 4a: multi-file builds, external object/library linking, c linkage, curated libc headers, and the first pinned real-world zlib corpus gate
- phase 4b: c foundation expansion (unions, standalone enums, multidimensional arrays, varargs abi, preprocessing mode)
- phase 4c: complete the corpus-driven c foundation required by full zlib, cjson, and sqlite builds
- phase 4d: compile pugixml without exceptions, rtti, or the system c++ standard library
distributed under the mit license.
