chibicc C Compiler
repository·main·Indexed 11 days ago
https://github.com/rui314/chibiccA small, multi-pass C compiler implementing most C11 features, designed as a pedagogical tool for learning compiler construction. It follows an incremental approach to implement features like a preprocessor, recursive descent parsing, and code generation. Despite being a toy compiler, it can compile real-world programs such as Git, SQLite, and libpng. It supports standard GCC-like flags for preprocessing, compilation, assembly, and linking.
What's inside chibicc
- chibicc is a small C compiler that implements most C11 features. It is designed as a reference implementation for a book on C compiler construction and low-level programming. Despite being a 'toy compiler', it is capable of compiling real-world programs like Git, SQLite, and libpng. It follows an incremental approach where each commit in the repository corresponds to a specific section of the book, implementing one feature at a time.
Design principles and memory management in chibicc
mainchibicc prioritizes simplicity and readability over performance and memory efficiency. Key design choices include:
- Simplicity over Abstraction: Uses straightforward, sometimes duplicative code (like in the recursive descent parser) to remain readable for first-time readers.
- Memory Management: Uses
callocfor all heap allocations to ensure memory is zeroed. Notably, it never callsfree; memory is only released when the process exits. This is a deliberate choice for short-lived programs like compilers. - Data Structures: Uses simple structures like linked lists for sets and a single large
Nodestruct for all AST nodes to avoid the complexity of unions and premature optimization.
How chibicc processes source code
mainchibicc is a multi-pass compiler that operates through the following stages:
- Tokenize: Converts an input string into a list of tokens.
- Preprocess: Takes tokens and produces a new list of macro-expanded tokens by interpreting preprocessor directives.
- Parse: A recursive descent parser that constructs Abstract Syntax Trees (AST) from the preprocessed tokens and assigns types to each AST node.
- Codegen: A code generator that emits assembly text from the AST nodes.
Contributing to chibicc
mainThe project follows an unusual contribution model to maintain the integrity of the book's incremental learning path:
- No Pull Requests: The maintainer does not accept direct pull requests. Instead, bugs are fixed by rewriting the commit history to incorporate the fix at the original point of introduction.
- History Rewriting: The maintainer may occasionally
force-pushto the repository to rewrite history. If you have local commits based on the repository, you will need to rebase them manually after a force-push.
How chibicc manages the compilation pipeline
mainChibicc acts as a driver that orchestrates several stages of the C compilation process by invoking subprocesses (like
asfor assembly orldfor linking) or running its internalcc1logic.The Pipeline Stages
- Preprocessing: Handles macros (
-D,-U), includes (-I,-include), and header expansion. If-Eis specified, the process stops here. - Compilation (
cc1): Converts C code into assembly. If-Sis specified, the process stops here. - Assembly (
as): Converts assembly code into object files (.o). If-cis specified, the process stops here. - Linking (
ld): Combines object files, libraries (-l), and startup files (likecrt1.o) into a final executable or shared library. This is the default behavior if no other flags are provided.
- Preprocessing: Handles macros (
How chibicc handles dependency generation
mainChibicc supports dependency generation similar to GCC, which is useful for automating builds with
make.-M: Writes a list of input files to stdout in a formatmakecan read.-MD: Writes dependencies to a file named<output_file>.d(or<output_file>if-ois used).-MMD: Similar to-MD, but skips dependencies found in standard system include paths.-MP: Adds extra rules to the dependency file to prevent issues if a header file is deleted.-MF <file>: Specifies a custom filename for the dependency output.-MT <target>: Specifies the target name used in the dependency file.-MQ <file>: Used with-MTto generate dependency rules for a specific target.
Use chibicc CLI to compile C code
mainThe
chibicccommand-line interface is used to compile C source files into various formats including object files, assembly, or executable binaries. It supports standard GCC-like flags for preprocessing, compilation, assembly, and linking.Basic Usage
To compile a C file into an executable (default behavior):
chibicc main.cTo specify an output filename:
chibicc -o my_program main.cCommon Compilation Flags
-c: Compile and assemble, but do not link. Produces an object file (.o).-S: Stop after the compilation stage. Produces an assembly file (.s).-E: Stop after the preprocessing stage. Prints preprocessed tokens to stdout.-D <macro>: Define a macro (e.g.,-DDEBUGor-DVERSION=1).-U <macro>: Undefine a macro.-I <path>: Add a directory to the include search path.-include <file>: Force include a specific file.-x <type>: Force the input file type (e.g.,-x cor-x assembler).-fpic: Generate position-independent code.-static: Link with static libraries.-shared: Create a shared library.
chibicc -o my_program main.cSupported and unsupported C11 features in chibicc
mainchibicc supports almost all mandatory and most optional features of C11, along with some GCC extensions.
Supported features include:
- Preprocessor
- Floating point types:
float,double, andlong double(x87 80-bit) - Bit-fields
alloca()- Variable-length arrays
- Compound literals
- Thread-local variables
- Atomic variables
- Common symbols
- Designated initializers
- String literals:
L,u,U, andu8 - Functions taking/returning structs (per x86-64 SystemV ABI)
Unsupported features:
- Complex numbers
- K&R-style function prototypes
- GCC-style inline assembly
- Digraphs and trigraphs
Reference: chibicc command-line options
mainThe following table lists the supported command-line options for
chibiccas implemented in the driver.Option Description -o <path>Specify the output file path. -SGenerate assembly code. -cGenerate object files (compile and assemble, no link). -EPreprocess only (output tokens to stdout). -D <macro>Define a macro. Supports -DNAME=VALUEor-DNAME.-U <macro>Undefine a macro. -I <path>Add directory to include search path. -include <file>Force include a specific file. -x <type>Force input file type ( c,assembler, ornone).-M,-MD,-MMDDependency generation flags (for Makefiles). -MF <file>Specify the dependency file output path. -MT <file>Specify the target name in dependency files. -MPGenerate extra rules for dependency files. -MQ <file>Generate dependency rules for a specific target. -L <path>Add directory to linker search path (passed to ld).-l<lib>Link against a library (e.g., -lm).-Wl,<arg>Pass arguments directly to the linker. -staticLink with static libraries. -sharedCreate a shared library. -fcommon/-fno-commonControl common symbol handling. -fpic/-fPICGenerate position-independent code. -###Debug mode: dump subprocess command lines to stderr. -cc1Run in cc1mode (internal compiler driver mode).