Smaller C is a simple and small single-pass C compiler

Overview
Smaller C is a simple and small single-pass C compiler,
currently supporting most of the C language common between C89/ANSI C
and C99 (minus some C89 and plus some C99 features).

Currently it generates 16-bit and 32-bit 80386+ assembly code for NASM
that can then be assembled and linked into DOS, Windows, Linux and Mac OS X
programs.
(You may use YASM or FASM instead of NASM)

Code generation for MIPS CPUs is also supported (primarily for RetroBSD).

The compiler is capable of compiling itself.

The core compiler comes with a preprocessor (ucpp), a linker and a compiler
driver (the driver invokes the preprocessor, the core compiler, the assembler,
and the linker and supports options similar to those of gcc).

The standard C library is work-in-progress and it's close to completion.

See the project documentation for more up-to-date details:
https://github.com/alexfru/SmallerC/tree/master/v0100/doc

For the lack of a better place, you can discuss Smaller C here:
https://hackaday.io/project/5569-smaller-c

Links:
NASM: http://nasm.us/
YASM: http://yasm.tortall.net/
FASM: http://flatassembler.net/
CWSDPMI: https://sandmann.dotster.com/cwsdpmi/
HX DOS Extender: https://web.archive.org/web/20141003032346/http://www.japheth.de/
RetroBSD: http://retrobsd.org/

Other projects based on/using Smaller C:
"ROM C" (like ROM Basic but C): https://hackaday.io/project/29198-native-c-pic32-color-video-on-tv
FYS OS: http://www.fysnet.net/fysos.htm
NewBasic Compiler: http://fysnet.net/nbc.htm
Sweet32 CPU and toolchain: https://github.com/Basman74/Sweet32-CPU

Normative and other useful documents on C:
C99 + TC1 + TC2 + TC3, WG14 N1256:
  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
Dave Prosser's C preprocessing algorithm annotated by Diomidis D. Spinellis:
  http://www.spinellis.gr/blog/20060626/index.html
Rationale for C99:
  http://www.open-std.org/jtc1/sc22/wg14/www/docs/C99RationaleV5.10.pdf
The New C Standard: An Economic and Cultural Commentary:
  http://www.knosof.co.uk/cbook/cbook.html
The Development of the C Language by Dennis M. Ritchie:
  https://www.bell-labs.com/usr/dmr/www/chist.html
The Standard C Library by P.J. Plauger
  https://www.amazon.com/dp/0131315099
