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
Smaller C is a simple and small single-pass C compiler
Overview
Comments
-
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 inprintf
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 -
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 -
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 -
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 -
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
questionelf_module_get_ptr
. -
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 -
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 -
"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.)
question
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 -
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).
enhancement wontfix$ 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'
-
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 -
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
-
Full implementation of aditional 8086 compatibility mode
My code is based on Pull request 33 from aleexmaftei.
Changes:
- Implementation of "-8086" flag on smlrc and smlrcc
- Implementation of macro __SMALLER_C_8086__, setted by "-8086" flag
- This new flag can be used with 32-bit modes, but generate bigger code without 386 otimizations on 16 bits.
- Create a alternative lcds.a library with 8086 code only, named lcds86.a
- When "-8086" and "-tiny"/"-dost" flags active, use new "lcds86.a" instead "lcds.a"
- Creation of "Use8086InstrOnly" global variable on smlrc and smlrcc, setted by "-8086" flag
- When activated change generation of (MOVZX, MOVSX, Bit operations, SETxx instructions, etc) to 8086 compatible equivalents.
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 (underbindp
). - Windows binaries (under
binw
). - CWSDPMI r5 dependency for the DOS DPMI binaries.
- Include and library files (under
include
andlib
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 toC:\SMLRC\BIND
orC:\SMLRC\BINDP
orC:\SMLRC\BINW
, as appropriate. - Make
NASM.EXE
(you'll need version 2.03 or later) available through thePATH
environment variable as well.
Source code(zip)
v1.0.1+dos.win.1ab15c7.zip(962.20 KB)
- DOS binaries: regular (under
-
v1.0.0+dos.win.2a18041(Aug 29, 2021)
This release includes:
- DOS binaries: regular (under
bind
) and DPMI (underbindp
). - Windows binaries (under
binw
). They need to be assembled from parts (with thecopy /b
command, seebinw/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
andlib
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 toC:\SMLRC\BIND
orC:\SMLRC\BINDP
orC:\SMLRC\BINW
, as appropriate. - Make
NASM.EXE
(you'll need version 2.03 or later) available through thePATH
environment variable as well.
Source code(zip)
v1.0.0+dos.win.2a18041.zip(959.77 KB)
- DOS binaries: regular (under
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
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
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-
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.
Aheui JIT compiler for PC and web
아희짓 개요 아희짓은 아희 언어를 위한 JIT (Just in Time) 컴파일러입니다. 어셈블러와 유틸 라이브러리외에 외부 라이브러리에 전혀 의존하지 않고 JIT을 바닥부터 구현합니다. 지원 환경 64비트 windows, mac, linux (x86 아키텍쳐) 웹어셈
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
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
GNU Prolog is a native Prolog compiler
GNU Prolog is a native Prolog compiler with constraint solving over finite domains (FD)
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
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.
yadcc - Yet Another Distributed C++ Compiler
Yet Another Distributed C++ Compiler. yadcc是一套腾讯广告自研的分布式编译系统,用于支撑腾讯广告的日常开发及流水线。相对于已有的同类解决方案,我们针对实际的工业生产环境做了性能、可靠性、易用性等方面优化。
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
bcc is an interactive compiler of a language called b.
bcc is an interactive compiler of a language called b.
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
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
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
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.
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
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