SYNOPSIS chibicc [FLAGS] INPUTS DESCRIPTION chibicc - A Small GNU-Style ISO/IEC 9899:2011 Standard Compiler OVERVIEW chibicc is the simplest/tiniest/hackable/readable c11 compiler in the world that can compile code quickly and consistently across platforms FLAGS -o PATH Specifies path of output. -c Objectify the source file, but do not link. -S Compile the source file, but do not objectify. -E Preprocess the source file, but do not compile. Output defaults to stdout. -D TOKEN[=VALUE] Defines preprocessor token. -U TOKEN Undefines preprocessor token. -include DIR Add include. -I DIR -iquote DIR -isystem DIR Adds include directory. -x c (default for .c files) -x assembler (default for .s files) -x assembler-with-cpp (default for .S files) Explicitly specifies programming language. -Wa arg1[,arg2...] -Xassembler arg1[,arg2...] Appends opaque arguments passed along to assembler. -Wl arg1[,arg2...] -Xlinker arg1[,arg2...] Appends opaque arguments passed along to linker. -v Enables verbose mode. Lines with subprocess commands start with a space. -### Implies -v and enables shell command argument quoting. --version Shows compiler version. --help Shows this information. CODEGEN -pg -mfentry -mnop-mcount -mrecord-mcount Controls output of profiling hooks in function prologues. -fdata-sections -ffunction-sections Controls granularity of code visible to the linker. -msse3 -msse4 -msse4.1 -msse4.2 -mpopcnt Specifies microarchitectural features. Default is K8. -fpie -fpic -fPIC Controls output of position independent code. -fcommon -fno-common Controls usage of traditional STT_COMMON objects. MAKEFILE -M Generate makefile header dependency code. Output defaults to stdout. -MD Generate makefile header dependency code, and compile. Output defaults to output path with .d extension. -MMD Generate makefile header dependency code, and compile. Default include roots are excluded as dependencies. Output defaults to output path with .d extension. -MF PATH Specifies output path of header dependency code. -MT NAME Specifies name of target in generated makefile code. -MQ NAME Specifies name of target in makefile code w/ quoting. INTERNALS -P Generate Python bindings. -A Print abstract syntax tree. -J Generate HTML documentation for public APIs based on Javadoc comments containing Markdown. INTEGRAL TYPES _Bool char short int long long long __int128 signed char unsigned char unsigned short unsigned int unsigned long unsigned long long unsigned __int128 FLOATING POINT TYPES float double long double BUILTIN FUNCTIONS T __builtin_expect(T, int) unsigned long __builtin_offsetof(typename, token) int __builtin_reg_class(typename) num __builtin_constant_p(expr) int __builtin_unreachable() void * __builtin_frame_address(int) _Bool __builtin_types_compatible_p(typename, typename) T __builtin_atomic_exchange(T *addr, T neu) T * __builtin_assume_aligned(T *addr) void * __builtin_alloca(unsigned long) void __builtin_trap() int __builtin_clz(int) int __builtin_clzl(long) int __builtin_clzll(long long) int __builtin_ctz(int) int __builtin_ctzl(long) int __builtin_ctzll(long long) int __builtin_ffs(int) int __builtin_ffsl(long) int __builtin_ffsll(long long) int __builtin_popcount(unsigned int) long __builtin_popcountl(unsigned long) long __builtin_popcountll(unsigned long) unsigned long __builtin_strlen(char *) char * __builtin_strstr(char *, char *) char * __builtin_strchr(char *, int) void * __builtin_memcpy(void *, void *, unsigned long) char * __builtin_strpbrk(char *, char *) unsigned short __builtin_bswap16(unsigned short) unsigned int __builtin_bswap32(unsigned int) unsigned long __builtin_bswap64(unsigned long) int __builtin_isnan(flonum) int __builtin_isinf(flonum) int __builtin_isfinite(flonum) int __builtin_fpclassify(flonum) int __builtin_isless(flonum, flonum) int __builtin_isgreater(flonum, flonum) int __builtin_isunordered(flonum, flonum) int __builtin_islessequal(flonum, flonum) int __builtin_islessgreater(flonum, flonum) int __builtin_isgreaterequal(flonum, flonum) double __builtin_nan(char *) float __builtin_nanf(char *) long double __builtin_nanl(char *) long __builtin_signbit(double) int __builtin_signbitf(float) int __builtin_signbitl(long double) double __builtin_huge_val() float __builtin_huge_valf() long double __builtin_huge_vall() double __builtin_fabs(double) float __builtin_fabsf(float) long double __builtin_fabsl(long double) double __builtin_logb(double) float __builtin_logbf(float) long double __builtin_logbl(long double) double __builtin_fmax(double, double) float __builtin_fmaxf(float, float) long double __builtin_fmaxl(long double, long double) double __builtin_fmin(double, double) float __builtin_fminf(float, float) long double __builtin_fminl(long double, long double) double __builtin_copysign(double, double) float __builtin_copysignf(float, float) long double __builtin_copysignl(long double, long double) void __builtin_ia32_movntq(di *, di) int __builtin_ia32_pmovmskb128(v16qi) T __atomic_load_n(T *addr, int memorder) void __atomic_load(T *addr, T *res, int memorder) void __atomic_store_n(T *addr, T val, int memorder) void __atomic_store(T *addr, T *val, int memorder) void __atomic_clear(_Bool *addr, int memorder) _Bool __atomic_test_and_set(void *addr, int memorder) T __atomic_fetch_add(T *addr, T amt, int memorder) T __atomic_fetch_sub(T *addr, T amt, int memorder) T __atomic_fetch_xor(T *addr, T amt, int memorder) T __atomic_fetch_and(T *addr, T amt, int memorder) T __atomic_fetch_or(T *addr, T amt, int memorder) _Bool __atomic_compare_exchange_n(T *addr, T *old, T neu, int weak, int goodorder, int failorder) T __sync_lock_test_and_set(T *addr, T value, ...) void __sync_lock_release(T *addr, ...) BUILTIN OBJECTS __func__ __FUNCTION__ __va_area__ __alloca_size__ BUILTIN MACROS __FILE__ __LINE__ __DATE__ __TIME__ __COUNTER__ __TIMESTAMP__ __BASE_FILE__ __chibicc__ __cosmopolitan__ __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__ __NO_INLINE__ __GNUC_STDC_INLINE__ __BIGGEST_ALIGNMENT__ __C99_MACRO_WITH_VA_ARGS __GCC_ASM_FLAG_OUTPUTS__ __ELF__ __LP64__ _LP64 __STDC__ __STDC_HOSTED__ __STDC_NO_COMPLEX__ __STDC_UTF_16__ __STDC_UTF_32__ __STDC_VERSION__ __USER_LABEL_PREFIX__ __alignof__ __const__ __inline__ __signed__ __typeof__ __volatile__ __unix __unix__ __linux __linux__ __gnu_linux__ __BYTE_ORDER__ __FLOAT_WORD_ORDER__ __ORDER_BIG_ENDIAN__ __ORDER_LITTLE_ENDIAN__ __INT8_MAX__ __UINT8_MAX__ __INT16_MAX__ __UINT16_MAX__ __SHRT_MAX__ __INT_MAX__ __INT32_MAX__ __UINT32_MAX__ __INT64_MAX__ __LONG_MAX__ __LONG_LONG_MAX__ __UINT64_MAX__ __SIZE_MAX__ __INTPTR_MAX__ __UINTPTR_MAX__ __WINT_MAX__ __CHAR_BIT__ __SIZEOF_SHORT__ __SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_LONG_LONG__ __SIZEOF_POINTER__ __SIZEOF_PTRDIFF_T__ __SIZEOF_SIZE_T__ __SIZEOF_WCHAR_T__ __SIZEOF_WINT_T__ __SIZEOF_FLOAT__ __SIZEOF_FLOAT128__ __SIZEOF_DOUBLE__ __SIZEOF_FLOAT80__ __SIZEOF_LONG_DOUBLE__ __INT8_TYPE__ __UINT8_TYPE__ __INT16_TYPE__ __UINT16_TYPE__ __INT32_TYPE__ __UINT32_TYPE__ __INT64_TYPE__ __UINT64_TYPE__ __INTPTR_TYPE__ __UINTPTR_TYPE__ __PTRDIFF_TYPE__ __SIZE_TYPE__ __WCHAR_TYPE__ __CHAR16_TYPE__ __CHAR32_TYPE__ __WINT_TYPE__ __CHAR16_TYPE__ __WCHAR_TYPE__ __CHAR32_TYPE__ __INT_LEAST8_TYPE__ __UINT_LEAST8_TYPE__ __INT_LEAST16_TYPE__ __UINT_LEAST16_TYPE__ __INT_LEAST32_TYPE__ __UINT_LEAST32_TYPE__ __INT_LEAST64_TYPE__ __UINT_LEAST64_TYPE__ __INT_FAST8_TYPE__ __UINT_FAST8_TYPE__ __INT_FAST16_TYPE__ __UINT_FAST16_TYPE__ __INT_FAST32_TYPE__ __UINT_FAST32_TYPE__ __INT_FAST64_TYPE__ __UINT_FAST64_TYPE__ __DBL_DECIMAL_DIG__ __DBL_DENORM_MIN__ __DBL_DIG__ __DBL_EPSILON__ __DBL_HAS_DENORM__ __DBL_HAS_INFINITY__ __DBL_HAS_QUIET_NAN__ __DBL_MANT_DIG__ __DBL_MAX_10_EXP__ __DBL_MAX_EXP__ __DBL_MAX__ __DBL_MIN_10_EXP__ __DBL_MIN_EXP__ __DBL_MIN__ __FLT_DECIMAL_DIG__ __FLT_DENORM_MIN__ __FLT_DIG__ __FLT_EPSILON__ __FLT_EVAL_METHOD_TS_18661_3__ __FLT_EVAL_METHOD__ __FLT_HAS_DENORM__ __FLT_HAS_INFINITY__ __FLT_HAS_QUIET_NAN__ __FLT_MANT_DIG__ __FLT_MAX_10_EXP__ __FLT_MAX_EXP__ __FLT_MAX__ __FLT_MIN_10_EXP__ __FLT_MIN_EXP__ __FLT_MIN__ __FLT_RADIX__ __LDBL_DECIMAL_DIG__ __LDBL_DENORM_MIN__ __LDBL_DIG__ __LDBL_EPSILON__ __LDBL_HAS_DENORM__ __LDBL_HAS_INFINITY__ __LDBL_HAS_QUIET_NAN__ __LDBL_MANT_DIG__ __LDBL_MAX_10_EXP__ __LDBL_MAX_EXP__ __LDBL_MAX__ __LDBL_MIN_10_EXP__ __LDBL_MIN_EXP__ __LDBL_MIN__ __x86_64 __x86_64__ __amd64 __amd64__ __MMX__ __SSE__ __SSE_MATH__ __SSE2__ __SSE2_MATH__ __SSE3__ [conditional] __SSE4__ [conditional] __POPCNT__ [conditional] __PG__ [conditional] __PIC__ [conditional] __MFENTRY__ [conditional] ASSEMBLER That process is normally an implementation detail of your compiler, which can embed this program or launch it as a subprocess. Much GNU style syntax is supported. Your code that gets embedded in an asm() statement will ultimately end up here. This implementation, has the advantage of behaving the same across platforms, in a simple single file implementation that compiles down to a 100kilo ape executable. Your assembler supports the following flags: -o FILE output path [default: a.out] -I DIR append include path [default: .] -W inhibit .warning -Z inhibit .error and .err Your assembler supports the following directives: .zero N emits 0's .byte INT... emits int8 .word INT... emits int16 .long INT... emits int32 .quad INT... emits int64 .octa INT... emits int128 .ascii STR... emits string .asciz STR... emits string and 0 byte .ident STR emits string to .comment section .float NUMBER... emits binary32 .double NUMBER... emits binary64 .float80 NUMBER... emits x86 float (10 bytes) .ldbl NUMBER... emits x86 float (16 bytes) .zleb128 NUMBER... emits LEB-128 zigzag varint .sleb128 NUMBER... emits LEB-128 signed varint .uleb128 NUMBER... emits LEB-128 unsigned varint .align BYTES [FILL [MAXSKIP]] emits fill bytes to boundary .end halts tokenization .abort crashes assembler .err aborts (ignorable w/ -Z) .error STR aborts (ignorable w/ -Z) .warning STR whines (ignorable w/ -W) .text enters text section (default) .data enters data section .bss enters bss section .section NAME [SFLG SHT] enters section .previous enters previous section .pushsection NAME [SFLG SHT] pushes section .popsection pops section .type SYM TYPE sets type of symbol .size SYM EXPR sets size of symbol .internal SYM... marks symbol STV_INTERNAL .hidden SYM... marks symbol STV_HIDDEN .protected SYM... marks symbol STV_PROTECTED .globl SYM... marks symbol STB_GLOBAL .local SYM... marks symbol STB_LOCAL .weak SYM... marks symbol STB_WEAK .include FILE assembles file source .incbin FILE emits file content .file FILENO PATH dwarf file define .loc FILENO LINENO dwarf source line TYPE can be one of the following: - @notype STT_NOTYPE (default) - @object STT_OBJECT - @function STT_FUNC - @common STT_COMMON - @tls_object STT_TLS SHT can be one of the following: - @progbits SHT_PROGBITS - @note SHT_NOTE - @nobits SHT_NOBITS - @preinit_array SHT_PREINIT_ARRAY - @init_array SHT_INIT_ARRAY - @fini_array SHT_FINI_ARRAY SFLG is a string which may have the following characters: - a SHF_ALLOC - w SHF_WRITE - x SHF_EXECINSTR - g SHF_GROUP - M SHF_MERGE - S SHF_STRINGS - T SHF_TLS PREFIXES addr32 cs data16 ds es fs gs lock rep repe repne repnz repz rex rex.b rex.r rex.rb rex.rx rex.rxb rex.w rex.wb rex.wr rex.wrb rex.wrx rex.wrxb rex.wx rex.wxb rex.x rex.xb ss REGISTERS 64-bit 32-bit 16-bit lo byte hi byte │ sse mmx │ fpu ─────── ─────── ─────── ─────── ─────── │ ─────── ─────── │ ─────── %rax %eax %ax %al %ah │ %xmm0 %mm0 │ %st(0) %rcx %ecx %cx %cl %ch │ %xmm1 %mm1 │ %st(1) %rdx %edx %dx %dl %dh │ %xmm2 %mm2 │ %st(2) %rbx %ebx %bx %bl %bh │ %xmm3 %mm3 │ %st(3) %rsp %esp %sp %spl │ %xmm4 %mm4 │ %st(4) %rbp %ebp %bp %bpl │ %xmm5 %mm5 │ %st(5) %rsi %esi %si %sil │ %xmm6 %mm6 │ %st(6) %rdi %edi %di %dil │ %xmm7 %mm7 │ %st(7) %r8 %r8d %r8w %r8b │ %xmm8 %r9 %r9d %r9w %r9b │ %xmm9 %r10 %r10d %r10w %r10b │ %xmm10 %r11 %r11d %r11w %r11b │ %xmm11 %r12 %r12d %r12w %r12b │ %xmm12 %r13 %r13d %r13w %r13b │ %xmm13 %r14 %r14d %r14w %r14b │ %xmm14 %r15 %r15d %r15w %r15b │ %xmm15 %riz %eiz RICHARD STALLMAN MATH55 ASM() NOTATION BEHAVIOR =: write-only +: read/writeable SELECTION Autonomous a: ax/eax/rax b: bx/ebx/rbx c: bx/ebx/rbx d: dx/edx/rdx S: si/esi/rsi D: di/edi/rdi Algorithmic r: pick one of a,b,c,d,D,S,bp,sp,r8-15 registers, referenced as %0,etc. l: pick one of a,b,c,d,D,S,bp,r8-15 for indexing, referenced as %0,etc. q: pick one of a,b,c,d,r8-r15 for lo-byte access, e.g. %b0,%w0,%k0,etc. Q: pick one of a,b,c,d for hi-byte access, e.g. %h0,etc. U: pick one of a,c,d,D,S,r8-11 (call-clobbered) R: pick one of a,b,c,d,D,S,bp,sp (all models) y: pick mmx register x: pick sse register X: pick anything m: memory o: memory offsetable by an immediate, referenced as %0,2+%0,etc. p: memory, intended for load/push address and segments (movl %@:%p1, %0) g: probably shorthand for "rmi" combo X: allow anything Combos rm: pick register or memory address (converting immediates) rmi: pick register or memory address (allowing immediates) Immediates i: integer literal or compiler/assembler constexpr or linker embedding e: i∊[-2^31,2^31) for sign-extending immediates Z: i∊[0,2^32) for zero-extending immediates I: i∊[0,31] (5 bits for 32-bit shifts) J: i∊[0,63] (6 bits for 64-bit shifts) K: i∊[-128,127] L: permit uncasted char/short literal as zero-extended operand to andl? M: i∊[0,3] (intended for index scaling, e.g. "mov\t(?,?,1<<%0),?") N: i∊[0,255] (for in & out) M: 2-bit integer constant (shifts for index scaling) I: 5-bit integer constant (for 32-bit shifts) J: 6-bit integer constant (for 64-bit shifts) Transcendentals f: any stack slot t: top of stack (%st(0)) and possibly converts xmm to ymm u: second top of stack (%st(1)) Specials %= generates number unique to each instance %%REG explicitly-supplied register (used w/ clobbers) AUGMENTATION %pN print raw %PN print w/ @plt %aN print address %zN print only opcode suffix for operand type %lN print label without punctuation, e.g. jumps %cN print immediate w/o punctuation, e.g. lea %c0(%1),%2 %bN print lo-byte form, e.g. xchgb %b0,%%al (QImode 8-bit) %hN print hi-byte form, e.g. xchgb %h0,%%ah (QImode 8-bit) %wN print word form, e.g. xchgw %w0,%%ax (HImode 16-bit) %kN print dword form, e.g. xchgl %k0,%%eax (SImode 32-bit) %qN print qword form, e.g. xchgq %q0,%%rax (DImode 64-bit) %HN access high 8 bytes of SSE register, or +8 displacement %nN negated literal, e.g. lea %n0(%1),%2 %VN print register name without %, e.g. call foo%V0 EXAMPLE static inline void MixAudio(short a[static 8], const short b[static 8]) { asm("paddsw\t%1,%0" : "+x"(a) : "x"(b) : "memory"); }