Issues
  • Using long and float types in 16-bit mode

    Using long and float types in 16-bit mode

    Hey,

    I'm working on a MikeOS C library and I'm having trouble with the lack of long type that is needed for some functions. It would also be nice to support floating point in printf and other C functions. Do you have any plans to add the long or float types for 16-bit binaries?

    If not, perhaps you could explain the problems and I'll try to implement it.

    By the way, I've notice that using a floating point operation in 16-bit mode causes the compiler to emit a symbol such as: __addsf3

    Could I add floating point support at a library level by providing my own functions for these symbols?

    Thanks

    question 
    opened by ZeroKelvinKeyboard 27
  • Code and data in ROM and RAM on 80188?

    Code and data in ROM and RAM on 80188?

    Hello, I was looking for a C compiler for an 80C188 processor and this one came to be a really nice one. However, and after looking in the Wiki, I found something that might cripple my intentions. This board happens to have a 128k RAM and 512k flash. If the flat image produced by the compiler ends up in the read only map of the processor (in the flash), some code (ie global rw variables) will become read only. I was looking the smlrl.c file but I couldn't tell how to force that section to be in other place (for my purposes, at the bottom of the memory map, 0x0). I know that I'll need an initializer stub that should run prior to my code.

    So, my question is, it possible to achieve this without a lot of fiddling in the source file of smlrl? Or maybe some kind of hack using other tool alongside SmallerC?

    Sorry if this is not a proper "issue", but I wanted to ask directly to the author.

    question 
    opened by cocus 16
  • Linker & Call Exception

    Linker & Call Exception

    Hi,

    Recently I've been developing a 16-bit library/archive. The library is written in assembly (NASM) and makes calls to immediate values. It assemblies into an elf object just fine, but when I link it with smlrl, I get an Unhandled exception! error. I've been able to trace the problem back to the call instructions. I'm not sure if I'm making a silly mistake or if it's a genuine problem, but it seems that the linker can't handle handle my 16-bit calls!

    Below is the readout of the build process:

    smlrc.exe -seg16 -seg16 -SI .\../include test.c test.asm
    nasm.exe -f elf test.asm -o test.o
    smlrl.exe -flat16 -tiny -origin 0x3200 -entry _main test.o mlib.a -o test.bin
    
    Unhandled exception!
    
    Executed command failed
    

    I can give more information if needed. Any help would be appreciated!

    bug 
    opened by I8087 13
  • DOS: 32-bit code segments with 16-bit entry point

    DOS: 32-bit code segments with 16-bit entry point

    is it possible to create an MZ EXE with both 16-bit and 32-bit code segments? (for example, you have a stub that enters Protected Mode, calls into your main application to do some work, then returns to DOS) without DPMI?

    question 
    opened by lighth7015 9
  • Unexpected declaration or expression of type void: Porting an ELF loader to SmallerC

    Unexpected declaration or expression of type void: Porting an ELF loader to SmallerC

    Hi,

    While compiling an ELF loader on Windows, I ran into the following errors:

    Error in "elf-loader/elf-module.c" (38:41)
    Unexpected declaration or expression of type void
    
    Failed command 'smlrc.exe -seg32 -winstack -nopp elf-loader/elf-module.i elf-loader/elf-module.asm'
    

    The file (elf-loader/elf-module.c) is as follows:

    /*
     * ELF loadable modules
     *
     * 12 Feb 2011, Yury Ossadchy
     */
    #include <string.h>
    
    #include "elf-module-private.h"
    
    static char *elf_module_sym_name(elf_module_t *elf, int offs)
    {
        return elf->names + offs;
    }
    
    static void elf_module_layout(elf_module_t *elf)
    {
        int i;
        Elf_Shdr *shdr;
    
        for (i = 1; i < elf->header->e_shnum; i++) {
    	shdr = &elf->sections[i];
    
    	if (!(shdr->sh_flags & SHF_ALLOC))
    	    continue;
    
    	shdr->sh_addr = shdr->sh_addralign
    	    ? (elf->size + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1)
    	    : elf->size;
    	elf->size = shdr->sh_addr + shdr->sh_size;
        }
    }
    
    static void *elf_module_get_ptr(elf_module_t *elf, Elf_Addr addr)
    {
        return elf->start + addr;
    }
    
    static void *elf_module_sec_ptr(elf_module_t *elf, Elf_Shdr *shdr)
    {
        return (void *) elf->header + shdr->sh_offset;
    }
    
    static int elf_module_reloc(elf_module_t *elf)
    {
        int i;
        Elf_Shdr *shdr = &elf->sections[0];
    
        for (i = 0; i < elf->header->e_shnum; i++) {
    	switch (shdr->sh_type) {
    	case SHT_REL:
    	    elf_module_reloc_section(elf, shdr);
    	    break;
    	case SHT_RELA:
    	    elf_module_reloca_section(elf, shdr);
    	    break;
    	}
    	shdr++;
        }
        return 0;
    }
    
    static int elf_module_link(elf_module_t *elf, elf_module_link_cbs_t *cbs)
    {
        int err;
        int n = elf->symtab->sh_size / sizeof(Elf_Sym);
        Elf_Sym *sym;
        Elf_Sym *symtab = elf_module_sec_ptr(elf, elf->symtab);
        Elf_Sym *end = &symtab[n];
    
        for (sym = &symtab[1]; sym < end; sym++) {
    	switch (sym->st_shndx) {
    	case SHN_COMMON:
    	    return -EME_NOEXEC;
    
    	case SHN_ABS:
    	    break;
    	
    	case SHN_UNDEF:
    	    /* resolve external symbol */
    	    sym->st_value = (Elf_Addr)
    		cbs->resolve(elf, elf_module_sym_name(elf, sym->st_name));
    	    if (!sym->st_value)
    		return -EME_UNDEFINED_REFERENCE;
    	    break;
    
    	default:
    	    /* bind to physical section location and define as accessible symbol */
    	    sym->st_value += (Elf_Addr) elf_module_get_ptr(elf,
    		elf->sections[sym->st_shndx].sh_addr);
    
    	    if (ELF_SYM_TYPE(sym->st_info) != STT_SECTION) {
    		err = cbs->define(elf, elf_module_sym_name(elf, sym->st_name),
    		    (void *) sym->st_value);
    		if (err < 0)
    		    return err;
    	    }
    	}
        }
        return 0;
    }
    
    int elf_module_init(elf_module_t *elf, void *data, size_t size)
    {
        int i;
    
        elf->header = data;
    
        if (memcmp(elf->header->e_ident, ELF_MAGIC, sizeof(ELF_MAGIC) - 1)
    	|| !elf_module_check_machine(elf)) {
    	return -EME_NOEXEC;
        }
    
        elf->sections = data + elf->header->e_shoff;
        elf->strings = data + elf->sections[elf->header->e_shstrndx].sh_offset;
        elf->size = 0;
    
        /* section 0 is reserved */
        for (i = 1; i < elf->header->e_shnum; i++) {
    	Elf_Shdr *shdr = &elf->sections[i];
    
    	if (shdr->sh_type == SHT_SYMTAB) {
    	    elf->symtab = &elf->sections[i];
    	    elf->strtab = &elf->sections[elf->sections[i].sh_link];
    	    elf->names = data + elf->strtab->sh_offset;
    	}
        }
    
        elf_module_layout(elf);
        return 0;
    }
    
    size_t elf_module_get_size(elf_module_t *elf)
    {
        return elf->size;
    }
    
    void elf_module_set_data(elf_module_t *elf, void *data)
    {
        elf->data = data;
    }
    
    void *elf_module_get_data(elf_module_t *elf)
    {
        return elf->data;
    }
    
    int elf_module_load(elf_module_t *elf, void *dest, elf_module_link_cbs_t *cbs)
    {
        int i;
        int res;
        Elf_Shdr *shdr;
    
        elf->start = dest;
    
        for (i = 1; i < elf->header->e_shnum; i++) {
    	shdr = &elf->sections[i];
    
    	if (!(shdr->sh_flags & SHF_ALLOC))
    	    continue;
    
    	memcpy(elf_module_get_ptr(elf, shdr->sh_addr),
    	    (void *) elf->header + shdr->sh_offset, shdr->sh_size);
        }
    
        res = elf_module_link(elf, cbs);
        if (res < 0)
    	goto out;
    
        res = elf_module_reloc(elf);
    out:
        return res;
    }
    
    void *elf_module_lookup_symbol(elf_module_t *elf, char *name)
    {
        int i;
        int n = elf->symtab->sh_size / sizeof(Elf_Sym);
        Elf_Sym *sym = (void *) elf->header + elf->symtab->sh_offset + sizeof(Elf_Sym);
    
        for (i = 1; i < n; i++, sym++) {
    	switch (sym->st_shndx) {
    	case SHN_ABS:
    	    break;
    
    	case SHN_UNDEF:
    	    break;
    
    	default:
    	    if (!strcmp(elf_module_sym_name(elf, sym->st_name), name))
    		return (void *) sym->st_value;
    	}
        }
        return NULL;
    }
    

    Line 38 is the function elf_module_get_ptr.

    question 
    opened by lighth7015 7
  • Is Win16 support doable?

    Is Win16 support doable?

    I would like to know whether Win16 support is doable: whether SmallerC knows how to generate ASM code that can then be assembled (by NASM, etc) to Win16 NE executable, and be possibly linked to other Win16 dlls.

    question 
    opened by HBelusca 6
  • far pointers?

    far pointers?

    Hi!

    It is explicitly stated in the docs that the far pointers are unsupported. Yet its a pity, as it prevents the building of many existing DOS projects with this compiler. So I'd like to know if the support is planned, and if not - why, and how difficult is it to add such a support? Given that the huge pointers are already supported, what is the remaining problems that prevents the support of the far pointers?

    question 
    opened by stsp 5
  • "stdarg.h" macros.

    Hello, First off I would say Great Work! This is possibly the only compiler that satisfies my needs (less bloat, simple and loose syntax, NASM compatible etc.)
    I have been recently playing with this compiler for DOS development, sadly it does not support (until now) the parametrized macros, which is needed for functions like va_end, va_start and va_arg which are in turn needed for functions like printf. Is there a workaround? -ALLDESP

    question 
    opened by Benderx2 4
  • Invalid or unsupported command line option '-E'

    Invalid or unsupported command line option '-E'

    I’m trying to port mksh to SmallerC, and it fails at even detecting the compiler because the compiler driver lacks the option -E (preprocess only).

    $ cat >conftest.c <<\EOF
    const char *
    #if defined(__ICC) || defined(__INTEL_COMPILER)
    ct="icc"
    #elif defined(__xlC__) || defined(__IBMC__)
    ct="xlc"
    #elif defined(__SUNPRO_C)
    ct="sunpro"
    #elif defined(__SMALLER_C__)
    ct="smlrc"
    #elif defined(__neatcc__)
    ct="neatcc"
    #elif defined(__lacc__)
    ct="lacc"
    #elif defined(__ACK__)
    ct="ack"
    #elif defined(__BORLANDC__)
    ct="bcc"
    #elif defined(__WATCOMC__)
    ct="watcom"
    #elif defined(__MWERKS__)
    ct="metrowerks"
    #elif defined(__HP_cc)
    ct="hpcc"
    #elif defined(__DECC) || (defined(__osf__) && !defined(__GNUC__))
    ct="dec"
    #elif defined(__PGI)
    ct="pgi"
    #elif defined(__DMC__)
    ct="dmc"
    #elif defined(_MSC_VER)
    ct="msc"
    #elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
    ct="adsp"
    #elif defined(__IAR_SYSTEMS_ICC__)
    ct="iar"
    #elif defined(SDCC)
    ct="sdcc"
    #elif defined(__PCC__)
    ct="pcc"
    #elif defined(__TenDRA__)
    ct="tendra"
    #elif defined(__TINYC__)
    ct="tcc"
    #elif defined(__llvm__) && defined(__clang__)
    ct="clang"
    #elif defined(__NWCC__)
    ct="nwcc"
    #elif defined(__GNUC__)
    ct="gcc"
    #elif defined(_COMPILER_VERSION)
    ct="mipspro"
    #elif defined(__sgi)
    ct="mipspro"
    #elif defined(__hpux) || defined(__hpua)
    ct="hpcc"
    #elif defined(__ultrix)
    ct="ucode"
    #elif defined(__USLC__)
    ct="uslc"
    #elif defined(__LCC__)
    ct="lcc"
    #elif defined(MKSH_MAYBE_KENCC)
    /* and none of the above matches */
    ct="kencc"
    #else
    ct="unknown"
    #endif
    ;
    const char *
    #if defined(__KLIBC__) && !defined(__OS2__)
    et="klibc"
    #else
    et="unknown"
    #endif
    ;
    EOF
    $ smlrcc -linux -E  -I. -I'/root/mksh'  -DMKSH_BUILDSH -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN  conftest.c
    
    Invalid or unsupported command line option '-E'
    
    enhancement wontfix 
    opened by mirabilos 3
  • coordinate on testing

    coordinate on testing

    I created a project:

    https://c-testsuite.github.io/ https://github.com/c-testsuite/c-testsuite

    and wondered if you would like to join in, things are sparse and need organizing, but perhaps you understand what I am aiming for.

    question 
    opened by andrewchambers 3
  • compile error (using clang with asan)

    compile error (using clang with asan)

    I use clang(with fsanitize=address) to compile this project. when I call $ make I receive:

    awk -v l=/opt/SmallerC/v0100/srclib/ '/.$/{$0=l$0}{print}' /opt/SmallerC/v0100/srclib/lcds.txt > lcds.op ./smlrcc -SI /opt/SmallerC/v0100/include -I /opt/SmallerC/v0100/srclib @lcds.op

    ==15851==ERROR: LeakSanitizer: detected memory leaks

    Direct leak of 1400 byte(s) in 1 object(s) allocated from: #0 0x4da2e0 in realloc (/opt/SmallerC/smlrcc+0x4da2e0) #1 0x51445b in fatargs /opt/SmallerC/v0100/smlrcc.c:550:23

    SUMMARY: AddressSanitizer: 1400 byte(s) leaked in 1 allocation(s). /opt/SmallerC/v0100/../common.mk:42: recipe for target 'lcds.a' failed make: *** [lcds.a] Error 1 rm lcds.op

    opened by frokaikan 3
