scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 04a8d973223717c101ce4aff9934632f7f88803b
parent 147dad103e0f63f931618d5c68161d84c70192c1
Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
Date:   Thu, 19 Mar 2026 19:10:07 +0100

doc: Add documentation for cc1 and cc2

While they are not expected to be used directly having
them documented helps in the development process. Also,
improve the documentation for the scc-cc driver.

Diffstat:
Mdoc/man1/Makefile | 2++
Mdoc/man1/scc-cc.man | 610+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Adoc/man1/scc-cc1.man | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adoc/man1/scc-cc2.man | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 716 insertions(+), 119 deletions(-)

diff --git a/doc/man1/Makefile b/doc/man1/Makefile @@ -8,6 +8,8 @@ PAGES =\ scc-addr2line.1\ scc-ar.1\ scc-cc.1\ + scc-cc1.1\ + scc-cc2.1\ scc-cpp.1\ scc-nm.1\ scc-objdump.1\ diff --git a/doc/man1/scc-cc.man b/doc/man1/scc-cc.man @@ -1,164 +1,536 @@ .TH SCC-CC 1 scc\-VERSION .SH NAME -scc-cc \- simple C compiler with magic +scc-cc \- C compiler driver .SH SYNOPSIS .B scc-cc -.RB [ \-cdgkqQsw ] -.RB [ \-M | \-E | \-S ] -.RB [ \-D -.IR def[=val] ] ... -.RB [ \-I -.IR dir ] ... -.RB [ \-L -.IR dir ] ... -.RB [ \-U -.IR def ] ... -.RB [ \-l -.IR lib ] -.RB [ \-a -.IR arch ] -.RB [ \-o +.RB [ \-c | \-S | \-E ] +.RB [ \-std= standard ] +.br +.RB " " [ \-g ] +.RB [ \-Olevel ] +.br +.RB " " [ \-Wwarn ...] +.br +.RB " " [ \-Idir ...] +.RB [ \-Ldir ...] +.br +.RB " " [ \-Dmacro [ =defn ]...] +.RB [ \-Umacro ] +.br +.RB " " [ \-foption ...] +.RB [ \-mmachine-option ...] +.br +.RB " " [ \-o .IR outfile ] -.RB [ \-O -.IR level ] +.RB [ \-l lib ]... +.br +.RB " " [ \-Msdk ] +.RB [ \-q | \-Q ] +.br +.RB " " [ \-a +.IR arch ] .RB [ \-t .IR sys ] -.RB sourcefile ... +.br +.RB " " +.IR infile ... .SH DESCRIPTION -.B scc -is a simple C compiler which takes several -.I sourcefiles -and compiles them to an executable. The default output file is -.B a.out, -which can be changed by defining some -.I outfile. -.SH OPTIONS +.B scc-cc +is the compiler driver of the scc toolchain. +It accepts C source files, intermediate representation files, +assembler source files, object files, and archive libraries, +and orchestrates the tools required to turn them into an +executable or object file. +.PP +For each C source file +.RB ( .c ), +.B scc-cc +runs a pipeline of sub-processes connected by pipes: +the frontend +.B cc1 +compiles the source to scc IR, the backend +.B cc2 +lowers the IR to assembly (or to QBE IR when QBE mode is active), +the optional +.B qbe +stage compiles QBE IR to native assembly, +and finally the assembler +.B as +produces an object file. +When linking is not suppressed, the resulting object files are +passed to the linker +.B ld +to produce the final executable. +.PP +Files with other extensions are handled as follows: .TP -.B \-c -Do not run the linker. +.B .ir +Passed directly to +.BR cc2 , +skipping the +.B cc1 +stage. .TP -.B \-d -Do output internal tool messages. +.B .qbe +Passed directly to +.BR qbe , +skipping +.B cc1 +and +.BR cc2 . .TP -.BI \-D " define[=value]" -Specify a -.I define -for the preprocessor. +.B .s +Passed directly to the assembler, skipping all compiler stages. +.TP +.B .o ", " .a +Passed directly to the linker. +.SH OPTIONS +.SS Compilation Control +.TP +.B \-c +Compile and assemble, but do not link. +One object file is produced for each input source file. +If +.B \-o +is also specified, only a single input file is permitted. .TP .B \-E -Stop after the preprocessing stage, do not run the compiler and output the then -resulting source. +Stop after preprocessing. +The preprocessed source is written to standard output, +or to +.I outfile +if +.B \-o +is given. +Cannot be combined with +.B \-M +or the stop flags +.BR \-S , +.BR \-k . .TP -.B \-g -Do generate debug information. +.B \-M +Emit a +.BR make (1) +dependency rule describing the +.B #include +dependencies of each source file, then exit. +No compilation is performed. +Cannot be combined with +.BR \-E . .TP -.BI \-I " directory" -Define a include -.I directory -to get header files from. This directory is searched for before standard -include directories. +.B \-S +Stop after compilation; do not assemble. +Assembly source is written to a file with the same base name as +the input and the suffix +.BR .s . +.SS Preprocessor .TP -.B \-k -Do keep temporary objects. +.BI \-D macro [ =value ] +Define the preprocessor macro +.I macro +with an optional replacement text +.IR value . +If +.I value +is omitted, the macro is defined with the value +.BR 1 . +This option may be repeated to define multiple macros. .TP -.BI \-l " library" -Link against this -.I library. +.BI \-U macro +Undefine the preprocessor macro +.IR macro . +This option may be repeated. .TP -.BI \-L " directory" -Define a library -.I directory -to resolve dependencies from. This directory is used before the standard -paths. +.BI \-I dir +Prepend +.I dir +to the list of directories searched for header files. +User-specified directories are searched before system include +directories. +This option may be repeated. +.SS Optimisation .TP -.BI \-a " architecture" -Define the -.I architecture -to compile for (i.e. amd64, i386 ...). +.BI \-O level +Specify the optimisation level. +This option is accepted for compatibility with other compiler +driver interfaces but is otherwise ignored; +.B scc-cc +does not perform its own optimisation passes. +.SS Linker .TP -.B \-M -Output a rule for -.B make -describing the dependencies of the main source file. +.BI \-L dir +Add +.I dir +to the list of directories searched for libraries. +.TP +.BI \-l lib +Link against the library +.IR lib . +.SS Output .TP .BI \-o " outfile" -Define the name of the -.I outfile. +Place the output into +.IR outfile . +When compiling and linking, the default output name is +.BR a.out . +When compiling to an object file +.RB ( \-c ), +the default output name is derived from the input file name. +.SS Debugging and Symbols +.TP +.B \-g +Generate debugging information. +This flag is forwarded to the assembler and linker. .TP -.BI \-O " level" -Define the optimisation -.I level -to compile with. (This is a stub for compatibility reasons.) +.B \-s +Strip all symbol table and relocation information from the output +executable. +This flag is forwarded to the linker. +.SS Warnings +.TP +.B \-w +Enable warning messages for dubious constructs. +The flag is forwarded to +.BR cc1 . +.TP +.BI \-W param +Enable warnings. +The parameter +.I param +is ignored; the effect is the same as +.BR \-w . +Accepted for compatibility with other compiler driver interfaces. +.SS Target +.TP +.BI \-a " arch" +Select the target architecture. +Overrides the +.B ARCH +environment variable. +.TP +.BI \-t " sys" +Select the target operating system. +Overrides the +.B SYS +environment variable. +.SS Driver Behaviour +.TP +.B \-d +Enable verbose driver output. +The exact command line executed for each sub-process is printed +to standard error before that process is started. +.TP +.B \-k +Keep intermediate files. +When this flag is set, +.B scc-cc +saves the IR, QBE IR, and assembler output produced during +compilation alongside the object file, +using the base name of the input file with the suffixes +.BR .ir , +.BR .qbe , +and +.BR .s , +respectively. +The final object file is also kept even when linking. .TP .B \-q -Do not use -.I QBE. +Disable QBE mode. +.B cc2 +produces native assembly directly, without invoking +.BR qbe (1). .TP .B \-Q -Do use the -.I QBE. -.TP -.B \-s -Strip all symbol tables and relocation information from the resulting executable. +Enable QBE mode (default). +.B cc2 +produces QBE IR, which is then compiled to native assembly by +.BR qbe (1). +.SS Compatibility Options +The following options are accepted and silently ignored for +compatibility with other compiler driver interfaces: +.BR \-static , +.BR \-dynamic , +.BR \-pedantic , +.BR \-ansi , +any option beginning with +.BR \-std= , +any +.BI \-f option +and any +.BI \-m option. +.SH COMPILATION PIPELINE +For each C source file, +.B scc-cc +constructs and runs the following pipeline: +.PP +.EX +cc1 | cc2[\-qbe_arch\-abi] | [qbe] | as +.EE +.PP +Each stage is a separate process. +The stages are connected by anonymous pipes so that no large +intermediate files are created on disk unless +.B \-k +is used. .TP -.B \-S -Stop after the compilation stage, do not assemble and output the assembler -source. +.B cc1 +The C compiler frontend. +It reads the C source file, preprocesses it, parses it, +performs type checking and semantic analysis, +and emits the scc intermediate representation (IR) to standard +output. +It is installed as +.IR $SCCPREFIX/libexec/scc/cc1 . .TP -.BI \-t " system" -Define the -.I system -to compile for (i.e. linux, openbsd ...). +.B cc2 +The C compiler backend. +It reads the scc IR and emits either native assembly or QBE IR. +The exact binary invoked depends on the target architecture, ABI, +and whether QBE mode is active. +In QBE mode (the default), the binary name has the form +.BI cc2\-qbe_ arch \- abi ; +in native mode +.RB ( \-q ) +the form is +.BI cc2\- arch \- abi . +These binaries are installed under +.IR $SCCPREFIX/libexec/scc/ . .TP -.BI \-U " define" -Undefine a previously defined -.I define -by the -D parameter. +.B qbe +The QBE compiler backend. +Only invoked in QBE mode. +It reads QBE IR and emits native assembly. +.B qbe +is looked up in the standard +.BR PATH . .TP -.BI \-W " param" +.B as +The target assembler. +It assembles the native assembly into an object file. +The assembler command and its arguments are determined at +build time via the +.B ascmd +configuration variable in +.I sys.h +and may include +.B %a +(architecture), +.B %s +(system), +.B %b +(ABI), +.B %p +(library prefix), +and +.B %o +(output file) wildcards. +.PP +After all source files are compiled, the linker is invoked unless +.BR \-c , +.BR \-S , +.BR \-E , or -.B \-w -Show warning messages. -The parameter of -.B \-W -is ignored for compatibility reasons. +.B \-M +suppresses linking: .TP -.BI \-f " param" -and -.BI \-m " param" -are ignored for compatibility with other compiler command lines. -In the same way, -the options -.BI \-static , -.BI \-dynamic , -.BI \-pedantic , -.B \-ansi -and any option beginning with -.B \-std= -are ignored for the same reason. +.B ld +The target linker. +The linker command and its arguments are determined at build time +via the +.B ldcmd +configuration variable in +.IR sys.h . +The same wildcards as for +.B as +are supported, and +.B %c +expands to the full list of input object files. .SH ENVIRONMENT VARIABLES -Certain environment variables control the behaviour of scc. .TP .B ARCH -defines the -.I architecture -to compile for (i.e. amd64, i386 ...). +Target architecture name (e.g. +.BR amd64 , +.BR arm64 , +.BR i386 ). +Overridden by +.BR \-a . .TP .B SYS -defines the -.I system -to compile for (i.e. linux, openbsd ...). +Target operating system name (e.g. +.BR linux , +.BR openbsd ). +Overridden by +.BR \-t . .TP .B ABI -defines the -.I application binary interface -to compile for (i.e. sysv ...). +Target ABI name (e.g. +.BR sysv ). .TP .B FORMAT -defines the format of the output executable. +Target object file format (e.g. +.BR elf , +.BR coff ). .TP .B SCCPREFIX -defines the path prefix scc will search the scc suite in. +Path prefix under which the scc suite is installed. +Used to locate +.B cc1 +and +.B cc2 +under +.IR $SCCPREFIX/libexec/scc/ . +If not set, the compile-time +.B PREFIX +value is used. +.TP +.B SCCLIBPREFIX +Path prefix for scc libraries. +Expanded from the +.B %p +wildcard in linker and assembler command templates. +If not set, the compile-time +.B LIBPREFIX +value is used. +.TP +.B TMPDIR +Directory used for temporary files created during compilation. +If not set or empty, the current directory is used. +.SH EXAMPLES +.PP +Compile a C source file and link into an executable: +.IP +.EX +scc-cc \-o hello hello.c +.EE +.PP +Compile to an object file only: +.IP +.EX +scc-cc \-c hello.c +.EE +.PP +Compile multiple source files and link: +.IP +.EX +scc-cc \-o prog main.c util.c \-lm +.EE +.PP +Preprocess only and view the output: +.IP +.EX +scc-cc \-E hello.c +.EE +.PP +Generate make dependency rules: +.IP +.EX +scc-cc \-M hello.c +.EE +.PP +Stop after compilation, keeping intermediate files: +.IP +.EX +scc-cc \-k \-c hello.c +.EE +.PP +Compile for a specific target: +.IP +.EX +ARCH=arm64 ABI=sysv SYS=linux scc-cc \-o hello hello.c +.EE +.PP +Compile in native mode (no QBE): +.IP +.EX +scc-cc \-q \-o hello hello.c +.EE +.PP +Show all sub-process command lines: +.IP +.EX +scc-cc \-d \-c hello.c +.EE +.PP +The +.B \-d +flag prints the exact command line of each sub-process to standard error. +For example, compiling +.I hello.c +on an amd64 Linux system in QBE mode produces: +.IP +.EX +/usr/local/libexec/scc/cc1 \-I /usr/local/include/scc/bits/amd64/ \e + \-I /usr/local/include/scc/bits/linux/ \e + \-I /usr/local/include/scc/bits/linux/amd64/ \e + \-I /usr/local/include/scc/ hello.c +/usr/local/libexec/scc/cc2\-qbe_amd64\-sysv +qbe \-t amd64_sysv +as \-o hello.o +.EE +.SH DIAGNOSTICS +When a sub-process in the compilation pipeline fails, +.B scc-cc +reports an error to standard error and exits with a non-zero status. +.PP +If +.B cc1 +exits with a non-zero status, the error message comes from +.B cc1 +itself (a compilation error such as a syntax or type error) and +.B scc-cc +exits silently. +Likewise, if the linker +.B ld +fails, its own error output is displayed and +.B scc-cc +exits without an additional message. +.PP +If any stage terminates by a signal +or any other stage in the pipeline +.RB ( cc2 , +.BR qbe , +or +.BR as ) +terminates with non-zero exit then +these conditions are considered an internal error. +In this case +.B scc-cc +prints the following message to standard error: +.IP +.EX +scc-cc:tool: internal error +.EE +.PP +where +.I tool +is the name of the failing sub-process. +This message indicates a bug in the toolchain rather than an error in +the user's source code. +The same message is printed if +.B scc-cc +cannot +.BR execvp (2) +the sub-process binary (for example because +.B SCCPREFIX +is set incorrectly and +.B cc1 +or +.B cc2 +cannot be found). +In this case, +Using the option +.B \-d +combined with +.B \-k +is very useful because +it provides all the information to run the tool in isolation +and debug the issue. .SH SEE ALSO -.BR scc-cpp (1), -.BR scc-make (1) +.BR scc (1), +.BR scc\-cc1 (1), +.BR scc\-cc2 (1), +.BR scc\-cpp (1), +.BR scc\-ld (1), +.BR scc\-as (1), +.BR scc\-ir (7), +.BR qbe (1) diff --git a/doc/man1/scc-cc1.man b/doc/man1/scc-cc1.man @@ -0,0 +1,130 @@ +.TH SCC-CC1 1 scc\-VERSION +.SH NAME +scc-cc1 \- C compiler frontend +.SH SYNOPSIS +.B cc1 +.RB [ \-Ewd ] +.RB [ \-M ] +.RB [ \-a +.IR architecture ] +.RB [ \-D +.IR def[=val] ] ... +.RB [ \-U +.IR def ] ... +.RB [ \-I +.IR dir ] ... +.RI [ input ] +.SH DESCRIPTION +.B cc1 +is the C compiler frontend of the scc toolchain. +It reads a C source file (or standard input if no +.I input +file is given), performs preprocessing, parsing, type checking, +and semantic analysis, and emits the scc intermediate representation (IR) +to standard output. +.PP +.B cc1 +is not normally invoked directly. +It is called by the compiler driver +.BR scc\-cc (1), +which pipes its output to +.BR cc2 , +the code generation backend that produces assembly output. +.B cc1 +is installed as +.IR $prefix /libexec/scc/cc1. +.SH OPTIONS +.TP +.BI \-a " architecture" +Select the target architecture. +The following architectures are supported: +.RS +.TP +.B amd64-sysv +64-bit x86 with the System V ABI (default). +.TP +.B arm64-sysv +64-bit ARM with the System V ABI. +.TP +.B riscv64-sysv +64-bit RISC-V with the System V ABI. +.TP +.B i386-sysv +32-bit x86 with the System V ABI. +.TP +.B z80-scc +Zilog Z80 with the scc ABI. +.RE +.TP +.BI \-D " def[=val]" +Define the preprocessor macro +.I def +with an optional value +.IR val . +If +.I val +is omitted, the macro is defined with the value +.BR 1 . +This option may be repeated to define multiple macros. +.TP +.B \-E +Stop after preprocessing. +Emit the preprocessed C source to standard output instead of IR. +No compilation is performed. +.TP +.BI \-I " dir" +Prepend +.I dir +to the list of directories searched for header files. +This option may be repeated to add multiple directories. +User-specified directories are searched before any system include directories +added by +.BR scc\-cc (1). +.TP +.B \-M +Emit a +.BR make (1) +dependency rule describing the +.B #include +dependencies of the input file, then exit. +No compilation is performed. +.TP +.BI \-U " def" +Undefine the preprocessor macro +.IR def . +This option may be repeated. +.TP +.B \-d +Enable internal debug output. +.TP +.B \-w +Enable warning messages for dubious constructs. +.SH OUTPUT +.B cc1 +writes the scc IR to standard output. +The IR is a line-oriented, tab-separated format. +Declarations begin in column 0; expressions are indented with a tab +and written in reverse Polish notation. +For a full description of the IR format, types, storage classes, +and statement encoding, see +.BR scc\-ir (7). +.PP +When only preprocessing is requested +.RB ( \-E +or +.BR \-M ), +the preprocessed source or dependency rule is written to standard output +instead. +.PP +If any compilation error occurs, the output stream is closed immediately +so that the backend +.B cc2 +receives no output and can detect the failure. +.B cc1 +exits with a non-zero status on error. +.SH SEE ALSO +.BR scc\-cc (1), +.BR scc\-cpp (1), +.BR scc (1), +.BR scc\-cc2 (1), +.BR scc\-ir (7) diff --git a/doc/man1/scc-cc2.man b/doc/man1/scc-cc2.man @@ -0,0 +1,93 @@ +.TH SCC-CC2 1 scc\-VERSION +.SH NAME +scc-cc2 \- C compiler backend +.SH SYNOPSIS +.B cc2 +.RB [ \-d ] +.RI [ irfile ] +.SH DESCRIPTION +.B cc2 +is the C compiler backend of the scc toolchain. +It reads the scc intermediate representation (IR) from standard input +(or from +.I irfile +if given), and emits assembly code to standard output. +.PP +.B cc2 +is not normally invoked directly. +It is called by the compiler driver +.BR scc\-cc (1), +which pipes the IR produced by +.B cc1 +into +.BR cc2 . +.B cc2 +is installed as +.IR $prefix /libexec/scc/cc2-*. +.SH OPTIONS +.TP +.B \-d +Enable internal debug output. +When set, debugging information about the IR tree and the control flow +graph is printed to standard error during compilation. +.SH INPUT +.B cc2 +reads the scc IR produced by +.BR cc1 . +The IR is a line-oriented, tab-separated text format. +If +.I irfile +is specified, standard input is replaced by that file. +Otherwise the IR is read from standard input, which is the normal mode +when +.B cc2 +is used inside the pipeline constructed by +.BR scc\-cc (1). +.PP +For a full description of the IR format see +.BR scc\-ir (7). +.SH OUTPUT +.B cc2 +writes to standard output. +Depending on the variant of +.B cc2 +that is invoked, the output is either: +.TP +.B Native assembly +The target architecture assembly language, ready to be assembled by the +system assembler. +This is the output of the +.BI cc2\- arch \- abi +variants. +.TP +.B QBE IR +The intermediate language accepted by the QBE compiler backend. +This is the output of the +.BI cc2\-qbe_ arch \- abi +variants. +QBE subsequently compiles this IR to native assembly. +.SH BACKENDS +.B cc2 +is a family of architecture-specific binaries. +Each binary is compiled for a specific target and installed as a separate +executable under +.IR $SCCPREFIX/libexec/scc/ . +The following target backends are available: +.TP +.B cc2\-z80\-scc +Native code generator for the Zilog Z80 with the scc ABI. +.TP +.B cc2\-qbe_amd64\-sysv +QBE IR emitter for 64-bit x86 with the System V ABI. +.TP +.B cc2\-qbe_arm64\-sysv +QBE IR emitter for 64-bit ARM with the System V ABI. +.TP +.B cc2\-qbe_riscv64\-sysv +QBE IR emitter for 64-bit RISC-V with the System V ABI. +.SH SEE ALSO +.BR scc\-cc (1), +.BR scc\-cc1 (1), +.BR scc\-cpp (1), +.BR scc (1), +.BR scc\-ir (7)