chibicc C Compiler

repository·main·Indexed 11 days ago

https://github.com/rui314/chibicc

A 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.

Tokens
1.7K
Snippets
1
Records
9
Agent score
46%

What's inside chibicc

  1. Overview of chibicc

    main
    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.
  2. Design principles and memory management in chibicc

    main

    chibicc 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 calloc for all heap allocations to ensure memory is zeroed. Notably, it never calls free; 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 Node struct for all AST nodes to avoid the complexity of unions and premature optimization.
  3. How chibicc processes source code

    main

    chibicc is a multi-pass compiler that operates through the following stages:

    1. Tokenize: Converts an input string into a list of tokens.
    2. Preprocess: Takes tokens and produces a new list of macro-expanded tokens by interpreting preprocessor directives.
    3. Parse: A recursive descent parser that constructs Abstract Syntax Trees (AST) from the preprocessed tokens and assigns types to each AST node.
    4. Codegen: A code generator that emits assembly text from the AST nodes.
  4. Contributing to chibicc

    main

    The 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-push to 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.
  5. How chibicc manages the compilation pipeline

    main

    Chibicc acts as a driver that orchestrates several stages of the C compilation process by invoking subprocesses (like as for assembly or ld for linking) or running its internal cc1 logic.

    The Pipeline Stages

    1. Preprocessing: Handles macros (-D, -U), includes (-I, -include), and header expansion. If -E is specified, the process stops here.
    2. Compilation (cc1): Converts C code into assembly. If -S is specified, the process stops here.
    3. Assembly (as): Converts assembly code into object files (.o). If -c is specified, the process stops here.
    4. Linking (ld): Combines object files, libraries (-l), and startup files (like crt1.o) into a final executable or shared library. This is the default behavior if no other flags are provided.
  6. How chibicc handles dependency generation

    main

    Chibicc 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 format make can read.
    • -MD: Writes dependencies to a file named <output_file>.d (or <output_file> if -o is 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 -MT to generate dependency rules for a specific target.
  7. Use chibicc CLI to compile C code

    main

    The chibicc command-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.c

    To specify an output filename:

    chibicc -o my_program main.c

    Common 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., -DDEBUG or -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 c or -x assembler).
    • -fpic: Generate position-independent code.
    • -static: Link with static libraries.
    • -shared: Create a shared library.
    chibicc -o my_program main.c
  8. Supported and unsupported C11 features in chibicc

    main

    chibicc supports almost all mandatory and most optional features of C11, along with some GCC extensions.

    Supported features include:

    • Preprocessor
    • Floating point types: float, double, and long 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, and u8
    • 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
  9. Reference: chibicc command-line options

    main

    The following table lists the supported command-line options for chibicc as implemented in the driver.

    OptionDescription
    -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=VALUE or -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, or none).
    -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 cc1 mode (internal compiler driver mode).