Releases(v1.0.1+dos.win.1ab15c7)
  • v1.0.1+dos.win.1ab15c7(Sep 14, 2021)

    This release includes:

    • DOS binaries: regular (under bind) and DPMI (under bindp).
    • Windows binaries (under binw).
    • CWSDPMI r5 dependency for the DOS DPMI binaries.
    • Include and library files (under include and lib respectively).
    • Test programs (under tests).

    This release doesn't include:

    • The compiler sources.
    • NASM (you'll need version 2.03 or later).
    • Binaries for Linux and MacOS.

    Installation:

    • Create a directory as close as possible to the disk root, e.g. C:\SMLRC.
    • Unpack the contents of the archive there.
    • Set your PATH environment variable to point to C:\SMLRC\BIND or C:\SMLRC\BINDP or C:\SMLRC\BINW, as appropriate.
    • Make NASM.EXE (you'll need version 2.03 or later) available through the PATH environment variable as well.
    Source code(tar.gz)
    Source code(zip)
    v1.0.1+dos.win.1ab15c7.zip(962.20 KB)
  • v1.0.0+dos.win.2a18041(Aug 29, 2021)

    This release includes:

    • DOS binaries: regular (under bind) and DPMI (under bindp).
    • Windows binaries (under binw). They need to be assembled from parts (with the copy /b command, see binw/readme.txt for details). The reason being false positives in antivirus software, which may hinder downloading the pre-compiled Windows binaries.
    • CWSDPMI r5 dependency for the DOS DPMI binaries.
    • Include and library files (under include and lib respectively).
    • Test programs (under tests).

    This release doesn't include:

    • The compiler sources.
    • NASM (you'll need version 2.03 or later).
    • Binaries for Linux and MacOS.

    Installation:

    • Create a directory as close as possible to the disk root, e.g. C:\SMLRC.
    • Unpack the contents of the archive there.
    • Set your PATH environment variable to point to C:\SMLRC\BIND or C:\SMLRC\BINDP or C:\SMLRC\BINW, as appropriate.
    • Make NASM.EXE (you'll need version 2.03 or later) available through the PATH environment variable as well.
    Source code(tar.gz)
    Source code(zip)
    v1.0.0+dos.win.2a18041.zip(959.77 KB)
Owner
Alexey Frunze
Alexey Frunze
Compiler Design Project: Simulation of front-end phase of C Compiler involving switch-case construct.

CSPC41 Compiler Design Project Assignment Compiler Design Project: Simulation of front-end phase of C Compiler involving switch-case construct. Using

Adeep Hande 1 Dec 15, 2021
A Small C Compiler

8cc C Compiler Note: 8cc is no longer an active project. The successor is chibicc. 8cc is a compiler for the C programming language. It's intended to

Rui Ueyama 5.5k May 12, 2022
nanoc is a tiny subset of C and a tiny compiler that targets 32-bit x86 machines.

nanoc is a tiny subset of C and a tiny compiler that targets 32-bit x86 machines. Tiny? The only types are: int (32-bit signed integer) char (8-

Ajay Tatachar 16 Feb 13, 2022
Microvm is a virtual machine and compiler

The aim of this project is to create a stack based language and virtual machine for microcontrollers. A mix of approaches is used. Separate memory is used for program and variable space (Harvard architecture). An interpreter, virtual machine and compiler are available. A demostration of the interpreter in action is presented below.

null 9 Feb 21, 2022
Aheui JIT compiler for PC and web

아희짓 개요 아희짓은 아희 언어를 위한 JIT (Just in Time) 컴파일러입니다. 어셈블러와 유틸 라이브러리외에 외부 라이브러리에 전혀 의존하지 않고 JIT을 바닥부터 구현합니다. 지원 환경 64비트 windows, mac, linux (x86 아키텍쳐) 웹어셈

Sunho Kim 27 Jan 2, 2022
A LLVM and Clang compiler toolchain built for kernel development

Cosmic-Clang Toolchain This is a LLVM and Clang compiler toolchain built for kernel development. Builds are always made from the latest LLVM sources r

Ǥђ๏ຮ₮⌁Ⲙครtє࿐ 0 Apr 12, 2022
A C compiler for LLVM. Supports C++11/14/1z C11

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies

LLVM 13.8k May 14, 2022
GNU Prolog is a native Prolog compiler

GNU Prolog is a native Prolog compiler with constraint solving over finite domains (FD)

Daniel Diaz 52 May 11, 2022
Take your first step in writing a compiler.

first-step Take your first step in writing a compiler. Building from Source Before building first-step, please make sure you have installed the follow

PKU Compiler Course 25 Jan 22, 2022
NCC is an ANSI/ISO-compliant optimizing C compiler.

The compiler is retargetable by design, but, at present, it only produces binaries for Linux/x86_64. As the compiler ABI differs somewhat from the System V ABI used by Linux, its code cannot be linked against Linux system libraries. It does, however, provide its own (incomplete) standard ANSI/Posix C library.

Charles E. Youse 0 Apr 1, 2022
yadcc - Yet Another Distributed C++ Compiler

Yet Another Distributed C++ Compiler. yadcc是一套腾讯广告自研的分布式编译系统,用于支撑腾讯广告的日常开发及流水线。相对于已有的同类解决方案,我们针对实际的工业生产环境做了性能、可靠性、易用性等方面优化。

Tencent 237 May 13, 2022
C implementation of the Tiny BASIC compiler found in an article by Dr. Austin Henley

Teeny Tiny Basic A C implementation of the Tiny BASIC compiler found in this article and this github repo by Dr. Austin Henley. I did pretty well in A

Gavin Morris 4 Apr 12, 2022
bcc is an interactive compiler of a language called b.

bcc is an interactive compiler of a language called b.

kparc 16 Apr 5, 2022
This is a compiler written from scratch in C

C Compiler This is a compiler written from scratch in C, with fully supporting C18 as a goal. It can currently compile itself, and most simple program

null 26 May 6, 2022
mrcceppc is a reimplementation project for the Metrowerks mwcceppc compiler.

Compiler | mrcceppc mrcceppc is a reimplementation project for the Metrowerks mwcceppc compiler. Compiling Run generate_{version}.bat for which versio

null 7 Dec 10, 2021
A C header that allow users to compile brainfuck programs within a C compiler.

brainfuck.h A C header that allow users to compile brainfuck programs within a C compiler. You can insert the header into the top of your brainfuck so

null 2 Apr 18, 2022
Gilbraltar is a version of the OCaml compiler to be able to build a MirageOS for RaspberryPi 4.

Gilbraltar is a version of the OCaml compiler to be able to build a MirageOS for RaspberryPi 4. It's a work in progress repository to provide a dune's toolchain (as ocaml-freestanding) specialized for Raspberry Pi 4.

Calascibetta Romain 44 May 7, 2022
NaiveCC: a compiler frontend for a subset of C

NaiveCC: a compiler frontend for a subset of C This is a toy compiler frontend for a subset of the C programming language based on the LR(1) parsing t

Yuxiang Wei 1 Nov 15, 2021
A compiler written in C++ to convert .hoi code to hoi4 code

What is HC4? HC4 is a compiler that converts .hoic filenames to Hearts of Iron IV's .txt. Usage Use hc4 in the terminal (./hc4 if on Unix) and it will

SaCode 1 Jan 11, 2022