diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2020-05-11 21:28:00 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2020-05-11 21:28:00 +0200 |
commit | 86ef164d2d82a2f3f18e07ec639f8de197849178 (patch) | |
tree | 5d3747c596280a4d91cd05b3ad9315cb7bdaefce | |
parent | 1e3452c52d140e43efbfeaa5f4a1057e959b644d (diff) | |
download | compilertests-86ef164d2d82a2f3f18e07ec639f8de197849178.tar.gz compilertests-86ef164d2d82a2f3f18e07ec639f8de197849178.tar.bz2 |
added a helper build.sh script
-rwxr-xr-x | ecomp-c/build.sh | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/ecomp-c/build.sh b/ecomp-c/build.sh new file mode 100755 index 0000000..b146182 --- /dev/null +++ b/ecomp-c/build.sh @@ -0,0 +1,242 @@ +#!/bin/bash + +BINARY=${1:-ec} +COMPILER=${2:-gcc} +MODE=${3:-freestanding} +LEVEL=${4:-0} + +DEBUG=0 + +declare -a MODULES +MODULES+=("libc-${MODE}.c") +MODULES+=("$BINARY.c") + +case "${COMPILER}" in + gcc) + CFLAGS="-m32 -march=i386 -Werror -Wno-noreturn -Wall -pedantic -std=c89 -x c" + ;; + clang) + CFLAGS="-m32 -march=i386 -Werror -Wall -pedantic -std=c89 -x c" + ;; + pcc) + CFLAGS="-march=i386 -Werror -Wall -std=c89 -x c" + ;; + tcc) + CFLAGS="-m32 -march=i386 -Werror -Wall -std=c89" +esac + +case "${LEVEL}" in + 0|1|2|3) + CFLAGS+=" -O${LEVEL}" + ;; + d) + CFLAGS+=" -g -O0" + DEBUG=1 + ;; +esac + +case "${COMPILER}:${MODE}" in + gcc:freestanding) + CFLAGS+=" -ffreestanding -fno-stack-protector -nostdlib -emain -fno-pic -fno-omit-frame-pointer" + ;; + clang:freestanding) + CFLAGS+=" -ffreestanding -fno-stack-protector -nostdlib -Wl,-emain -fno-omit-frame-pointer" + ;; + pcc:freestanding) + CFLAGS+=" -ffreestanding -nostdlib -Wl,-emain" + ;; + tcc:freestanding) + CFLAGS+=" -fno-bultin -nostdlib" + MODULES+=("_start-stub.c") + ;; + *:hosted) + CFLAGS+=" -lbsd" + ;; +esac + +if [ "${DEBUG}" = 1 ]; then + cat ${MODULES[@]} > "${BINARY}_tmp.c" + ${COMPILER} ${CFLAGS} -o ${BINARY} "${BINARY}_tmp.c" +else + cat ${MODULES[@]} | ${COMPILER} ${CFLAGS} -o ${BINARY} - +fi + +exit 0 +#TODO: amalgamation xxx.c or stding -x c - + +# debbuging freestanding compiler +cat libc-freestanding.c ec.c > test.c +gcc -g -O0 -m32 -march=i386 -ffreestanding -fno-stack-protector -nostdlib -emain -Werror -Wno-noreturn -Wall -pedantic -fno-pic -std=c89 -o ec test.c + +assembler +--------- + +cat libc-freestanding.c asm-i386.c | gcc -g -O0 -m32 -march=i386 -ffreestanding -fno-stack-protector -nostdlib -emain -Werror -Wno-noreturn -Wall -pedantic -fno-pic -std=c89 -o asm-i386 -x c - +# optimized with own libc, syscalls need -fno-omit-frame-pointer otherwise they clobber the stack +cat libc-freestanding.c asm-i386.c | gcc -g -O1 -m32 -march=i386 -fno-omit-frame-pointer -ffreestanding -fno-stack-protector -nostdlib -emain -Werror -Wno-noreturn -Wall -pedantic -fno-pic -std=c89 -o asm-i386 -x c - +cat libc-freestanding.c asm-i386.c | gcc -g -O2 -m32 -march=i386 -fno-omit-frame-pointer -ffreestanding -fno-stack-protector -nostdlib -emain -Werror -Wno-noreturn -Wall -pedantic -fno-pic -std=c89 -o asm-i386 -x c - +cat libc-freestanding.c asm-i386.c | gcc -g -O3 -m32 -march=i386 -fno-omit-frame-pointer -ffreestanding -fno-stack-protector -nostdlib -emain -Werror -Wno-noreturn -Wall -pedantic -fno-pic -std=c89 -o asm-i386 -x c - + +# to use libc and syscall of the host +cat libc-hosted.c asm-i386.c | gcc -g -O0 -m32 -march=i386 -fno-stack-protector -Werror -Wno-noreturn -Wall -pedantic -fno-pic -std=c89 -o asm-i386 -x c - -lbsd +cat libc-hosted.c asm-i386.c | gcc -g -O3 -m32 -march=i386 -Werror -Wall -pedantic -std=c89 -o asm-i386.c -lbsd -x c - + +cat libc-freestanding.c asm-i386.c | clang -g -O0 -m32 -march=i386 -ffreestanding -fno-stack-protector -nostdlib -Wl,-emain -Werror -Wall -pedantic -std=c89 -o asm-i386 -x c - +# ENOSYS in syscall wrappers, is the optimizer clobbering something here? +cat libc-freestanding.c asm-i386.c | clang -g -O1 -m32 -march=i386 -fno-omit-frame-pointer -ffreestanding -fno-stack-protector -nostdlib -Wl,-emain -Werror -Wall -pedantic -std=c89 -o asm-i386 -x c - +cat libc-freestanding.c asm-i386.c | clang -g -O2 -m32 -march=i386 -fno-omit-frame-pointer -ffreestanding -fno-stack-protector -nostdlib -Wl,-emain -Werror -Wall -pedantic -std=c89 -o asm-i386 -x c - +cat libc-freestanding.c asm-i386.c | clang -g -O3 -m32 -march=i386 -fno-omit-frame-pointer -ffreestanding -fno-stack-protector -nostdlib -Wl,-emain -Werror -Wall -pedantic -std=c89 -o asm-i386 -x c - +# to use libc and syscall of the host +cat libc-hosted.c asm-i386.c | clang -g -O3 -m32 -march=i386 -Werror -Wall -pedantic -std=c89 -o asm-i386 -lbsd -x c - + +cat libc-freestanding.c asm-i386.c | pcc -g -O1 -march=i386 -ffreestanding -nostdlib -Wl,-emain -Werror -Wall -std=c89 -o asm-i386 -x c - +# to use libc and syscall of the host +# valgrind fails in SIGILL at unhandled instruction bytes: 0xC8 0x4 0x0 0x0 +cat libc-hosted.c asm-i386.c | pcc -g -O1 -march=i386 -Werror -Wall -std=c89 -o asm-i386 -lbsd -x c - + +cat libc-freestanding.c asm-i386.c _start-stub.c | tcc -g -m32 -march=i386 -nostdlib -std=c89 -Werror -Wall -o asm-i386 - +cat libc-freestanding.c asm-i386.c _start-stub.c | tcc -g -m32 -march=i386 -nostdlib -std=c89 -Werror -Wall -o asm-i386 - + +# -nostdlib segfaults with tcc 0.9.27 +# hangs with git version above 0.9.27 +cat libc-freestanding.c asm-i386.c | tcc -g -m32 -march=i386 -fno-builtin -std=c89 -Werror -Wall -o asm-i386 - +# needs git version above 0.9.27 +cat libc-freestanding.c asm-i386.c _start-stub.c | tcc -g -m32 -march=i386 -nostdlib -std=c89 -Werror -Wall -o asm-i386 - +# to use libc and syscall of the host +cat libc-hosted.c asm-i386.c | tcc -g -m32 -march=i386 -std=c89 -Werror -Wall -o asm-i386 -lbsd - + +# for debugging freestandig mode +cat libc-freestanding.c asm-i386.c > test.c +gcc -g -O0 -m32 -march=i386 -ffreestanding -fno-stack-protector -nostdlib -emain -Werror -Wno-noreturn -Wall -pedantic -fno-pic -std=c89 -o asm-i386 test.c + +# for debugging hosted mode +cat libc-hosted.c asm-i386.c > test.c +gcc -g -O0 -m32 -march=i386 -Werror -Wall -pedantic -std=c89 -o asm-i386 -lbsd test.c + +usage +----- + +# compile +./ec < test1.e > test1.asm +# use the host assembler to produce a binary +fasm test1.asm test1.bin +# use our own minimalistic assembler +./asm-i386 < test1.asm > test1.bin +gcc -g -Wall -std=c99 -o emul emul.c -lunicorn -lcapstone -pthread +./emul test1.bin + +# run test framework +tests/run_tests.sh + +links +----- + +1:10:00 video Hjalfi writes a compiler + +things I got from cowgol: +inner-nested functions/procedures +don't do automatic type promotion, maybe something like uint8, int8, etc. +no recursion, well, we might need that + +4:09:00 video Hjalfi writes an assembler + +no frees as things are freed in the end, well, we don't obey that rule, +compiler/assember should be embedable and they have local scopes which +can be freed while running, thus reducing the memory usage and hence +allowing bigger modules to be comiled/assembled. + +hashtables as simple table on the first character + list, avoids complex +hashtable classes in C. + +pass operator precedence as recursive descent variable (as in retargetable +C compiler). We prefer the hierarchical approach + +syscalls +-------- + +https://www.win.tue.nl/~aeb/linux/lk/lk-4.html + +memory management +----------------- + +nice lecture on the topic: +http://dmitrysoshnikov.com/compilers/writing-a-memory-allocator/ + +https://www.informatik.htw-dresden.de/~beck/ASM/syscall_list.html +sbrk and brk inspiration drawn form rt0 (git@github.com:lpsantil/rt0.git) + +malloc inspired by: +https://arjunsreedharan.org/post/148675821737/memory-allocators-101-write-a-simple-memory +https://github.com/arjun024/memalloc.git + +full bootstrappable compiler +---------------------------- + +we also embedd the needed syscalls (currently Linux 32-bit only): +- exit +- read from stdin +- write to stdout +- brk +the parts of libc we needs are embedded. this mininimalistic libc +uses the syscalls. + +requirements +------------ + +our parser requires a language recursive functions + +const expressions +----------------- + +const + N : integer = 20; + M : integer = 2 * N + 3; + +this needs a small interpreter to create the right constants. If we +have a different target architecture we must emulate that target +architecture's semantic! + +const folding also is desireable for functions: + +function f( x : integer ) : integer +begin + return 2 * x; +end + +const + M : integer = 2 * f( N ); + +This makes the compiler much more complicated, as we have to basically +interpret arbitrary code. + +const folding eliminates the need for a preprocessor, as we can +easily define global constants like platforms, etc. + +const + PLATFORM_BITS : integer = 32; + +type + integer32 : ARRAY[PLATFORM_BITS] OF BIT; + +there are henn-and-egg dragons here! + +but we need it for internal constants like 'true' and 'false' for +initializing a constant of 'boolean'. + +detection of uninitialized variables +------------------------------------ + +this might be very hard and heuristical (and the depend on the compiler +optimization level). Simple flows can be statically analyzed, what +to do when conditions, loops and complex data structures come into place? + +assembler +--------- + +http://ref.x86asm.net/coder32.html +"Art Of Intel x86 Assembly" +Intel® 64 and IA-32 Architectures Software Developer’s Manual +https://www.felixcloutier.com/x86/index.html +http://www.c-jump.com/CIS77/CPU/x86/lecture.html#X77_0140_encoding_add_ecx_eax +https://c9x.me/x86/html/file_module_x86_id_147.html + |