Compare commits

...

71 Commits

Author SHA1 Message Date
Andrius Štikonas 772bfa5329 Fix bootstrap from mes on riscv64. 2023-07-23 20:23:23 +01:00
Andrius Štikonas ee274e0d0c x86_64 tinycc patch 2023-07-23 20:08:24 +01:00
Ekaitz aec9569801 Add debug information 2022-08-28 23:55:13 +02:00
Ekaitz 9d5859e57b Add cmp_r for riscv64 to fix branching 2022-08-28 17:48:43 +02:00
Ekaitz 0e3f4c86d7 Fix `gjmp_*` calls 2022-08-11 14:38:19 +02:00
Ekaitz 7b0774f67b Tentative gtst rewrite 2022-08-10 15:45:51 +02:00
Ekaitz f67c2a680f Move RISCV definitions to the old place -> libtcc.c 2022-08-10 12:22:10 +02:00
Ekaitz c0b50a25a2 WIP: gtst function: lay it out with comments 2022-08-09 20:20:23 +02:00
Ekaitz ef55a31795 Add a manifest file for running the compiler 2022-08-08 18:30:21 +02:00
Ekaitz 8a11993952 Make guix.scm handle lib/libtcc1.c properly:
-> Properly means make it be an empty file :S
2022-08-08 16:41:24 +02:00
Ekaitz ac0c6844e0 Add riscv to conftest 2022-08-08 12:36:54 +02:00
Ekaitz ce78388547 Add RISC-V 64bit support to tccelf.c 2022-08-08 11:47:35 +02:00
Ekaitz 2c8ed6b6cd Fix guix.scm package 2022-08-08 10:58:41 +02:00
Ekaitz 726fbc56e9 guix.scm: Fix extra makefile name 2022-08-05 15:28:39 +02:00
Ekaitz 1de3a740d6 WIP: riscv support backport for mes 2022-08-05 15:28:39 +02:00
Ekaitz a715171766 Guix package: make use of the build scripts provided 2022-07-12 11:57:29 +02:00
Ekaitz 452921d768 Add guix package for tcc and riscv64-tcc 2022-06-29 12:34:25 +02:00
Ekaitz 5054ff8239 Copy RISC-V 64 support to Mes compatible TinyCC 2022-06-29 12:34:25 +02:00
Jan (janneke) Nieuwenhuizen 5bba73ccca
Add ROADMAP.
TODO
  - setjmp
  - possibly: commented-out HAVE_FLOAT? in tccgen.c
  - integrate ARM ./bootstrap.sh build into commencement.scm
    + build gcc-2.95.3 ...etc, etc.

DONE:

  - ./pre-inst-env guix build --system=armhf-linux -e tcc-boot
  - mes-tcc can be bootstrapped, build and and rebuild itself, until
    boot6-tcc, with long longs and floats
2020-12-24 18:39:53 +01:00
Jan (janneke) Nieuwenhuizen 9d675376ce
Revert "HACK bootstrap with arm-unknown-linux-gnueabihf-gcc."
This reverts commit c173a80c284d11f4ade5e6b6fa402a22f78bba9f.
2020-12-24 18:39:53 +01:00
Jan (janneke) Nieuwenhuizen 6b69b496ad
Revert "build-32.sh: Save bootX intermediate results."
This reverts commit af9ef83a3dc59f9456bedeb056fdf8e7d895e6e8.
2020-12-24 18:39:52 +01:00
Jan (janneke) Nieuwenhuizen 02c45923d5
build-32.sh: Save bootX intermediate results. 2020-12-24 18:39:52 +01:00
Jan (janneke) Nieuwenhuizen aab73482fe
HACK bootstrap with arm-unknown-linux-gnueabihf-gcc. 2020-12-24 18:39:52 +01:00
Jan (janneke) Nieuwenhuizen ebd1a5941f
HACK bootstrappable: ARM: "tccgen_ok". 2020-12-24 18:39:52 +01:00
Jan (janneke) Nieuwenhuizen 8d475711f1
HACK bootstrappable: ARM: "tccpp_ok". 2020-12-24 18:39:52 +01:00
Jan (janneke) Nieuwenhuizen 126174a3f6
build: Support building on Guix aarch64-linux. 2020-12-24 18:39:52 +01:00
Jan (janneke) Nieuwenhuizen b693ee0d30
doc: Update 'README'. 2020-12-24 18:39:51 +01:00
Jan (janneke) Nieuwenhuizen 8aa1a0ac36
build: Add support for ARM.
* doit,
bootstrap.sh,
build.sh,
cc.sh: Update and add support for ARM.
* build-x86.sh: Likewise.  Rename to ...
* build-32.sh: ... this.
.gitignore: Remove test output.
2020-12-24 18:39:51 +01:00
Jan (janneke) Nieuwenhuizen 7d55366627
Revert "lotsa debug printing."
This reverts commit 18a9e45500cdaf8dbb34aaab7a4753062a949af6.
2020-12-24 12:15:40 +01:00
Jan (janneke) Nieuwenhuizen 5eb85b0468
Revert "lotsa debug printing: reduce"
This reverts commit 412a9bbfc7d041fda021a86853930b3a90374458.
2020-12-24 12:15:39 +01:00
Jan (janneke) Nieuwenhuizen ad5a6bae59
lotsa debug printing: reduce 2020-12-24 12:15:39 +01:00
Jan Nieuwenhuizen 1d4b206c45
lotsa debug printing. 2020-12-24 12:15:39 +01:00
Jan (janneke) Nieuwenhuizen 8c6f0c2c61
ARM: allow fake asm in functions. 2020-12-24 12:15:39 +01:00
Jan (janneke) Nieuwenhuizen 523498ec01
bootstrappable: ARM: Force eabi header. 2020-12-24 12:15:39 +01:00
Jan (janneke) Nieuwenhuizen 5334d68ee2
bootstrappable: HAVE_LONG_LONG, part 3. 2020-12-24 12:15:39 +01:00
Jan (janneke) Nieuwenhuizen 2cb4f26e26
bootstrappable: ARM: HAVE_FLOAT? 2020-12-24 12:15:38 +01:00
Jan (janneke) Nieuwenhuizen 2613fb5d63
bootstrappable: ARM: generate __memcpy, __memmove, __memset.
* tccgen.c (vstore)[BOOTSTRAP && __arm__]: Generate TOK__memove.
(init_putz): Generate TOK__memset.
* tcctok.h[BOOTSTRAP && __arm__]: Add __memcpy, __memmove, __memset.
2020-12-24 12:15:38 +01:00
Jan (janneke) Nieuwenhuizen fc93202abe
bootstrappable: ARM: HAVE_SETJMP. 2020-12-24 12:15:38 +01:00
Jan (janneke) Nieuwenhuizen 35c9c24614
bootstrappable: HAVE_LONG_LONG_STUB. 2020-12-16 14:28:50 +01:00
Jan (janneke) Nieuwenhuizen bdec98dd01
bootstrappable: HAVE_LONG_LONG, part 2. 2020-12-16 14:28:50 +01:00
Jan (janneke) Nieuwenhuizen 2556e10583
bootstrappable: ARM: HAVE_FLOAT. 2020-12-16 14:28:50 +01:00
Jan (janneke) Nieuwenhuizen fcb48635ce
bootstrappable: ARM: Avoid ternary. 2020-12-16 14:28:49 +01:00
Jan (janneke) Nieuwenhuizen d0608d0d68
bootstrappable: ARM: Avoid ternary in argument.
This avoids depending on "70-ternary-arithmetic-argument.c"

* arm-gen.c (gcall_or_jmp): Split calculation and call.
2020-12-16 14:28:49 +01:00
Jan (janneke) Nieuwenhuizen f7e98b52a1
bootstrappable: ARM: HAVE_FLOAT. 2020-12-16 14:28:49 +01:00
Jan (janneke) Nieuwenhuizen e23023ec8a
bootstrappable: HAVE_FLOAT, part 2. 2020-12-16 14:28:49 +01:00
Jan (janneke) Nieuwenhuizen 907479d7ff
bootstrappable: Avoid function modulo. 2020-12-13 14:53:32 +01:00
Jan (janneke) Nieuwenhuizen 33403a4011
bootstrappable: Avoid using __clear_cache. 2020-12-13 14:53:31 +01:00
Jan (janneke) Nieuwenhuizen 94fa1710aa
bootstrappable: Use tmp initialization instead of for struct assigment. 2020-12-13 14:53:31 +01:00
Jan (janneke) Nieuwenhuizen 35ccd60989
bootstrappable: Support libtcc1-mes.a. 2020-12-13 14:53:31 +01:00
Jan (janneke) Nieuwenhuizen 0334950c24
Revert "bootstrappable: Handle libtcc1.a."
This reverts commit 274bd060fd.
2020-12-13 14:53:31 +01:00
Jan Nieuwenhuizen 20b1a1d001
README: Update to add info about GNU Mes and bootstrappable-tinycc.
* README: Add header on GNU Mes and bootstrappable-tinycc.
2020-02-22 16:31:24 +01:00
Jan Nieuwenhuizen 6e62e0e58b
makefile: Add dist target.
* Makefile (dist): Create reproducible tarball.
2019-11-17 12:06:06 +01:00
Jan Nieuwenhuizen 17df781f70
Revert "lotsa debug printing."
This reverts commit 09cecc93442f2f3b7dbd1bb5faf18b41f42103ff.
2019-10-10 22:40:48 +02:00
Jan Nieuwenhuizen ba1c47dbdb
lotsa debug printing. 2019-10-10 22:40:47 +02:00
Jan Nieuwenhuizen 0585122eb1
build: Update for mes-0.21. 2019-10-10 22:40:47 +02:00
Jan Nieuwenhuizen f90808b155
build: Update for mes-0.20. 2019-04-06 14:16:30 +02:00
Jan Nieuwenhuizen 1063d5a0dc
bootstrappable: Update tccelf.c for mes-0.20. 2019-04-05 14:13:05 +02:00
Jan Nieuwenhuizen 36c0af218f
build: Support gash. 2019-04-04 21:46:55 +02:00
Jan Nieuwenhuizen ec63de4990
test: run tests/tests2 tests. 2019-04-04 21:46:55 +02:00
Jan Nieuwenhuizen cee58e0963
build: Support building from bootstrap-mes. 2019-04-04 21:46:54 +02:00
Jan Nieuwenhuizen 39de35689e
bootstrappable: Force static link. 2019-04-04 21:46:54 +02:00
Jan Nieuwenhuizen 2b6271d1d5
bootstrappable: Work around MesCC bug.
* tccelf.c (squeeze_multi_relocs): Simplify expressions.
2019-04-04 21:46:54 +02:00
Jan Nieuwenhuizen 379c62d63f
bootstrappable: add tcc.h include guards to include location. 2019-04-04 21:46:54 +02:00
Jan Nieuwenhuizen 274bd060fd
bootstrappable: Handle libtcc1.a. 2018-10-04 09:07:18 +02:00
Jan Nieuwenhuizen 6ae9aa40c7
bootstrappable: Skip tidy_section_headers.
* tccelf.c (elf_output_file)[BOOTSTRAPPABLE]: Skip tidy_section_headers.
2018-10-04 09:07:18 +02:00
Jan Nieuwenhuizen a130ce1702
bootstrappable: HAVE_FLOAT. 2018-10-04 09:07:17 +02:00
Jan Nieuwenhuizen de906df43a
bootstrappable: HAVE_BITFIELD. 2018-10-04 09:07:17 +02:00
Jan Nieuwenhuizen 540ba0b456
bootstrappable: HAVE_LONG_LONG.
* tccpp.c (parse_number)[!HAVE_LONG_LONG]: Skip overflow test.  Do not
  set TOK_CCLONG.
2018-10-04 09:07:17 +02:00
Jan Nieuwenhuizen 306f6779ad
bootstrappable: Work around Nyacc-0.80.42 bug.
* tccgen.c (update_storage)[__MESC__]: Work around Nyacc-0.80.42 bug.
2018-10-04 09:07:17 +02:00
Jan Nieuwenhuizen 9c97705c42
build: bootstrap build scripts.
* bootstrap.sh: New file.
* build.sh: New file.
* check.sh: New file.
* doit: New file.
* install.sh: New file.
* test.sh: New file.
2018-10-04 09:07:17 +02:00
Jan Nieuwenhuizen 584478fca2
bootstrappable: Remove non-free grep test.
* tests/tests2/46_grep.c: Remove non-free grep code.
* tests/tests2/46_grep.expect: Remove.
2018-09-18 07:27:57 +02:00
53 changed files with 6009 additions and 614 deletions

1
.gitignore vendored
View File

@ -54,3 +54,4 @@ tests/libtcc_test
tests/vla_test
tests/hello
tests/tests2/fred.txt
tests/tests2/*.1

8
BOOT Normal file
View File

@ -0,0 +1,8 @@
#export LIBRARY_PATH=/home/janneke/src/tinycc-seed
#export INCLUDE_PATH=/home/janneke/src/mes/include
export C_INCLUDE_PATH=/home/janneke/src/mes/include
export LIBRARY_PATH=/home/janneke/src/tinycc-seed
./configure --cc='mes-tcc -static' --cpu=i386
make ONE_SOURCE=yes CPPFLAGS=-DONE_SOURCE=yes

View File

@ -78,6 +78,7 @@ NATIVE_DEFINES_$(CONFIG_arm_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI
NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP
NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64
NATIVE_DEFINES_$(CONFIG_riscv64) += -DTCC_TARGET_RISCV64
NATIVE_DEFINES += $(NATIVE_DEFINES_yes)
ifeq ($(INCLUDED),no)
@ -91,11 +92,11 @@ TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
all: $(PROGS) $(TCCLIBS) $(TCCDOCS)
# cross compiler targets to build
TCC_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince c67
TCC_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince c67 riscv64
# TCC_X += arm-fpa arm-fpa-ld arm-vfp arm-eabi
# cross libtcc1.a targets to build
LIBTCC1_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince
LIBTCC1_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince riscv64
PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF))
LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),libtcc1-$X.a)
@ -132,6 +133,7 @@ DEF-arm-vfp = -DTCC_TARGET_ARM -DTCC_ARM_VFP
DEF-arm-eabi = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI
DEF-arm-eabihf = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
DEF-arm = $(DEF-arm-eabihf)
DEF-riscv64 = -DTCC_TARGET_RISCV64
DEF-$(NATIVE_TARGET) = $(NATIVE_DEFINES)
DEFINES += $(DEF-$T) $(DEF-all)
@ -165,6 +167,7 @@ arm_FILES = $(CORE_FILES) arm-gen.c arm-link.c arm-asm.c
arm-wince_FILES = $(arm_FILES) tccpe.c
arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c
c67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
riscv64_FILES = $(CORE_FILES) riscv64-gen.c riscv64-link.c riscv64-asm.c
# libtcc sources
LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES)))
@ -188,7 +191,7 @@ $(X)%.o : %.c $(LIBTCC_INC)
$(X)tcc.o : tcctools.c
# Host Tiny C Compiler
tcc$(EXESUF): tcc.o $(LIBTCC)
$(PROGRAM_PREFIX)tcc$(EXESUF): tcc.o $(LIBTCC)
$(CC) -o $@ $^ $(LIBS) $(LDFLAGS) $(LINK_LIBTCC)
# Cross Tiny C Compilers
@ -390,3 +393,27 @@ help:
# --------------------------------------------------------------------------
endif # ($(INCLUDED),no)
### dist
.PHONY: dist
PACKAGE=tcc
COMMIT=$(shell git describe --dirty)
CVS_VERSION=$(COMMIT:release_%=%)
TARBALL_VERSION=$(subst _,.,$(CVS_VERSION))
TARBALL_DIR:=$(PACKAGE)-$(TARBALL_VERSION)
TARBALL=$(TARBALL_DIR).tar.gz
# Be friendly to Debian; avoid using EPOCH
MTIME=$(shell git show HEAD --format=%ct --no-patch)
# Reproducible tarball
TAR_FLAGS=--sort=name --mtime=@$(MTIME) --owner=0 --group=0 --numeric-owner --mode=go=rX,u+rw,a-s
$(TARBALL):
(git ls-files \
--exclude=$(TARBALL_DIR); \
echo $^ | tr ' ' '\n') \
| tar $(TAR_FLAGS) \
--transform=s,^,$(TARBALL_DIR)/,S -T- -cf- \
| gzip -c --no-name > $@
dist: $(TARBALL)

85
README
View File

@ -1,3 +1,88 @@
Bootstrappable TCC/TinyCC -- Tiny C Compiler's bootstrappable fork
------------------------------------------------------------------
Bootstrappable TCC is a fork from mainline TCC development, that
started spring 2017 from
commit 307b7b183d4ee56e74090b0e525d6a587840e31f
Author: Aron BARATH <baratharon@caesar.elte.hu>
Date: Tue May 16 07:03:26 2017 +0200
the R_X86_64_GOTOFF64 relocation was missing
and can be compiled by MesCC (https://gnu.org/s/mes).
Initially the plan was to make TinyCC itself "bootstrappable"
(https://bootstrappable.org).
The best way to do so would be to gradually simplify the
implementation of TinyCC by restricting the use of language constructs
to a well-defined subset of C. In bootstrapping each stage or
compiler adds functionality; a compiler that is written in itself --a
so-called `self-hosting' compiler--is not considered to be
bootstrappable.
At the time this vision was not received with much enthousiasm
https://lists.nongnu.org/archive/html/tinycc-devel/2017-09/msg00019.html
so I decided to fork TinyCC and instead grow MesCC (a bootstrappable
sub-C compiler in a subset of Guile Scheme) into a full C99 compiler.
Currently, the Reduced Binary Seed Bootstrap of the GNU Guix System
uses bootstrappable-tinycc. See
https://guix.gnu.org/en/blog/2020/guix-further-reduces-bootstrap-seed-to-25/
https://guix.gnu.org/blog/2019/guix-reduces-bootstrap-seed-by-50/
The fork consists of about 30 patches
ff2210b3 build: Add support for ARM.
f8c8caaf ARM: allow fake asm in functions.
d9ecdebc bootstrappable: ARM: Force eabi header.
82b822c3 bootstrappable: HAVE_LONG_LONG, part 3.
77ae03e8 bootstrappable: ARM: HAVE_FLOAT?
82678555 bootstrappable: ARM: generate __memcpy, __memmove, __memset.
0688c1f5 bootstrappable: ARM: HAVE_SETJMP.
35c9c246 bootstrappable: HAVE_LONG_LONG_STUB.
bdec98dd bootstrappable: HAVE_LONG_LONG, part 2.
2556e105 bootstrappable: ARM: HAVE_FLOAT.
fcb48635 bootstrappable: ARM: Avoid ternary.
d0608d0d bootstrappable: ARM: Avoid ternary in argument.
f7e98b52 bootstrappable: ARM: HAVE_FLOAT.
e23023ec bootstrappable: HAVE_FLOAT, part 2.
907479d7 bootstrappable: Avoid function modulo.
33403a40 bootstrappable: Avoid using __clear_cache.
94fa1710 bootstrappable: Use tmp initialization instead of for struct assigment.
35ccd609 bootstrappable: Support libtcc1-mes.a.
cee58e09 build: Support building from bootstrap-mes.
39de3568 bootstrappable: Force static link.
2b6271d1 bootstrappable: Work around MesCC bug.
379c62d6 bootstrappable: add tcc.h include guards to include location.
6ae9aa40 bootstrappable: Skip tidy_section_headers.
a130ce17 bootstrappable: HAVE_FLOAT.
de906df4 bootstrappable: HAVE_BITFIELD.
540ba0b4 bootstrappable: HAVE_LONG_LONG.
306f6779 bootstrappable: Work around Nyacc-0.80.42 bug.
9c97705c build: bootstrap build scripts.
584478fc bootstrappable: Remove non-free grep test.
that work around bugs and missing C language features in MesCC. Only
three of these are really interesting: the HAVE_* patches that allow
for stepwise introduction of bitfields, doubles/floats and long longs.
In time, I hope we can remove the need for this fork; either by
upstreaming some bootstrappable work or else by maturing MesCC.
At the time of writing, mainline (non-bootstrappable) tinycc lives
here
https://repo.or.cz/tinycc.git
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
--
janneke
Tiny C Compiler - C Scripting Everywhere - The Smallest ANSI C compiler
-----------------------------------------------------------------------

220
ROADMAP Normal file

File diff suppressed because one or more lines are too long

View File

@ -70,7 +70,6 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
uint8_t *clobber_regs,
int out_reg)
{
asm_error();
}
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
@ -78,7 +77,6 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
const uint8_t *clobber_regs,
int *pout_reg)
{
asm_error();
}
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)

View File

@ -636,7 +636,14 @@ void load(int r, SValue *sv)
} else if (v < VT_CONST) {
if(is_float(ft))
#ifdef TCC_ARM_VFP
#if !BOOTSTRAP
o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */
#else
{
int t = 0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft);
o(t); /* fcpyX */
}
#endif
#else
o(0xEE008180|(fpr(r)<<12)|fpr(v));
#endif
@ -749,7 +756,12 @@ static void gcall_or_jmp(int is_jmp)
greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);
} else
put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, 0);
#if !BOOTSTRAP
o(x|(is_jmp?0xE0000000:0xE1000000));
#else
x |= (is_jmp?0xE0000000:0xE1000000);
o(x);
#endif
} else {
if(!is_jmp)
o(0xE28FE004); // add lr,pc,#4
@ -804,7 +816,11 @@ struct avail_regs {
int first_free_reg; /* next free register in the sequence, hole excluded */
};
#if !BOOTSTRAP
#define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 }
#else
#define AVAIL_REGS_INITIALIZER {0}
#endif
/* Find suitable registers for a VFP Co-Processor Register Candidate (VFP CPRC
param) according to the rules described in the procedure call standard for
@ -959,6 +975,7 @@ static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo)
*todo = 0;
plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans));
memset(plan->clsplans, 0, sizeof(plan->clsplans));
for(i = nb_args; i-- ;) {
int j, start_vfpreg = 0;
CType type = vtop[-i].type;
@ -981,7 +998,12 @@ static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo)
start_vfpreg = assign_vfpreg(&avregs, align, size);
end_vfpreg = start_vfpreg + ((size - 1) >> 2);
if (start_vfpreg >= 0) {
#if !BOOTSTRAP
pplan = (struct param_plan) {start_vfpreg, end_vfpreg, &vtop[-i]};
#else
struct param_plan tmp = {start_vfpreg, end_vfpreg, &vtop[-i]};
pplan = tmp;
#endif
if (is_hfa)
add_param_plan(plan, pplan, VFP_STRUCT_CLASS);
else
@ -998,7 +1020,14 @@ static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo)
* CORE_STRUCT_CLASS or the first of STACK_CLASS. */
for (j = ncrn; j < 4 && j < ncrn + size / 4; j++)
*todo|=(1<<j);
#if !BOOTSTRAP
pplan = (struct param_plan) {ncrn, j, &vtop[-i]};
#else
{
struct param_plan tmp = {ncrn, j, &vtop[-i]};
pplan = tmp;
}
#endif
add_param_plan(plan, pplan, CORE_STRUCT_CLASS);
ncrn += size/4;
if (ncrn > 4)
@ -1017,7 +1046,12 @@ static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo)
if (ncrn == 4)
break;
}
#if !BOOTSTRAP
pplan = (struct param_plan) {ncrn, ncrn, &vtop[-i]};
#else
struct param_plan tmp = {ncrn, ncrn, &vtop[-i]};
pplan = tmp;
#endif
ncrn++;
if (is_long)
pplan.end = ncrn++;
@ -1026,7 +1060,14 @@ static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo)
}
}
nsaa = (nsaa + (align - 1)) & ~(align - 1);
#if !BOOTSTRAP
pplan = (struct param_plan) {nsaa, nsaa + size, &vtop[-i]};
#else
{
struct param_plan tmp = {nsaa, nsaa + size, &vtop[-i]};
pplan = tmp;
}
#endif
add_param_plan(plan, pplan, STACK_CLASS);
nsaa += size; /* size already rounded up before */
}
@ -1439,7 +1480,12 @@ int gtst(int inv, int t)
if (nocode_wanted) {
;
} else if (v == VT_CMP) {
#if !BOOTSTRAP
op=mapcc(inv?negcc(vtop->c.i):vtop->c.i);
#else
int tmp_arg = inv?negcc(vtop->c.i):vtop->c.i;
op=mapcc(tmp_arg);
#endif
op|=encbranch(r,t,1);
o(op);
t=r;
@ -1643,6 +1689,7 @@ done:
#ifdef TCC_ARM_VFP
static int is_zero(int i)
{
#if HAVE_FLOAT
if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
return 0;
if (vtop[i].type.t == VT_FLOAT)
@ -1650,6 +1697,9 @@ static int is_zero(int i)
else if (vtop[i].type.t == VT_DOUBLE)
return (vtop[i].c.d == 0.0);
return (vtop[i].c.ld == 0.l);
#else
return 0;
#endif
}
/* generate a floating point operation 'v = t1 op t2' instruction. The
@ -1746,6 +1796,7 @@ void gen_opf(int op)
#else
static uint32_t is_fconst()
{
#if HAVE_FLOAT
long double f;
uint32_t r;
if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
@ -1779,6 +1830,7 @@ static uint32_t is_fconst()
return r|6;
if(f==10.0)
return r|7;
#endif
return 0;
}
@ -1965,7 +2017,12 @@ ST_FUNC void gen_cvt_itof1(int t)
r2|=r2<<12;
if(!(vtop->type.t & VT_UNSIGNED))
r2|=0x80; /* fuitoX -> fsituX */
#if !BOOTSTRAP
o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/
#else
int x = 0xEEB80A40|r2|T2CPR(t);
o(x); /* fYitoX*/
#endif
#else
r2=fpr(vtop->r=get_reg(RC_FLOAT));
if((t & VT_BTYPE) != VT_FLOAT)
@ -2041,7 +2098,12 @@ void gen_cvt_ftoi(int t)
#ifdef TCC_ARM_VFP
r=vfpr(gv(RC_FLOAT));
u=u?0:0x10000;
#if !BOOTSTRAP
o(0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u); /* ftoXizY */
#else
int x =0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u;
o(x); /* ftoXizY */
#endif
r2=intr(vtop->r=get_reg(RC_INT));
o(0xEE100A10|(r<<16)|(r2<<12));
return;
@ -2095,7 +2157,12 @@ void gen_cvt_ftof(int t)
#ifdef TCC_ARM_VFP
if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) {
uint32_t r = vfpr(gv(RC_FLOAT));
#if !BOOTSTRAP
o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t));
#else
int x = 0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t);
o(x);
#endif
}
#else
/* all we have to do on i386 and FPA ARM is to put the float in a register */

241
boot.sh Executable file
View File

@ -0,0 +1,241 @@
#! /bin/sh
set -e
if [ "$V" = 1 -o "$V" = 2 ]; then
set -x
fi
arch=${arch-$(uname -m)}
case $arch in
aarch*)
cpu=arm
mes_cpu=arm
tcc_cpu=arm
triplet=arm-linux-gnueabihf
cross_prefix=${triplet}-
;;
arm*|aarch*)
cpu=arm
mes_cpu=arm
tcc_cpu=arm
triplet=arm-unknown-linux-gnueabihf
cross_prefix=${triplet}-
;;
*)
cpu=x86
mes_cpu=x86
tcc_cpu=i386
triplet=i686-unknown-linux-gnu
cross_prefix=${triplet}-
;;
esac
if [ "$TCC" = ./mes-tcc ]; then
program_prefix=${program_prefix-boot0-}
elif [ "$TCC" = ./boot0-tcc ]; then
program_prefix=${program_prefix-boot1-}
elif [ "$TCC" = ./boot1-tcc ]; then
program_prefix=${program_prefix-boot2-}
elif [ "$TCC" = ./boot2-tcc ]; then
program_prefix=${program_prefix-boot3-}
elif [ "$TCC" = ./boot3-tcc ]; then
program_prefix=${program_prefix-boot4-}
elif [ "$TCC" = ./boot4-tcc ]; then
program_prefix=${program_prefix-boot5-}
elif [ "$TCC" = ./boot5-tcc ]; then
program_prefix=${program_prefix-boot6-}
elif [ "$TCC" = ./boot6-tcc ]; then
program_prefix=${program_prefix-boot7-}
elif [ "$TCC" = ./boot7-tcc ]; then
program_prefix=${program_prefix-boot8-}
elif [ "$TCC" = ./boot8-tcc ]; then
program_prefix=${program_prefix-boot9-}
elif [ "$TCC" = ./gcc-tcc ]; then
program_prefix=${program_prefix-boot0-}
elif [ "$TCC" = ${cross_prefix}gcc ]; then
program_prefix=${program_prefix-boot0-}
elif [ "$TCC" = ./${cross_prefix}tcc ]; then
program_prefix=${program_prefix-boot0-}
else
program_prefix=${program_prefix-foo-}
fi
unset C_INCLUDE_PATH LIBRARY_PATH
prefix=${prefix-/usr/local}
mkdir -p $prefix
absprefix=$(cd $prefix && pwd)
GUIX=${GUIX-$(command -v guix||:)}
MES_PREFIX=${MES_PREFIX-mes}
MES_LIB=${MES_LIB-$MES_PREFIX/lib}
C_INCLUDE_PATH=${C_INCLUDE_PATH-$MES_PREFIX/include}
LIBRARY_PATH=${LIBRARY_PATH-..$MES_PREFIX/lib}
interpreter=/lib/mes-loader
if [ "$program_prefix" = "boot0-" ]; then
BOOT_CPPFLAGS_TCC="
-D BOOTSTRAP=1
"
if $have_long_long; then
BOOT_CPPFLAGS_TCC="$BOOT_CPPFLAGS_TCC -D HAVE_LONG_LONG_STUB=1"
fi
elif [ "$program_prefix" = "boot1-" ]; then
BOOT_CPPFLAGS_TCC="
-D BOOTSTRAP=1
-D HAVE_BITFIELD=1
"
if $have_long_long; then
BOOT_CPPFLAGS_TCC="$BOOT_CPPFLAGS_TCC -D HAVE_LONG_LONG=1"
fi
elif [ "$program_prefix" = "boot2-" ]; then
BOOT_CPPFLAGS_TCC="
-D BOOTSTRAP=1
-D HAVE_BITFIELD=1
"
if $have_float; then
BOOT_CPPFLAGS_TCC="$BOOT_CPPFLAGS_TCC -D HAVE_FLOAT_STUB=1"
fi
if $have_long_long; then
BOOT_CPPFLAGS_TCC="$BOOT_CPPFLAGS_TCC -D HAVE_LONG_LONG=1"
fi
elif [ "$program_prefix" = "boot3-" ]; then
BOOT_CPPFLAGS_TCC="
-D BOOTSTRAP=1
-D HAVE_BITFIELD=1
"
if $have_float; then
BOOT_CPPFLAGS_TCC="$BOOT_CPPFLAGS_TCC -D HAVE_FLOAT=1"
fi
if $have_long_long; then
BOOT_CPPFLAGS_TCC="$BOOT_CPPFLAGS_TCC -D HAVE_LONG_LONG=1"
fi
else
BOOT_CPPFLAGS_TCC="
-D BOOTSTRAP=1
-D HAVE_BITFIELD=1
"
if $have_float; then
BOOT_CPPFLAGS_TCC="$BOOT_CPPFLAGS_TCC -D HAVE_FLOAT=1"
fi
if $have_long_long; then
BOOT_CPPFLAGS_TCC="$BOOT_CPPFLAGS_TCC -D HAVE_LONG_LONG=1"
fi
fi
if $have_setjmp; then
BOOT_CPPFLAGS_TCC="$BOOT_CPPFLAGS_TCC -D HAVE_SETJMP=1"
fi
if test "$mes_cpu" = x86; then
CPP_TARGET_FLAG="-D TCC_TARGET_I386=1"
elif test "$mes_cpu" = arm; then
CPP_TARGET_FLAG="-D TCC_TARGET_ARM=1 -D TCC_ARM_VFP=1 -D CONFIG_TCC_LIBTCC1_MES=1"
elif test "$mes_cpu" = x86_64; then
BOOT_CPPFLAGS_TCC="$BOOT_CPPFLAGS_TCC -D HAVE_SETJMP=1"
CPP_TARGET_FLAG="-D TCC_TARGET_X86_64=1"
else
echo "cpu not supported: $mes_cpu"
fi
CPPFLAGS_TCC="
-I .
-I $MES_PREFIX/lib
-I $MES_PREFIX/include
$CPP_TARGET_FLAG
-D inline=
-D CONFIG_TCCDIR=\"$prefix/lib/tcc\"
-D CONFIG_TCC_CRTPREFIX=\"$prefix/lib:"{B}"/lib:.\"
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"
-D CONFIG_TCC_LIBPATHS=\"$prefix/lib:"{B}"/lib:.\"
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$prefix/include:"{B}"/include\"
-D TCC_LIBGCC=\"$prefix/lib/libc.a\"
-D TCC_LIBTCC1_MES=\"libtcc1-mes.a\"
-D CONFIG_TCCBOOT=1
-D CONFIG_TCC_STATIC=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"
if $ONE_SOURCE; then
CPPFLAGS_TCC="$CPPFLAGS_TCC -D ONE_SOURCE=1"
fi
if $ONE_SOURCE; then
files="tcc.c"
else
$TCC -g -v -c $BOOT_CPPFLAGS_TCC $CPPFLAGS_TCC tccpp.c
$TCC -g -v -c $BOOT_CPPFLAGS_TCC $CPPFLAGS_TCC tccgen.c
$TCC -g -v -c $BOOT_CPPFLAGS_TCC $CPPFLAGS_TCC tccelf.c
$TCC -g -v -c $BOOT_CPPFLAGS_TCC $CPPFLAGS_TCC tccrun.c
$TCC -g -v -c $BOOT_CPPFLAGS_TCC $CPPFLAGS_TCC ${tcc_cpu}-gen.c
$TCC -g -v -c $BOOT_CPPFLAGS_TCC $CPPFLAGS_TCC ${tcc_cpu}-link.c
$TCC -g -v -c $BOOT_CPPFLAGS_TCC $CPPFLAGS_TCC ${tcc_cpu}-asm.c
$TCC -g -v -c $BOOT_CPPFLAGS_TCC $CPPFLAGS_TCC tccasm.c
$TCC -g -v -c $BOOT_CPPFLAGS_TCC $CPPFLAGS_TCC libtcc.c
$TCC -g -v -c $BOOT_CPPFLAGS_TCC $CPPFLAGS_TCC tcc.c
files="
tccpp.o
tccgen.o
tccelf.o
tccrun.o
${tcc_cpu}-gen.o
${tcc_cpu}-link.o
${tcc_cpu}-asm.o
tccasm.o
libtcc.o
tcc.o
"
fi
echo $TCC \
-g \
-v \
-static \
-o ${program_prefix}tcc \
$BOOT_CPPFLAGS_TCC \
$CPPFLAGS_TCC \
-L . \
$files
$TCC \
-g \
-v \
-static \
-o ${program_prefix}tcc \
$BOOT_CPPFLAGS_TCC \
$CPPFLAGS_TCC \
-L . \
$files
if $REBUILD_LIBC; then
for i in 1 i n; do
cp -f $MES_LIB/crt$i.c .
./${program_prefix}tcc -c -g -o ${program_prefix}crt$i.o crt$i.c
cp -f ${program_prefix}crt$i.o crt$i.o
done
rm -f libtcc1.a
./${program_prefix}tcc -c -g $CPP_TARGET_FLAG -D HAVE_FLOAT=1 -o libtcc1.o $MES_LIB/libtcc1.c
./${program_prefix}tcc -ar rc libtcc1.a libtcc1.o
if [ $mes_cpu = arm ]; then
./${program_prefix}tcc -c -g $BOOT_CPPFLAGS lib/armeabi.c
./${program_prefix}tcc -c -g $CPP_TARGET_FLAG $BOOT_CPPFLAGS_TCC -o libtcc1-tcc.o lib/libtcc1.c
./${program_prefix}tcc -ar rc libtcc1-tcc.a libtcc1-tcc.o armeabi.o
# BOOTSTRAP: => Bus error
##./${program_prefix}tcc -c -g $CPP_TARGET_FLAG $BOOT_CPPFLAGS_TCC -o libtcc1-mes.o $MES_LIB/libtcc1.c
##./${program_prefix}tcc -c -g $CPP_TARGET_FLAG -D BOOTSTRAP=1 -D HAVE_FLOAT=1 -D HAVE_LONG_LONG=1 -o libtcc1-mes.o $MES_LIB/libtcc1.c
./${program_prefix}tcc -c -g $CPP_TARGET_FLAG -D HAVE_FLOAT=1 -D HAVE_LONG_LONG=1 -o libtcc1-mes.o $MES_LIB/libtcc1.c
./${program_prefix}tcc -ar rc libtcc1-mes.a libtcc1-mes.o armeabi.o
./${program_prefix}tcc -c -g $CPP_TARGET_FLAG $BOOT_CPPFLAGS_TCC -o libtcc1.o lib/libtcc1.c
./${program_prefix}tcc -ar rc libtcc1.a libtcc1.o armeabi.o
cp -f libtcc1-mes.a $prefix/lib/tcc
fi
cp -f libtcc1.a $prefix/lib/tcc
fi
echo "boot.sh: done"

257
bootstrap.sh Executable file
View File

@ -0,0 +1,257 @@
#! /bin/sh
set -e
if test "$V" = 1 -o "$V" = 2; then
set -x
fi
MESCC=${MESCC-$(command -v mescc)}
if test "$V" = 2; then
sh $MESCC --help
fi
host=${host-$($MESCC -dumpmachine 2>/dev/null)}
if test -z "$host$host_type"; then
mes_cpu=${arch-$(get_machine || uname -m)}
else
mes_cpu=${host%%-*}
fi
case "$mes_cpu" in
i386|i486|i586|i686|x86)
mes_cpu=x86
tcc_cpu=i386
have_float=${have_float-true}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-true}
;;
armv4|armv7l|arm)
mes_cpu=arm
tcc_cpu=arm
have_float=${have_float-true}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-false}
;;
amd64)
tcc_cpu=x86_64
mes_cpu=x86_64
have_float=${have_float-true}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-true}
;;
esac
case "$host" in
*linux-gnu|*linux)
mes_kernel=linux;;
*gnu)
mes_kernel=gnu;;
*)
mes_kernel=linux;;
esac
export mes_cpu
export tcc_cpu
export have_float
export have_long_long
export have_setjmp
prefix=${prefix-/usr/local}
MES_PREFIX=${MES_PREFIX-mes}
MES_STACK=${MES_STACK-10000000}
export MES_STACK
interpreter=${interpreter-/mes/loader}
MES_LIB=${MES_LIB-$MES_PREFIX/lib}
MES_SOURCE=${MES_SOURCE-mes-source}
#MES_LIB=$MES_SOURCE/gcc-lib/${mes_cpu}-mes
export MES_SOURCE
export MES_PREFIX
export MES_LIB
ONE_SOURCE=${ONE_SOURCE-false}
export ONE_SOURCE
CPPFLAGS="
-I $MES_PREFIX/lib
-I $MES_PREFIX/include
-D BOOTSTRAP=1
"
if test "$mes_cpu" = x86; then
CPP_TARGET_FLAG=" -D TCC_TARGET_I386=1"
elif test "$mes_cpu" = arm; then
CPP_TARGET_FLAG="-D TCC_TARGET_ARM=1 -D TCC_ARM_VFP=1 -D CONFIG_TCC_LIBTCC1_MES=1"
elif test "$mes_cpu" = x86_64; then
CPP_TARGET_FLAG=" -D TCC_TARGET_X86_64=1"
else
echo "cpu not supported: $mes_cpu"
fi
CPPFLAGS_TCC="$CPPFLAGS
-I .
$CPP_TARGET_FLAG
-D inline=
-D CONFIG_TCCDIR=\"$prefix/lib/tcc\"
-D CONFIG_TCC_CRTPREFIX=\"$prefix/lib:"{B}"/lib:.\"
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"
-D CONFIG_TCC_LIBPATHS=\"$prefix/lib:"{B}"/lib:.\"
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$prefix/include:"{B}"/include\"
-D TCC_LIBGCC=\"$prefix/lib/libc.a\"
-D TCC_LIBTCC1_MES=\"libtcc1-mes.a\"
-D CONFIG_TCCBOOT=1
-D CONFIG_TCC_STATIC=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"
if $ONE_SOURCE; then
files="tcc.s"
CPPFLAGS_TCC="$CPPFLAGS_TCC -D ONE_SOURCE=1"
else
files="tccpp.s tccgen.s tccelf.s tccrun.s ${tcc_cpu}-gen.s ${tcc_cpu}-link.s ${tcc_cpu}-asm.s tccasm.s libtcc.s tcc.s"
fi
CFLAGS=
if test "$V" = 1; then
CFLAGS="$CFLAGS -v"
elif test "$V" = 2; then
CFLAGS="$CFLAGS -v -v"
fi
for f in $files; do
i=$(basename $f .s)
[ -z "$V" ] && echo " CC $i.c"
sh $MESCC \
-S \
-o $f \
$CPPFLAGS_TCC \
$CFLAGS \
$i.c
done
[ -z "$V" ] && echo " CCLD mes-tcc"
sh $MESCC $verbose -o mes-tcc -L $MES_SOURCE/mescc-lib -L $MES_SOURCE/lib $files -l c+tcc
CC="./mes-tcc"
AR="./mes-tcc -ar"
CPPFLAGS="
-I $MES_PREFIX/include
-I $MES_PREFIX/include/$mes_kernel/$mes_cpu
-I $MES_PREFIX/lib
-D BOOTSTRAP=1
"
CFLAGS=
REBUILD_LIBC=${REBUILD_LIBC-true}
export REBUILD_LIBC
mkdir -p $prefix/lib/tcc
if $REBUILD_LIBC; then
for i in 1 i n; do
rm -f crt$i.o;
cp -f $MES_LIB/crt$i.c .
$CC $CPPFLAGS $CFLAGS -static -nostdlib -nostdinc -c crt$i.c
done
rm -f libc.a
cp -f $MES_LIB/libc+gnu.c libc.c
$CC -c $CPPFLAGS $CFLAGS libc.c
$AR cr libc.a libc.o
rm -f libtcc1.a
cp -f $MES_LIB/libtcc1.c .
$CC -c $CPPFLAGS $CFLAGS libtcc1.c
$AR cr libtcc1.a libtcc1.o
if [ $mes_cpu = arm ]; then
$CC -c $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG lib/armeabi.c
$CC -c $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG lib/libtcc1.c
$AR cr libtcc1.a libtcc1.o armeabi.o
$CC -c $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG -o libtcc1-mes.o $MES_LIB/libtcc1.c
# $AR cr libtcc1-mes.a libtcc1-mes.o armeabi.o
$AR cr libtcc1-mes.a libtcc1-mes.o
cp -f libtcc1-mes.a $prefix/lib/tcc
fi
rm -f libgetopt.a
cp -f $MES_LIB/libgetopt.c .
$CC -c $CPPFLAGS $CFLAGS libgetopt.c
$AR cr libgetopt.a libgetopt.o
else
cp -f $MES_LIB/crt1.o .
cp -f $MES_LIB/crti.o .
cp -f $MES_LIB/crtn.o .
cp -f $MES_LIB/libc+gnu.a .
cp -f $MES_LIB/libtcc1.a .
cp -f $MES_LIB/libgetopt.a .
if [ $mes_cpu = arm ]; then
$CC -c $CPPFLAGS $CFLAGS $MES_LIB/libtcc1.c
$CC -c $CPPFLAGS $CFLAGS lib/armeabi.c
$AR cr libtcc1.a libtcc1.o armeabi.o
fi
fi
cp -f libc.a $prefix/lib
cp -f libtcc1.a $prefix/lib/tcc
cp -f libgetopt.a $prefix/lib
export mes_cpu
export prefix
export CPPFLAGS
TCC=./mes-tcc sh boot.sh
TCC=./boot0-tcc sh boot.sh
TCC=./boot1-tcc sh boot.sh
TCC=./boot2-tcc sh boot.sh
TCC=./boot3-tcc sh boot.sh
TCC=./boot4-tcc sh boot.sh
TCC=./boot5-tcc sh boot.sh
if cmp --help; then
cmp boot5-tcc boot6-tcc
fi
cp -f boot5-tcc tcc
CC=./tcc
AR='./tcc -ar'
if true; then
for i in 1 i n; do
rm -f crt$i.o;
cp -f $MES_LIB/crt$i.c .
$CC -c -g $CPPFLAGS $CFLAGS -static -nostdlib -nostdinc crt$i.c
done
rm -f libc.a
$CC -c -g $CPPFLAGS $CFLAGS libc.c
$AR cr libc.a libc.o
rm -f libtcc1.a
$CC -c -g $CPPFLAGS $CPP_TARGET_FLAG $CFLAGS lib/libtcc1.c
$AR cr libtcc1.a libtcc1.o
if [ $mes_cpu = arm ]; then
$CC -c -g $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG lib/armeabi.c
$CC -c -g $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG -o libtcc1-tcc.o lib/libtcc1.c
$AR rc libtcc1-tcc.a libtcc1-tcc.o armeabi.o
$CC -c -g $CPPFLAGS $CFLAGS -D HAVE_FLOAT=1 -D HAVE_LONG_LONG=1 libtcc1-mes.o $MES_LIB/libtcc1.c
$AR cr libtcc1-mes.a libtcc1-mes.o armeabi.o
$CC -c -g $CPP_TARGET_FLAG $CFLAGS -o libtcc1.o lib/libtcc1.c
$AR cr libtcc1.a libtcc1.o armeabi.o
cp -f libtcc1-tcc.a $prefix/lib/tcc
cp -f libtcc1-mes.a $prefix/lib/tcc
fi
rm -f libgetopt.a
$CC -c -g $CPPFLAGS $CFLAGS libgetopt.c
$AR cr libgetopt.a libgetopt.o
cp -f libc.a $prefix/lib
cp -f libtcc1.a $prefix/lib/tcc
cp -f libgetopt.a $prefix/lib
fi
echo "bootstrap.sh: done"

303
build-32.sh Executable file
View File

@ -0,0 +1,303 @@
#! /bin/sh
set -e
if test "$V" = 1 -o "$V" = 2; then
set -x
fi
arch=$(uname -m)
case $arch in
aarch*)
cpu=arm
mes_cpu=arm
tcc_cpu=arm
triplet=arm-linux-gnueabihf
cross_prefix=${triplet}-
have_float=${have_float-false}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-false}
;;
arm*|aarch)
cpu=arm
mes_cpu=arm
tcc_cpu=arm
triplet=arm-unknown-linux-gnueabihf
cross_prefix=${triplet}-
have_float=${have_float-false}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-false}
;;
*)
cpu=x86
mes_cpu=x86
tcc_cpu=i386
triplet=i686-unknown-linux-gnu
cross_prefix=${triplet}-
have_float=${have_float-true}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-true}
;;
esac
case "$host" in
*linux-gnu|*linux)
mes_kernel=linux;;
*gnu)
mes_kernel=gnu;;
*)
mes_kernel=linux;;
esac
export cpu
export cross_prefix
export mes_cpu
export tcc_cpu
export triplet
export have_float
export have_long_long
export have_setjmp
prefix=${prefix-usr}
export prefix
MES_PREFIX=${MES_PREFIX-mes-source}
MES_SOURCE=${MES_SOURCE-mes-source}
MES_LIB=${MES_LIB-$MES_PREFIX/lib}
MES_LIB=$MES_SOURCE/gcc-lib/${mes_cpu}-mes
ONE_SOURCE=${ONE_SOURCE-false}
export V
export MESCC
export MES_DEBUG
export MES_PREFIX
export MES_LIB
export MES_SOURCE
export ONE_SOURCE
export REBUILD_LIBC
CC=${CC-${cross_prefix}gcc}
CPPFLAGS="
-I $MES_PREFIX/include
-I $MES_PREFIX/include/$mes_kernel/$mes_cpu
-I $MES_PREFIX/lib
-D BOOTSTRAP=1
"
CFLAGS="
-fpack-struct
-nostdinc
-nostdlib
-fno-builtin
"
if test "$mes_cpu" = x86; then
CPP_TARGET_FLAG="-D TCC_TARGET_I386=1"
elif test "$mes_cpu" = arm; then
CFLAGS="$CFLAGS -marm"
CPP_TARGET_FLAG="-D TCC_TARGET_ARM=1 -D TCC_ARM_VFP=1 -D CONFIG_TCC_LIBTCC1_MES=1"
elif test "$mes_cpu" = x86_64; then
CPP_TARGET_FLAG="-D TCC_TARGET_X86_64=1"
else
echo "cpu not supported: $mes_cpu"
fi
rm -f mes
ln -sf $MES_PREFIX mes
rm -f ${cross_prefix}tcc
unset C_INCLUDE_PATH LIBRARY_PATH
$CC -c $CPPFLAGS $CFLAGS $MES_PREFIX/lib/linux/$mes_cpu-mes-gcc/crt1.c
$CC -c $CPPFLAGS $CFLAGS $MES_PREFIX/lib/linux/$mes_cpu-mes-gcc/crti.c
$CC -c $CPPFLAGS $CFLAGS $MES_PREFIX/lib/linux/$mes_cpu-mes-gcc/crtn.c
cp $MES_LIB/libc+tcc.a .
cp $MES_LIB/libtcc1.a .
cp $MES_LIB/libc+tcc.a libc.a
mkdir -p $prefix/lib
absprefix=$(cd $prefix && pwd)
interpreter=/lib/mes-loader
export interpreter
if $ONE_SOURCE; then
CFLAGS="$CFLAGS
--include=$MES_SOURCE/lib/linux/$cpu-mes-gcc/crt1.c
-Wl,-Ttext-segment=0x1000000
"
else
LDFLAGS="
-L .
--include=$MES_SOURCE/lib/linux/$cpu-mes-gcc/crt1.c
-Wl,-Ttext-segment=0x1000000
"
fi
CPPFLAGS_TCC="$CPPFLAGS
-I .
$CPP_TARGET_FLAG
-D inline=
-D CONFIG_TCCDIR=\"$prefix/lib/tcc\"
-D CONFIG_TCC_CRTPREFIX=\"$prefix/lib:"{B}"/lib:.\"
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"
-D CONFIG_TCC_LIBPATHS=\"$prefix/lib:"{B}"/lib:.\"
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$prefix/include:"{B}"/include\"
-D TCC_LIBGCC=\"$prefix/lib/libc.a\"
-D TCC_LIBTCC1_MES=\"libtcc1-mes.a\"
-D CONFIG_TCCBOOT=1
-D CONFIG_TCC_STATIC=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"
if $ONE_SOURCE; then
CPPFLAGS_TCC="$CPPFLAGS_TCC -D ONE_SOURCE=1"
fi
if $ONE_SOURCE; then
$CC -g -o ${cross_prefix}tcc \
$CFLAGS \
$CPPFLAGS_TCC \
tcc.c \
libtcc1.a \
libc.a \
-lgcc \
libc.a
else
$CC -g -c $CFLAGS $CPPFLAGS_TCC tccpp.c
$CC -g -c $CFLAGS $CPPFLAGS_TCC tccgen.c
$CC -g -c $CFLAGS $CPPFLAGS_TCC tccelf.c
$CC -g -c $CFLAGS $CPPFLAGS_TCC tccrun.c
$CC -g -c $CFLAGS $CPPFLAGS_TCC ${tcc_cpu}-gen.c
$CC -g -c $CFLAGS $CPPFLAGS_TCC ${tcc_cpu}-link.c
$CC -g -c $CFLAGS $CPPFLAGS_TCC ${tcc_cpu}-asm.c
$CC -g -c $CFLAGS $CPPFLAGS_TCC tccasm.c
$CC -g -c $CFLAGS $CPPFLAGS_TCC libtcc.c
$CC -g -c $CFLAGS $CPPFLAGS_TCC tcc.c
files="
tccpp.o
tccgen.o
tccelf.o
tccrun.o
${tcc_cpu}-gen.o
${tcc_cpu}-link.o
${tcc_cpu}-asm.o
tccasm.o
libtcc.o
tcc.o
"
$CC \
-g \
$LDFLAGS \
$CPPFLAGS_TCC \
-o ${cross_prefix}tcc \
$files \
libtcc1.a \
libc.a \
-lgcc \
libc.a
fi
rm -rf ${cross_prefix}gcc-usr
mkdir -p ${cross_prefix}gcc-usr
cp *.a ${cross_prefix}gcc-usr
cp *.o ${cross_prefix}gcc-usr
mkdir -p $prefix/lib/tcc
cp -f libc.a $prefix/lib
cp -f libtcc1.a $prefix/lib/tcc
rm -f armeabi.o
cp libtcc1.a libtcc1-mes.a
# REBUILD_LIBC=true
# TCC=$CC sh -x boot.sh
# REBUILD_LIBC=true
# TCC=./boot0-tcc sh boot.sh
# TCC=./boot1-tcc sh boot.sh
# TCC=./boot2-tcc sh boot.sh
# TCC=./boot3-tcc sh boot.sh
# TCC=./boot4-tcc sh boot.sh
# TCC=./boot5-tcc sh boot.sh
# TCC=./boot6-tcc sh boot.sh
# exit 22
rm -rf ${cross_prefix}gcc-boot
mkdir -p ${cross_prefix}gcc-boot
cp *.a ${cross_prefix}gcc-boot
cp *.o ${cross_prefix}gcc-boot
CC="./${cross_prefix}tcc"
AR="./${cross_prefix}tcc -ar"
CFLAGS=
REBUILD_LIBC=${REBUILD_LIBC-true}
$CC -c $CPPFLAGS $CFLAGS $MES_PREFIX/lib/linux/$mes_cpu-mes-gcc/crt1.c
$CC -c $CPPFLAGS $CFLAGS $MES_PREFIX/lib/linux/$mes_cpu-mes-gcc/crti.c
$CC -c $CPPFLAGS $CFLAGS $MES_PREFIX/lib/linux/$mes_cpu-mes-gcc/crtn.c
cp $MES_LIB/libc+tcc.a .
cp $MES_LIB/libtcc1.a .
cp $MES_LIB/libc+tcc.a libc.a
mkdir -p $prefix/lib/tcc
if $REBUILD_LIBC; then
for i in 1 i n; do
rm -f crt$i.o;
cp -f $MES_LIB/crt$i.c .
$CC $CPPFLAGS $CFLAGS -static -nostdlib -nostdinc -c crt$i.c
done
rm -f libc.a
cp -f $MES_LIB/libc+gnu.c libc.c
$CC -c $CPPFLAGS $CFLAGS libc.c
$AR cr libc.a libc.o
rm -f libtcc1.a
cp -f $MES_LIB/libtcc1.c .
$CC -c $CPPFLAGS $CPP_TARGET_FLAG $CFLAGS lib/libtcc1.c
$AR cr libtcc1.a libtcc1.o
if [ $mes_cpu = arm ]; then
$CC -c -g $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG lib/armeabi.c
$CC -c -g $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG -o libtcc1-tcc.o lib/libtcc1.c
$AR rc libtcc1-tcc.a libtcc1-tcc.o armeabi.o
$CC -c -g $CPPFLAGS $CFLAGS -D HAVE_FLOAT=1 -D HAVE_LONG_LONG=1 -o libtcc1-mes.o $MES_LIB/libtcc1.c
$AR cr libtcc1-mes.a libtcc1-mes.o armeabi.o
$CC -c -g $CPP_TARGET_FLAG $CFLAGS -o libtcc1.o lib/libtcc1.c
$AR cr libtcc1.a libtcc1.o armeabi.o
cp -f libtcc1-tcc.a $prefix/lib/tcc
cp -f libtcc1-mes.a $prefix/lib/tcc
fi
rm -f libgetopt.a
cp -f $MES_LIB/libgetopt.c .
$CC -c $CPPFLAGS $CFLAGS libgetopt.c
$AR cr libgetopt.a libgetopt.o
else
cp -f $MES_LIB/crt1.o .
cp -f $MES_LIB/crti.o .
cp -f $MES_LIB/crtn.o .
cp -f $MES_LIB/libc+gnu.a libc.a
cp -f $MES_LIB/libtcc1.a .
cp -f $MES_LIB/libgetopt.a .
if [ $mes_cpu = arm ]; then
cp -f $MES_LIB/libtcc1.a $MES_LIB/libtcc1-mes.a
cp -f libtcc1-mes.a $prefix/lib/tcc
fi
fi
cp -f libc.a $prefix/lib
cp -f libtcc1.a $prefix/lib/tcc
rm -rf ${cross_prefix}tcc-usr
mkdir -p ${cross_prefix}tcc-usr
cp *.a ${cross_prefix}tcc-usr
cp *.o ${cross_prefix}tcc-usr

84
build-gcc.sh Executable file
View File

@ -0,0 +1,84 @@
#! /bin/sh
set -ex
CC=${CC-gcc}
crt1=$($CC --print-file-name=crt1.o)
prefix=${prefix-./usr}
rm -f tcc gcc-tcc
touch config.mak
make clean
rm -f *.a *.o
unset ONE_SOURCE
unset CFLAGS LDFLAGS
CPPFLAGS_TCC="
-DHAVE_FLOAT=1
-DHAVE_BITFIELD=1
-DHAVE_LONG_LONG=1
-DHAVE_SETJMP=1
"
arch=$(uname -m)
case $arch in
aarch*)
cpu=arm
mes_cpu=arm
tcc_cpu=arm
triplet=arm-linux-gnueabihf
cross_prefix=${triplet}-
CFLAGS=-marm
CPP_TARGET_FLAG="-DTCC_CPU_VERSION=7 -DTCC_TARGET_ARM -DTCC_ARM_VFP"
;;
arm*|aarch*)
cpu=arm
mes_cpu=arm
tcc_cpu=arm
triplet=arm-unknown-linux-gnueabihf
cross_prefix=${triplet}-
CFLAGS=-marm
CPP_TARGET_FLAG="-DTCC_CPU_VERSION=7 -DTCC_TARGET_ARM -DTCC_ARM_VFP"
;;
*x86_64*)
cpu=x86_64
mes_cpu=x86_64
tcc_cpu=x86_64
triplet=x86_64-unknown-linux-gnu
cross_prefix=${triplet}-
CFLAGS=
CPP_TARGET_FLAG="-DTCC_TARGET_X86_64"
;;
*)
cpu=x86
mes_cpu=x86
tcc_cpu=i386
triplet=i686-unknown-linux-gnu
cross_prefix=${triplet}-
CFLAGS=
CPP_TARGET_FLAG="-DTCC_TARGET_I386"
;;
esac
./configure --prefix=$prefix --tccdir=$PWD --crtprefix=$crtdir --extra-cflags="$CFLAGS $CPPFLAGS_TCC" --cc=$CC
type -p etags && make ETAGS
#Try building without eabihf
#make PROGRAM_PREFIX=gcc- gcc-tcc
if [ $mes_cpu = arm ]; then
make PROGRAM_PREFIX=gcc- gcc-tcc DEF-arm='$(DEF-arm-vfp)'
./gcc-tcc -c $CPP_TARGET_FLAG $CPPFLAGS_TCC $CFLAGS -c lib/libtcc1.c
./gcc-tcc -ar cr libtcc1.a libtcc1.o
else
make PROGRAM_PREFIX=gcc- gcc-tcc
rm -f libtcc1.c
touch libtcc1.c
./gcc-tcc -c libtcc1.c
./gcc-tcc -ar cr libtcc1.a libtcc1.o
fi
make libtcc1.a
rm -rf gcc-tcc-usr
mkdir -p gcc-tcc-usr
cp *.o *.a gcc-tcc-usr
rm -rf $prefix
mkdir -p $prefix/lib/tcc
cp libtcc1.a $prefix/lib/tcc

234
build.sh Executable file
View File

@ -0,0 +1,234 @@
#! /bin/sh
set -e
export V
export MESCC
export MES_DEBUG
export MES_PREFIX
export MES_LIB
export MES_SOURCE
export ONE_SOURCE
export PREPROCESS
export REBUILD_LIBC
export cpu
export cross_prefix
export mes_cpu
export prefix
export tcc_cpu
export triplet
if test "$V" = 1 -o "$V" = 2; then
set -x
fi
unset CPATH C_INCLUDE_PATH LIBRARY_PATH
prefix=${prefix-usr}
export prefix
MESCC=${MESCC-mes-source/pre-inst-env mescc}
CC=${CC-$MESCC}
host=${host-$($CC -dumpmachine 2>/dev/null)}
if test -z "$host$host_type"; then
mes_cpu=${arch-$(get_machine || uname -m)}
else
mes_cpu=${host%%-*}
fi
case "$mes_cpu" in
i386|i486|i586|i686|x86)
mes_cpu=x86
tcc_cpu=i386
have_float=${have_float-true}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-true}
;;
armv4|armv7l|arm)
mes_cpu=arm
tcc_cpu=arm
have_float=${have_float-false}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-false}
;;
amd64)
tcc_cpu=x86_64
mes_cpu=x86_64
have_float=${have_float-true}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-true}
;;
esac
case "$host" in
*linux-gnu|*linux)
mes_kernel=linux;;
*gnu)
mes_kernel=gnu;;
*)
mes_kernel=linux;;
esac
export mes_cpu
export tcc_cpu
export have_float
export have_long_long
export have_setjmp
MES=${MES-mes-source/bin/mes}
MES_PREFIX=${MES_PREFIX-mes}
MES_SOURCE=${MES_SOURCE-mes-source}
MES_LIB=${MES_LIB-$MES_PREFIX/lib}
MES_LIB=$MES_SOURCE/gcc-lib/${mes_cpu}-mes
PREPROCESS=${PREPROCESS-true}
ONE_SOURCE=${ONE_SOURCE-false}
interpreter=/lib/mes-loader
rm -f tcc.E tcc.hex2 tcc.M1 tcc.m1 mes-tcc boot?-tcc
verbose=
if test "$V" = 1; then
MESCCFLAGS="$MESCCFLAGS -v"
elif test "$V" = 2; then
MESCCFLAGS="$MESCCFLAGS -v -v"
fi
mkdir -p $prefix/lib
if test "$V" = 2; then
sh $MESCC --help
fi
if $ONE_SOURCE; then
sh cc.sh tcc
files="tcc.S"
else
sh cc.sh tccpp
sh cc.sh tccgen
sh cc.sh tccelf
sh cc.sh tccrun
sh cc.sh ${tcc_cpu}-gen
sh cc.sh ${tcc_cpu}-link
sh cc.sh ${tcc_cpu}-asm
sh cc.sh tccasm
sh cc.sh libtcc
sh cc.sh tcc
files="
tccpp.S
tccgen.S
tccelf.S
tccrun.S
${tcc_cpu}-gen.S
${tcc_cpu}-link.S
${tcc_cpu}-asm.S
tccasm.S
libtcc.S
tcc.S
"
fi
$MESCC \
$MESCCFLAGS \
-g \
-o mes-tcc \
-L $MES_SOURCE/mescc-lib \
-L $MES_SOURCE/lib \
$files \
-l c+tcc
CC="./mes-tcc"
AR="./mes-tcc -ar"
CPPFLAGS="
-I $MES_PREFIX/include
-I $MES_PREFIX/include/$mes_kernel/$mes_cpu
-I $MES_PREFIX/lib
-D BOOTSTRAP=1
"
if test "$mes_cpu" = x86; then
CPP_TARGET_FLAG="-D TCC_TARGET_I386=1"
elif test "$mes_cpu" = arm; then
CPP_TARGET_FLAG="-D TCC_TARGET_ARM=1 -D TCC_ARM_VFP=1 -D CONFIG_TCC_LIBTCC1_MES=1"
elif test "$mes_cpu" = x86_64; then
CPP_TARGET_FLAG="-D TCC_TARGET_X86_64=1"
else
echo "cpu not supported: $mes_cpu"
fi
CFLAGS=
REBUILD_LIBC=${REBUILD_LIBC-true}
mkdir -p $prefix/lib/tcc
if $REBUILD_LIBC; then
for i in 1 i n; do
rm -f crt$i.o;
cp -f $MES_LIB//crt$i.c .
$CC $CPPFLAGS $CFLAGS -static -nostdlib -nostdinc -c crt$i.c
done
rm -f libc.a
cp -f $MES_LIB/libc+gnu.c libc.c
$CC -c $CPPFLAGS $CFLAGS libc.c
$AR cr libc.a libc.o
rm -f libtcc1.a
cp -f $MES_LIB/libtcc1.c .
$CC -c $CPPFLAGS $CPP_TARGET_FLAG $CFLAGS lib/libtcc1.c
$AR cr libtcc1.a libtcc1.o
if [ $mes_cpu = arm ]; then
$CC -c -g $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG lib/armeabi.c
$CC -c -g $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG -o libtcc1-tcc.o lib/libtcc1.c
$AR rc libtcc1-tcc.a libtcc1-tcc.o armeabi.o
$CC -c -g $CPPFLAGS $CFLAGS -D HAVE_FLOAT=1 -D HAVE_LONG_LONG=1 -o libtcc1-mes.o $MES_LIB/libtcc1.c
$AR cr libtcc1-mes.a libtcc1-mes.o armeabi.o
$CC -c -g $CPP_TARGET_FLAG $CFLAGS -o libtcc1.o lib/libtcc1.c
# $AR cr libtcc1.a libtcc1.o armeabi.o
$AR cr libtcc1.a libtcc1.o
cp -f libtcc1-tcc.a $prefix/lib/tcc
cp -f libtcc1-mes.a $prefix/lib/tcc
fi
rm -f libgetopt.a
cp -f $MES_LIB/libgetopt.c .
$CC -c $CPPFLAGS $CFLAGS libgetopt.c
$AR cr libgetopt.a libgetopt.o
else
cp -f $MES_LIB/crt1.o .
cp -f $MES_LIB/crti.o .
cp -f $MES_LIB/crtn.o .
cp -f $MES_LIB/libc+gnu.a libc.a
cp -f $MES_LIB/libtcc1.a .
cp -f $MES_LIB/libgetopt.a .
if [ $mes_cpu = arm ]; then
$CC -c $CPPFLAGS $CFLAGS $MES_LIB/libtcc1.c
$CC -c $CPPFLAGS $CFLAGS lib/armeabi.c
fi
fi
cp -f libc.a $prefix/lib
cp -f libtcc1.a $prefix/lib/tcc
cp -f libgetopt.a $prefix/lib
rm -rf mes-usr
mkdir -p mes-usr
cp *.M1 mes-usr
cp *.S mes-usr
cp *.a mes-usr
REBUILD_LIBC=true
TCC=./mes-tcc sh boot.sh
TCC=./boot0-tcc sh boot.sh
TCC=./boot1-tcc sh boot.sh
TCC=./boot2-tcc sh boot.sh
TCC=./boot3-tcc sh boot.sh
TCC=./boot4-tcc sh boot.sh
TCC=./boot5-tcc sh boot.sh
cmp boot5-tcc boot6-tcc
cp -f boot5-tcc tcc
echo "build.sh: done"

72
cc.sh Executable file
View File

@ -0,0 +1,72 @@
#! /bin/sh
set -e
if [ "$V" = 1 -o "$V" = 2 ]; then
set -x
MESCCFLAGS="$MESCCFLAGS -v"
fi
t=$1
rm -f $t.E $t.M1 $t.m1
MES=${MES-mes-source/bin/mes}
MESCC=${MESCC-mes-source/pre-inst-env mescc}
CFLAGS=${CFLAGS-}
MES_PREFIX=${MES_PREFIX-mes-source}
absprefix=$(cd $prefix && pwd)
interpreter=/lib/mes-loader
ulimit -s 17030
CPPFLAGS="
-I $MES_PREFIX/lib
-I $MES_PREFIX/include
-D BOOTSTRAP=1
"
if test "$mes_cpu" = x86; then
CPP_TARGET_FLAG="-D TCC_TARGET_I386=1"
elif test "$mes_cpu" = arm; then
CPP_TARGET_FLAG="-D TCC_TARGET_ARM=1 -D TCC_ARM_VFP=1 -D CONFIG_TCC_LIBTCC1_MES=1"
elif test "$mes_cpu" = x86_64; then
CPP_TARGET_FLAG="-D TCC_TARGET_X86_64=1"
else
echo "cpu not supported: $mes_cpu"
fi
CPPFLAGS_TCC="$CPPFLAGS
-I .
$CPP_TARGET_FLAG
-D inline=
-D CONFIG_TCCDIR=\"$prefix/lib/tcc\"
-D CONFIG_TCC_CRTPREFIX=\"$prefix/lib:"{B}"/lib:.\"
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"
-D CONFIG_TCC_LIBPATHS=\"$prefix/lib:"{B}"/lib:.\"
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$prefix/include:"{B}"/include\"
-D TCC_LIBGCC=\"$prefix/lib/libc.a\"
-D TCC_LIBTCC1_MES=\"libtcc1-mes.a\"
-D CONFIG_TCCBOOT=1
-D CONFIG_TCC_STATIC=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"
if $ONE_SOURCE; then
CPPFLAGS_TCC="$CPPFLAGS_TCC -D ONE_SOURCE=$ONE_SOURCE"
fi
if $PREPROCESS; then
time sh $MESCC $MESCCFLAGS -E -o $t.E \
$CFLAGS \
$CPPFLAGS_TCC \
$t.c
time sh $MESCC $MESCCFLAGS -S -o $t.M1 $t.E
else
time sh $MESCC $MESCCFLAGS -S -o $t.M1 \
$CFLAGS \
$CPPFLAGS_TCC \
$t.c
fi
tr -d '\r' < $t.M1 > $t.S

417
check.sh Executable file
View File

@ -0,0 +1,417 @@
#! /usr/bin/env bash
export V
if test "$V" = 1 -o "$V" = 2; then
set -x
fi
arch=$(uname -m)
case $arch in
aarch*)
cpu=arm
tcc_cpu=arm
triplet=arm-linux-gnueabihf
cross_prefix=${triplet}-
;;
arm*|aarch*)
cpu=arm
tcc_cpu=arm
triplet=arm-unknown-linux-gnueabihf
cross_prefix=${triplet}-
;;
*)
cpu=x86
tcc_cpu=i386
triplet=i686-unknown-linux-gnu
cross_prefix=${triplet}-
;;
esac
export cpu
export cross_prefix
export tcc_cpu
export triplet
GCC_TCC=${GCC_TCC-./${cross_prefix}tcc}
TCC=${TCC-./tcc}
MES_PREFIX=${MES_PREFIX-mes}
MES_SOURCE=${MES_SOURCE-mes-source}
export MES_PREFIX
export MES_SOURCE
mkdir -p lib/tests
cp -r $MES_SOURCE/lib/tests lib
mes_tests="
lib/tests/scaffold/t.c
lib/tests/scaffold/01-return-0.c
lib/tests/scaffold/02-return-1.c
lib/tests/scaffold/03-call.c
lib/tests/scaffold/04-call-0.c
lib/tests/scaffold/05-call-1.c
lib/tests/scaffold/06-call-not-1.c
lib/tests/scaffold/06-not-call-1.c
lib/tests/scaffold/06-call-2.c
lib/tests/scaffold/06-call-string.c
lib/tests/scaffold/06-call-variable.c
lib/tests/scaffold/06-return-void.c
lib/tests/scaffold/07-include.c
lib/tests/scaffold/08-assign.c
lib/tests/scaffold/08-assign-negative.c
lib/tests/scaffold/08-assign-global.c
lib/tests/scaffold/10-if-0.c
lib/tests/scaffold/11-if-1.c
lib/tests/scaffold/12-if-eq.c
lib/tests/scaffold/13-if-neq.c
lib/tests/scaffold/14-if-goto.c
lib/tests/scaffold/15-if-not-f.c
lib/tests/scaffold/16-if-t.c
lib/tests/scaffold/17-compare-char.c
lib/tests/scaffold/17-compare-ge.c
lib/tests/scaffold/17-compare-gt.c
lib/tests/scaffold/17-compare-le.c
lib/tests/scaffold/17-compare-lt.c
lib/tests/scaffold/17-compare-unsigned-ge.c
lib/tests/scaffold/17-compare-unsigned-gt.c
lib/tests/scaffold/17-compare-unsigned-le.c
lib/tests/scaffold/17-compare-unsigned-lt.c
lib/tests/scaffold/17-compare-unsigned-char-le.c
lib/tests/scaffold/17-compare-unsigned-short-le.c
lib/tests/scaffold/17-compare-unsigned-long-le.c
lib/tests/scaffold/17-compare-and.c
lib/tests/scaffold/17-compare-or.c
lib/tests/scaffold/17-compare-and-or.c
lib/tests/scaffold/17-compare-assign.c
lib/tests/scaffold/17-compare-call.c
lib/tests/scaffold/18-assign-shadow.c
lib/tests/scaffold/20-while.c
lib/tests/scaffold/21-char-array-simple.c
lib/tests/scaffold/21-char-array.c
lib/tests/scaffold/22-while-char-array.c
lib/tests/scaffold/23-global-pointer-init-null.c
lib/tests/scaffold/23-global-pointer-init.c
lib/tests/scaffold/23-global-pointer-ref.c
lib/tests/scaffold/23-global-pointer-pointer-ref.c
lib/tests/scaffold/23-pointer-sub.c
lib/tests/scaffold/23-pointer.c
lib/tests/mes/30-oputs.c
lib/tests/mes/30-eputs.c
lib/tests/string/30-strlen.c
lib/tests/scaffold/30-exit-0.c
lib/tests/scaffold/30-exit-42.c
lib/tests/scaffold/32-call-wrap.c
lib/tests/scaffold/32-compare.c
lib/tests/scaffold/33-and-or.c
lib/tests/scaffold/34-pre-post.c
lib/tests/scaffold/35-compare-char.c
lib/tests/scaffold/36-compare-arithmetic.c
lib/tests/scaffold/36-compare-arithmetic-negative.c
lib/tests/scaffold/37-compare-assign.c
lib/tests/scaffold/38-compare-call-2.c
lib/tests/scaffold/38-compare-call-3.c
lib/tests/scaffold/38-compare-call.c
lib/tests/scaffold/40-if-else.c
lib/tests/scaffold/41-ternary.c
lib/tests/scaffold/42-goto-label.c
lib/tests/scaffold/43-for-do-while.c
lib/tests/scaffold/44-switch.c
lib/tests/scaffold/44-switch-fallthrough.c
lib/tests/scaffold/44-switch-body-fallthrough.c
lib/tests/scaffold/45-void-call.c
lib/tests/scaffold/46-function-static.c
lib/tests/scaffold/47-function-expression.c
lib/tests/scaffold/48-global-static.c
lib/tests/assert/50-assert.c
lib/tests/mes/50-itoa.c
lib/tests/posix/50-getenv.c
lib/tests/stdlib/50-malloc.c
lib/tests/string/50-strcmp.c
lib/tests/string/50-strcmp-itoa.c
lib/tests/string/50-strcpy.c
lib/tests/string/50-strncmp.c
lib/tests/posix/50-open-read.c
lib/tests/scaffold/51-pointer-sub.c
lib/tests/scaffold/54-argc.c
lib/tests/scaffold/54-argv.c
lib/tests/scaffold/55-char-array.c
lib/tests/scaffold/60-math.c
lib/tests/scaffold/60-math-itoa.c
lib/tests/scaffold/61-array.c
lib/tests/scaffold/62-array.c
lib/tests/scaffold/63-struct.c
lib/tests/scaffold/63-struct-pointer.c
lib/tests/scaffold/63-struct-local.c
lib/tests/scaffold/63-struct-function.c
lib/tests/scaffold/63-struct-assign.c
lib/tests/scaffold/63-struct-array.c
lib/tests/scaffold/63-struct-array-assign.c
lib/tests/scaffold/63-struct-array-compare.c
lib/tests/scaffold/63-struct-cell.c
lib/tests/scaffold/64-make-cell.c
lib/tests/scaffold/65-read.c
lib/tests/scaffold/66-local-char-array.c
"
tcc_tests="
lib/tests/scaffold/70-stdarg.c
lib/tests/stdio/70-printf-hello.c
lib/tests/stdio/70-printf-simple.c
lib/tests/stdio/70-printf.c
lib/tests/stdlib/70-strtoull.c
lib/tests/string/70-strchr.c
lib/tests/scaffold/71-struct-array.c
lib/tests/scaffold/72-typedef-struct-def.c
lib/tests/scaffold/72-typedef-struct-def-local.c
lib/tests/scaffold/73-union-hello.c
lib/tests/scaffold/73-union.c
lib/tests/scaffold/74-multi-line-string.c
lib/tests/scaffold/75-struct-union.c
lib/tests/scaffold/76-pointer-arithmetic-pp.c
lib/tests/scaffold/76-pointer-arithmetic.c
lib/tests/scaffold/77-pointer-assign.c
lib/tests/scaffold/78-union-struct.c
lib/tests/scaffold/79-int-array-simple.c
lib/tests/scaffold/79-int-array.c
lib/tests/scaffold/7a-struct-char-array.c
lib/tests/scaffold/7b-struct-int-array-hello.c
lib/tests/scaffold/7b-struct-int-array-pointer.c
lib/tests/scaffold/7b-struct-int-array.c
lib/tests/scaffold/7c-dynarray.c
lib/tests/scaffold/7d-cast-char.c
lib/tests/scaffold/7e-struct-array-access.c
lib/tests/scaffold/7f-struct-pointer-arithmetic.c
lib/tests/scaffold/7g-struct-byte-word-field.c
lib/tests/scaffold/7h-struct-assign.c
lib/tests/scaffold/7i-struct-struct-simple.c
lib/tests/scaffold/7i-struct-struct.c
lib/tests/scaffold/7k-empty-for.c
lib/tests/scaffold/7k-for-each-elem-simple.c
lib/tests/scaffold/7k-for-each-elem.c
lib/tests/scaffold/7l-struct-any-size-array-simple.c
lib/tests/scaffold/7l-struct-any-size-array.c
lib/tests/scaffold/7m-struct-char-array-assign.c
lib/tests/scaffold/7n-struct-struct-array.c
lib/tests/scaffold/7o-struct-pre-post-simple.c
lib/tests/scaffold/7o-struct-pre-post.c
lib/tests/scaffold/7p-struct-cast.c
lib/tests/scaffold/7q-bit-field-simple.c
lib/tests/scaffold/7q-bit-field.c
lib/tests/scaffold/7r-sign-extend.c
lib/tests/scaffold/7s-struct-short.c
lib/tests/scaffold/7s-unsigned-compare.c
lib/tests/scaffold/7t-function-destruct.c
lib/tests/scaffold/7u-double.c
lib/tests/scaffold/7u-long-long.c
lib/tests/scaffold/7u-ternary-expression.c
lib/tests/scaffold/7u-call-ternary.c
lib/tests/scaffold/7u-inc-byte-word.c
lib/tests/scaffold/7u-struct-func.c
lib/tests/scaffold/7u-struct-size10.c
lib/tests/scaffold/7u-vstack.c
lib/tests/scaffold/70-array-in-struct-init.c
lib/tests/scaffold/70-struct-short-enum-init.c
lib/tests/scaffold/70-struct-post.c
lib/tests/scaffold/70-extern.c
lib/tests/scaffold/70-ternary-arithmetic-argument.c
lib/tests/setjmp/80-setjmp.c
lib/tests/stdio/80-sscanf.c
lib/tests/stdlib/80-qsort.c
lib/tests/stdlib/80-qsort-dupes.c
lib/tests/string/80-strncpy.c
lib/tests/string/80-strrchr.c
lib/tests/scaffold/82-define.c
lib/tests/scaffold/83-heterogenoous-init.c
lib/tests/scaffold/84-struct-field-list.c
lib/tests/scaffold/85-sizeof.c
"
gnu_tests="
lib/tests/dirent/90-readdir.c
lib/tests/io/90-stat.c
lib/tests/mes/90-abtod.c
lib/tests/mes/90-dtoab.c
lib/tests/posix/90-execlp.c
lib/tests/posix/90-unsetenv.c
lib/tests/signal/90-signal.c
lib/tests/stdio/90-fopen.c
lib/tests/stdio/90-fopen-append.c
lib/tests/stdio/90-fread-fwrite.c
lib/tests/stdio/90-fseek.c
lib/tests/stdio/90-sprintf.c
lib/tests/stdlib/90-strtol.c
lib/tests/string/90-snprintf.c
lib/tests/string/90-strpbrk.c
lib/tests/string/90-strspn.c
lib/tests/scaffold/90-goto-var.c
lib/tests/scaffold/91-goto-array.c
lib/tests/scaffold/a0-call-trunc-char.c
lib/tests/scaffold/a0-call-trunc-short.c
lib/tests/scaffold/a0-call-trunc-int.c
lib/tests/scaffold/a0-math-divide-signed-negative.c
lib/tests/scaffold/a1-global-no-align.c
lib/tests/scaffold/a1-global-no-clobber.c
"
tests="$mes_tests$tcc_tests$gnu_tests"
broken="
lib/tests/scaffold/t.c
lib/tests/scaffold/70-ternary-arithmetic-argument.c
lib/tests/dirent/90-readdir.c
lib/tests/io/90-stat.c
lib/tests/stdio/90-fseek.c
"
if [ $TCC = ./tcc ]; then
broken="$broken
lib/tests/scaffold/60-math.c
lib/tests/scaffold/7s-unsigned-compare.c
"
fi
if [ $tcc_cpu = "arm" ]; then
broken="$broken
lib/tests/setjmp/80-setjmp.c
lib/tests/mes/90-abtod.c
lib/tests/signal/90-signal.c
"
fi
if [ ! -x $GCC_TCC ]; then
broken="$broken
02-return-1
05-call-1
"
fi
if ! test -f lib/tests/scaffold/t.c; then
tests=
broken=
fi
expect=$(echo $broken | wc -w)
mkdir -p scaffold/tests
set +e
pass=0
fail=0
total=0
for t in $tests; do
b=$(basename "$t" .c)
sh test.sh "$t" &> "$t".log
r=$?
total=$((total+1))
if [ $r = 0 ]; then
echo $t: [OK]
pass=$((pass+1))
else
echo $t: [FAIL]
fail=$((fail+1))
fi
done
tests="
tests/tests2/00_assignment.c
tests/tests2/01_comment.c
tests/tests2/02_printf.c
tests/tests2/03_struct.c
tests/tests2/04_for.c
tests/tests2/05_array.c
tests/tests2/06_case.c
tests/tests2/07_function.c
tests/tests2/08_while.c
tests/tests2/09_do_while.c
tests/tests2/10_pointer.c
tests/tests2/11_precedence.c
tests/tests2/12_hashdefine.c
tests/tests2/13_integer_literals.c
tests/tests2/14_if.c
tests/tests2/15_recursion.c
tests/tests2/16_nesting.c
tests/tests2/17_enum.c
tests/tests2/18_include.c
tests/tests2/19_pointer_arithmetic.c
tests/tests2/20_pointer_comparison.c
tests/tests2/21_char_array.c
tests/tests2/22_floating_point.c
tests/tests2/23_type_coercion.c
tests/tests2/24_math_library.c
tests/tests2/25_quicksort.c
tests/tests2/26_character_constants.c
tests/tests2/27_sizeof.c
tests/tests2/28_strings.c
tests/tests2/29_array_address.c
tests/tests2/30_hanoi.c
tests/tests2/31_args.c
tests/tests2/32_led.c
tests/tests2/33_ternary_op.c
tests/tests2/34_array_assignment.c
tests/tests2/35_sizeof.c
tests/tests2/36_array_initialisers.c
tests/tests2/37_sprintf.c
tests/tests2/38_multiple_array_index.c
tests/tests2/39_typedef.c
tests/tests2/40_stdio.c
tests/tests2/41_hashif.c
tests/tests2/42_function_pointer.c
tests/tests2/43_void_param.c
tests/tests2/44_scoped_declarations.c
tests/tests2/45_empty_for.c
tests/tests2/47_switch_return.c
tests/tests2/48_nested_break.c
tests/tests2/49_bracket_evaluation.c
tests/tests2/50_logical_second_arg.c
tests/tests2/51_static.c
tests/tests2/52_unnamed_enum.c
tests/tests2/54_goto.c
tests/tests2/55_lshift_type.c
"
broken="$broken
tests/tests2/22_floating_point.c
tests/tests2/23_type_coercion.c
tests/tests2/24_math_library.c
tests/tests2/34_array_assignment.c
tests/tests2/49_bracket_evaluation.c
tests/tests2/55_lshift_type.c
"
#tests/tests2/24_math_library.c ; float, math
#tests/tests2/34_array_assignment.c ; fails with GCC
expect=$(echo $broken | wc -w)
for t in $tests; do
if [ ! -f "$t" ]; then
echo ' [SKIP]'
continue;
fi
b=$(basename "$t" .c)
d=$(dirname "$t")
sh test.sh "$t" &> "$d/$b".log
r=$?
total=$((total+1))
if [ $r = 0 ]; then
echo $t: [OK]
pass=$((pass+1))
else
echo $t: [FAIL]
fail=$((fail+1))
fi
done
[ $expect != 0 ] && echo "expect: $expect"
[ $fail != 0 ] && echo "failed: $fail"
echo "passed: $pass"
[ $fail -lt $expect ] && echo "solved: $(($expect - $fail))"
echo "total: $total"
if [ $fail != 0 -a $fail -gt $expect ]; then
echo FAILED: $fail/$total
exit 1
elif [ $fail != 0 ]; then
echo PASS: $pass/$total
else
echo PASS: $total
fi

40
compile.sh Executable file
View File

@ -0,0 +1,40 @@
#! /bin/sh
set -ex
MES_PREFIX=${MES_PREFIX-mes}
MES_SOURCE=${MES_SOURCE-mes-source}
arch=$(uname -m)
case $arch in
aarch*)
cpu=arm
tcc_cpu=arm
triplet=arm-linux-gnueabihf
cross_prefix=${triplet}-
;;
arm*|aarch*)
cpu=arm
tcc_cpu=arm
triplet=arm-unknown-linux-gnueabihf
cross_prefix=${triplet}-
;;
*)
cpu=x86
tcc_cpu=i386
triplet=i686-unknown-linux-gnu
cross_prefix=${triplet}-
;;
esac
rm -f *.$triplet-o *.mes-o
rm -f 1 2 1.elf 2.elf 1.a 2.a
# trivial object
./tcc -c -I $MES_PREFIX/include $MES_SOURCE/scaffold/main.c 2>/dev/null
./$triplet-tcc -o main.$triplet-o -c -I $MES_PREFIX/include $MES_SOURCE/scaffold/main.c 2> 1
set +e
./mes-tcc -o main.mes-o -c -I $MES_PREFIX/include $MES_SOURCE/scaffold/main.c &> 2
diff -y 1 2
readelf -a main.$triplet-o > 1.elf
readelf -a main.mes-o > 2.elf
diff -y 1.elf 2.elf || :

7
configure vendored
View File

@ -27,7 +27,7 @@ mandir=""
infodir=""
sysroot=""
cross_prefix=""
cc="gcc"
cc="gcc -g"
ar="ar"
strip="strip"
bigendian="no"
@ -198,6 +198,9 @@ case "$cpu" in
s390)
cpu="s390"
;;
riscv64)
cpu="riscv64"
;;
*)
echo "Unsupported CPU"
exit 1
@ -340,7 +343,7 @@ if test -z "$cross_prefix" ; then
fi
if test -z "$triplet"; then
if test $cpu = "x86_64" -o $cpu = "arm64" ; then
if test $cpu = "x86_64" -o $cpu = "arm64" -o $cpu = "riscv64" ; then
if test -f "/usr/lib64/crti.o" ; then
tcc_lddir="lib64"
fi

View File

@ -9,6 +9,8 @@
# define TRIPLET_ARCH "arm"
#elif defined(__aarch64__)
# define TRIPLET_ARCH "aarch64"
#elif defined(__riscv) && defined(__LP64__)
# define TRIPLET_ARCH "riscv64"
#else
# define TRIPLET_ARCH "unknown"
#endif

21
d Executable file
View File

@ -0,0 +1,21 @@
#! /bin/sh
set -ex
rm -f *.o *.a *.E *.hex2 *.mesc-o *.i686-unknown-linux-gnu-o *.M1
rm -f 1 2 1.elf 2.elf
# trivial object
set +e
./tcc -c -I ../mes/mlibc/include ../mes/scaffold/main.c 2>/dev/null
./i686-unknown-linux-gnu-tcc -o main.i686-unknown-linux-gnu-o -c -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 1
./tcc.mes -o main.mesc-o -c -I ../mes/mlibc/include ../mes/scaffold/main.c &> 2
diff -y 1 2
readelf -a main.i686-unknown-linux-gnu-o > 1.elf
readelf -a main.mesc-o > 2.elf
diff -y 1.elf 2.elf
# trivial bin
./tcc ../mes/scaffold/main.c
./i686-unknown-linux-gnu-tcc -o a.i686-unknown-linux-gnu-out -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 1.a
./tcc.mes -o a.mes-out -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 2.a
diff -y 1.a 2.a

94
doit Executable file
View File

@ -0,0 +1,94 @@
#! /bin/sh
set -ex
export V
export MES
export MESCC
export MES_DEBUG
export MES_PREFIX
export MES_LIB
export MES_SOURCE
export ONE_SOURCE
export PREPROCESS
export REBUILD_LIBC
export cpu
export cross_prefix
export mes_cpu
export prefix
export tcc_cpu
export triplet
prefix=usr
MES=${MES-mes-source/bin/mes}
MES_ARENA=70000000
MES_MAX_ARENA=70000000
export MES_ARENA MES_MAX_ARENA
MES=guile
MES=${MES-mes-source/bin/mes}
MESCC=${MESCC-mes-source/pre-inst-env mescc}
MES_PREFIX=${MES_PREFIX-mes-source}
REBUILD_LIBC=${REBUILD_LIBC-true}
rm -f mes
ln -sf $MES_PREFIX mes
sh build-gcc.sh
PREPROCESS=${PREPROCESS-true}
ONE_SOURCE=${ONE_SOURCE-false}
arch=$(uname -m)
case $arch in
aarch*)
cpu=arm
mes_cpu=arm
tcc_cpu=arm
triplet=arm-linux-gnueabihf
cross_prefix=${triplet}-
have_float=${have_float-true}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-false}
;;
arm*|aarch*)
cpu=arm
mes_cpu=arm
tcc_cpu=arm
triplet=arm-unknown-linux-gnueabihf
cross_prefix=${triplet}-
have_float=${have_float-true}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-false}
;;
*)
cpu=x86
mes_cpu=x86
tcc_cpu=i386
triplet=i686-unknown-linux-gnu
cross_prefix=${triplet}-
have_float=${have_float-true}
have_long_long=${have_long_long-true}
have_setjmp=${have_setjmp-true}
;;
esac
export cpu
export cross_prefix
export tcc_cpu
export triplet
export have_float
export have_long_long
export have_setjmp
MES_LIB=${MES_LIB-$MES_PREFIX/lib}
MES_LIB=$MES_SOURCE/gcc-lib/${mes_cpu}-mes
sh build-32.sh
sh build.sh
sh compile.sh
sh link.sh ||:
sh check.sh
rm -rf usr
sh install.sh

88
elf.h
View File

@ -1,3 +1,4 @@
/* This file defines standard ELF types, structures, and macros.
Copyright (C) 1995-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@ -232,7 +233,7 @@ typedef struct
#define EM_FX66 66 /* Siemens FX66 microcontroller */
#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */
#define EM_ST7 68 /* STMicroelectronics ST7 8 bit mc */
#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */
@ -262,7 +263,8 @@ typedef struct
#define EM_AARCH64 183 /* ARM AARCH64 */
#define EM_TILEPRO 188 /* Tilera TILEPro */
#define EM_TILEGX 191 /* Tilera TILE-Gx */
#define EM_NUM 192
#define EM_RISCV 243 /* RISC-V */
#define EM_NUM 253
/* If it is necessary to assign new unofficial EM_* values, please
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
@ -381,7 +383,7 @@ typedef struct
#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
#define SHF_ORDERED (1 << 30) /* Special ordering requirement
(Solaris). */
#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless
#define SHF_EXCLUDE (1U << 31) /* Section is excluded unless
referenced or allocated (Solaris).*/
/* Section group handling. */
@ -817,7 +819,7 @@ typedef struct
#define DF_1_EDITED 0x00200000 /* Object is modified after built. */
#define DF_1_NORELOC 0x00400000
#define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */
#define DF_1_GLOBAUDIT 0x01000000 /* Global auditin required. */
#define DF_1_GLOBAUDIT 0x01000000 /* Global auditing required. */
#define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */
/* Flags for the feature selection in DT_FEATURE_1. */
@ -1313,7 +1315,7 @@ typedef struct
#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */
#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */
#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */
#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */
#define R_SPARC_PC_LM22 39 /* Low middle 22 bits of ... */
#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */
#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */
#define R_SPARC_GLOB_JMP 42 /* was part of v9 ABI but was removed */
@ -2494,22 +2496,30 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_ARM_CALL 28
#define R_ARM_JUMP24 29
#define R_ARM_THM_JUMP24 30
#define R_ARM_BASE_ABS 31 /* Adjust by program base. */
#define R_ARM_ALU_PCREL_7_0 32
#define R_ARM_ALU_PCREL_15_8 33
#define R_ARM_ALU_PCREL_23_15 34
#define R_ARM_LDR_SBREL_11_0 35
#define R_ARM_ALU_SBREL_19_12 36
#define R_ARM_ALU_SBREL_27_20 37
#define R_ARM_TARGET1 38
#define R_ARM_SBREL31 39 /* Program base relative. */
#define R_ARM_V4BX 40
#define R_ARM_TARGET2 41
#define R_ARM_PREL31 42
#define R_ARM_MOVW_ABS_NC 43
#define R_ARM_MOVT_ABS 44
#define R_ARM_MOVW_PREL_NC 45 /* PC relative 16-bit (MOVW). */
#define R_ARM_MOVT_PREL 46 /* PC relative (MOVT). */
#define R_ARM_THM_MOVW_ABS_NC 47
#define R_ARM_THM_MOVT_ABS 48
/* Values from 49 to 89 are not yet used/handled by tcc. */
#define R_ARM_TLS_GOTDESC 90
#define R_ARM_TLS_CALL 91
#define R_ARM_TLS_DESCSEQ 92
#define R_ARM_THM_TLS_CALL 93
#define R_ARM_GOT_PREL 96
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
@ -2907,6 +2917,8 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_X86_64_NUM 43
/* x86-64 sh_type values. */
#define SHT_X86_64_UNWIND 0x70000001 /* Unwind information. */
/* AM33 relocations. */
#define R_MN10300_NONE 0 /* No reloc. */
@ -3233,5 +3245,71 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_TILEGX_NUM 130
/* RISC-V ELF Flags */
#define EF_RISCV_RVC 0x0001
#define EF_RISCV_FLOAT_ABI 0x0006
#define EF_RISCV_FLOAT_ABI_SOFT 0x0000
#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002
#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004
#define EF_RISCV_FLOAT_ABI_QUAD 0x0006
/* RISC-V relocations. */
#define R_RISCV_NONE 0
#define R_RISCV_32 1
#define R_RISCV_64 2
#define R_RISCV_RELATIVE 3
#define R_RISCV_COPY 4
#define R_RISCV_JUMP_SLOT 5
#define R_RISCV_TLS_DTPMOD32 6
#define R_RISCV_TLS_DTPMOD64 7
#define R_RISCV_TLS_DTPREL32 8
#define R_RISCV_TLS_DTPREL64 9
#define R_RISCV_TLS_TPREL32 10
#define R_RISCV_TLS_TPREL64 11
#define R_RISCV_BRANCH 16
#define R_RISCV_JAL 17
#define R_RISCV_CALL 18
#define R_RISCV_CALL_PLT 19
#define R_RISCV_GOT_HI20 20
#define R_RISCV_TLS_GOT_HI20 21
#define R_RISCV_TLS_GD_HI20 22
#define R_RISCV_PCREL_HI20 23
#define R_RISCV_PCREL_LO12_I 24
#define R_RISCV_PCREL_LO12_S 25
#define R_RISCV_HI20 26
#define R_RISCV_LO12_I 27
#define R_RISCV_LO12_S 28
#define R_RISCV_TPREL_HI20 29
#define R_RISCV_TPREL_LO12_I 30
#define R_RISCV_TPREL_LO12_S 31
#define R_RISCV_TPREL_ADD 32
#define R_RISCV_ADD8 33
#define R_RISCV_ADD16 34
#define R_RISCV_ADD32 35
#define R_RISCV_ADD64 36
#define R_RISCV_SUB8 37
#define R_RISCV_SUB16 38
#define R_RISCV_SUB32 39
#define R_RISCV_SUB64 40
#define R_RISCV_GNU_VTINHERIT 41
#define R_RISCV_GNU_VTENTRY 42
#define R_RISCV_ALIGN 43
#define R_RISCV_RVC_BRANCH 44
#define R_RISCV_RVC_JUMP 45
#define R_RISCV_RVC_LUI 46
#define R_RISCV_GPREL_I 47
#define R_RISCV_GPREL_S 48
#define R_RISCV_TPREL_I 49
#define R_RISCV_TPREL_S 50
#define R_RISCV_RELAX 51
#define R_RISCV_SUB6 52
#define R_RISCV_SET6 53
#define R_RISCV_SET8 54
#define R_RISCV_SET16 55
#define R_RISCV_SET32 56
#define R_RISCV_32_PCREL 57
#define R_RISCV_NUM 58
#endif /* elf.h */

162
guix.scm Normal file
View File

@ -0,0 +1,162 @@
(use-modules (ice-9 popen)
(ice-9 rdelim)
(guix packages)
(guix utils)
(guix gexp)
(guix profiles)
(guix download)
(guix build-system gnu)
((guix licenses) #:prefix license:)
(gnu packages gcc)
(gnu packages base)
(gnu packages linux)
(gnu packages maths)
(gnu packages perl)
(gnu packages cross-base)
(gnu packages bootstrap)
(gnu packages texinfo))
(define %source-dir (dirname (current-filename)))
(define %git-commit
(read-line
(open-pipe "git show HEAD | head -1 | cut -d ' ' -f 2 " OPEN_READ)))
(define (discard-git path stat)
(let* ((start (1+ (string-length %source-dir)) )
(end (+ 4 start)))
(not (false-if-exception (equal? ".git" (substring path start end))))))
(define libccross (cross-libc "riscv64-linux-gnu"))
(define-public tcc-mine-native
(package
(name "tcc") ;aka. "tinycc"
(version "riscv-mes-HEAD")
(source (local-file %source-dir
#:recursive? #t
#:select? discard-git))
(build-system gnu-build-system)
(native-inputs (list perl texinfo which))
(arguments
(list
#:configure-flags
#~(list
"--extra-cflags=-DHAVE_FLOAT=1 -DHAVE_BITFIELD=1 -DHAVE_LONG_LONG=1 -DHAVE_SETJMP=1"
"--disable-rpath")
#:test-target "test"
#:validate-runpath? #f
#:phases
#~(modify-phases
%standard-phases
(replace 'build
(lambda _
(invoke "./build-gcc.sh")))
(replace 'install
(lambda* (#:key inputs outputs #:allow-other-keys)
(install-file "libtcc1.a"
(string-append (assoc-ref outputs "out") "/lib/tcc"))
(install-file "tcc"
(string-append (assoc-ref outputs "out") "/bin"))
(copy-recursively "include"
(string-append (assoc-ref outputs "out") "/include")))) )))
(native-search-paths
(list (search-path-specification
(variable "CPATH")
(files '("include")))
(search-path-specification
(variable "LIBRARY_PATH")
(files '("lib" "lib64")))))
(synopsis "Tiny and fast C compiler")
(description
"TCC, also referred to as \"TinyCC\", is a small and fast C compiler
written in C. It supports ANSI C with GNU and extensions and most of the C99
standard.")
(home-page "http://www.tinycc.org/")
;; An attempt to re-licence tcc under the Expat licence is underway but not
;; (if ever) complete. See the RELICENSING file for more information.
(license license:lgpl2.1+)))
(define-public tcc-mine
(package
(name "tcc") ;aka. "tinycc"
(version "riscv-mes-HEAD")
(source (local-file %source-dir
#:recursive? #t
#:select? discard-git))
(build-system gnu-build-system)
(native-inputs (list perl texinfo which))
(arguments
(list
#:configure-flags
#~(list "--enable-cross"
"--disable-rpath"
"--extra-cflags=-DHAVE_FLOAT=1 -DHAVE_BITFIELD=1 -DHAVE_LONG_LONG=1 -DHAVE_SETJMP=1")
#:tests? #f
#:validate-runpath? #f
#:phases #~(modify-phases %standard-phases
(replace 'build
(lambda _
(invoke "make" "cross-riscv64")))
;; Cross compilers don't get the default config so we need to add custom
;; configuration like explained in `make help`
(add-before 'configure 'configure-cross
(lambda _
(call-with-output-file "config-cross.mak"
(lambda (port)
(display
(string-append "CRT-riscv64 = " #$libccross "/lib") port)
(newline port)
(display
(string-append "LIB-riscv64 = " #$libccross "/lib") port)
(newline port)
(display
(string-append "INC-riscv64 = " #$libccross "/include" ":" #$output "/include") port)))))
;(add-before 'install 'fail (lambda _ (error "Fail for debug")))
;; Default `make install` phase does not install the cross compilers
;; We have to do it by hand
(replace 'install
(lambda* (#:key inputs outputs #:allow-other-keys)
;; Make an empty libtcc1. Needed because:
;; - Later it'll try to dynamically link it (needed)
;; - It only has i386 related definitions, and fails if it's compiled in other arch (make it empty)
(call-with-output-file "lib/libtcc1.c"
(lambda (p) (display "" p)))
(invoke "./riscv64-tcc" "-c" "lib/libtcc1.c" "-o" "libtcc1.o")
(invoke "./riscv64-tcc" "-ar" "cr" "libtcc1-riscv64.a" "libtcc1.o")
;; Now install
(install-file "libtcc1-riscv64.a"
(string-append (assoc-ref outputs "out") "/lib/tcc"))
(install-file "riscv64-tcc"
(string-append (assoc-ref outputs "out") "/bin"))
(copy-recursively "include"
(string-append (assoc-ref outputs "out") "/include")))))))
(native-search-paths
(list (search-path-specification
(variable "CPATH")
(files '("include")))
(search-path-specification
(variable "LIBRARY_PATH")
(files '("lib" "lib64")))))
(outputs (list "out" "debug"))
(synopsis "Tiny and fast C compiler")
(description
"TCC, also referred to as \"TinyCC\", is a small and fast C compiler
written in C. It supports ANSI C with GNU and extensions and most of the C99
standard.")
(home-page "http://www.tinycc.org/")
;; An attempt to re-licence tcc under the Expat licence is underway but not
;; (if ever) complete. See the RELICENSING file for more information.
(license license:lgpl2.1+)))
tcc-mine

View File

@ -19,7 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define MAX_OPERANDS 3
@ -221,7 +223,11 @@ static const uint8_t segment_prefixes[] = {
static const ASMInstr asm_instrs[] = {
#define ALT(x) x
/* This removes a 0x0f in the second byte */
#if HAVE_LONG_LONG
#define O(o) ((uint64_t) ((((o) & 0xff00) == 0x0f00) ? ((((o) >> 8) & ~0xff) | ((o) & 0xff)) : (o)))
#else
#define O(o) ((uint32_t) ((((o) & 0xff00) == 0x0f00) ? ((((o) >> 8) & ~0xff) | ((o) & 0xff)) : (o)))
#endif
/* This constructs instr_type from opcode, type and group. */
#define T(o,i,g) ((i) | ((g) << OPC_GROUP_SHIFT) | ((((o) & 0xff00) == 0x0f00) ? OPC_0F : 0))
#define DEF_ASM_OP0(name, opcode)

View File

@ -74,7 +74,9 @@ enum {
/******************************************************/
#else /* ! TARGET_DEFS_ONLY */
/******************************************************/
#ifndef _TCC_H
#include "tcc.h"
#endif
/* define to 1/0 to [not] have EBX as 4th register */
#define USE_EBX 0
@ -1041,6 +1043,7 @@ ST_FUNC void gen_cvt_itof(int t)
/* convert fp to int 't' type */
ST_FUNC void gen_cvt_ftoi(int t)
{
#if HAVE_FLOAT
int bt = vtop->type.t & VT_BTYPE;
if (bt == VT_FLOAT)
vpush_global_sym(&func_old_type, TOK___fixsfdi);
@ -1053,6 +1056,7 @@ ST_FUNC void gen_cvt_ftoi(int t)
vpushi(0);
vtop->r = REG_IRET;
vtop->r2 = REG_LRET;
#endif // HAVE_FLOAT
}
/* convert from one floating point type to another */

View File

@ -20,7 +20,9 @@
#else /* !TARGET_DEFS_ONLY */
#ifndef _TCC_H
#include "tcc.h"
#endif
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
relocations, returns -1. */

View File

@ -38,6 +38,23 @@
#define LDBL_MAX_EXP 16384
#define LDBL_MAX 1.18973149535723176502e+4932L
#define LDBL_MAX_10_EXP 4932
#define DECIMAL_DIG 21
#elif defined __aarch64__ || defined __riscv
/*
* Use values from:
* gcc -dM -E -xc /dev/null | grep LDBL | sed -e "s/__//g"
*/
#define LDBL_MANT_DIG 113
#define LDBL_DIG 33
#define LDBL_EPSILON 1.92592994438723585305597794258492732e-34L
#define LDBL_MIN_EXP (-16381)
#define LDBL_MIN 3.36210314311209350626267781732175260e-4932L
#define LDBL_MIN_10_EXP (-4931)
#define LDBL_MAX_EXP 16384
#define LDBL_MAX 1.18973149535723176508575932662800702e+4932L
#define LDBL_MAX_EXP 16384
#define DECIMAL_DIG 36
#else

View File

@ -13,12 +13,16 @@ typedef __SIZE_TYPE__ uintptr_t;
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
#if HAVE_LONG_LONG
typedef signed long long int int64_t;
#endif
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
#if HAVE_LONG_LONG
typedef unsigned long long int uint64_t;
#endif
#endif
#ifndef NULL
#define NULL ((void*)0)

60
install.sh Executable file
View File

@ -0,0 +1,60 @@
#! /bin/sh
set -e
if [ "$V" = 1 -o "$V" = 2 ]; then
set -x
fi
arch=$(uname -m)
case $arch in
aarch*)
cpu=arm
mes_cpu=arm
tcc_cpu=arm
triplet=arm-linux-gnueabihf
cross_prefix=${triplet}-
;;
arm*|aarch*)
cpu=arm
mes_cpu=arm
tcc_cpu=arm
triplet=arm-unknown-linux-gnueabihf
cross_prefix=${triplet}-
;;
*)
cpu=x86
mes_cpu=x86
tcc_cpu=i386
triplet=i686-unknown-linux-gnu
cross_prefix=${triplet}-
;;
esac
prefix=${prefix-usr}
MES_PREFIX=${MES_PREFIX-mes}
mkdir -p $prefix/bin
cp tcc $prefix/bin
tar -C $MES_PREFIX -cf- include | tar -C $prefix -xf-
mkdir -p $prefix/lib
cp crt1.o $prefix/lib/crt1.o
cp crti.o $prefix/lib/crti.o
cp crtn.o $prefix/lib/crtn.o
mkdir -p $prefix/lib/tcc
cp libc.a $prefix/lib
cp libtcc1.a $prefix/lib/tcc
if [ $mes_cpu = arm ]; then
cp libtcc1-mes.a $prefix/lib/tcc
fi
cp libgetopt.a $prefix/lib
mkdir -p $prefix/share
cp crt1.c $prefix/share
cp crti.c $prefix/share
cp crtn.c $prefix/share
cp libc.c $prefix/share
cp libgetopt.c $prefix/share

View File

@ -41,6 +41,7 @@ I386_O = libtcc1.o alloca86.o alloca86-bt.o
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o
ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o
ARM64_O = lib-arm64.o
RISCV64_O = lib-arm64.o
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
OBJ-i386 = $(I386_O) $(BCHECK_O)
@ -56,6 +57,7 @@ OBJ-arm-vfp = $(ARM_O)
OBJ-arm-eabi = $(ARM_O)
OBJ-arm-eabihf = $(ARM_O)
OBJ-arm-wince = $(ARM_O) $(WIN_O)
OBJ-riscv64 = $(RISCV64_O) $(BCHECK_O)
$(BIN) : $(patsubst %.o,$(X)%.o,$(OBJ-$T))
$(XAR) rcs $@ $^

View File

@ -24,10 +24,12 @@ void *memcpy(void*,void*,__SIZE_TYPE__);
#include <string.h>
#endif
#ifndef __riscv
void __clear_cache(void *beg, void *end)
{
__arm64_clear_cache(beg, end);
}
#endif
typedef struct {
uint64_t x0, x1;

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/********************************************************/
/* global variables */
@ -64,6 +66,11 @@ static int nb_states;
#include "x86_64-link.c"
#include "i386-asm.c"
#endif
#ifdef TCC_TARGET_RISCV64
#include "riscv64-gen.c"
#include "riscv64-link.c"
#include "riscv64-asm.c"
#endif
#ifdef CONFIG_TCC_ASM
#include "tccasm.c"
#endif
@ -627,7 +634,11 @@ static int tcc_compile(TCCState *s1)
Sym *define_start;
define_start = define_stack;
#if HAVE_SETJMP
if (setjmp(s1->error_jmp_buf) == 0) {
#else
if (1) {
#endif
s1->nb_errors = 0;
s1->error_set_jmp_enabled = 1;
@ -734,6 +745,9 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_state = s;
++nb_states;
#if BOOTSTRAP
s->static_link = 1;
#endif
s->alacarte_link = 1;
s->nocommon = 1;
s->warn_implicit_function_declaration = 1;
@ -775,6 +789,8 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
tcc_define_symbol(s, "__STDC_HOSTED__", NULL);
tcc_define_symbol(s, "__SIZEOF_LONG_LONG__", "8");
/* target defines */
#if defined(TCC_TARGET_I386)
tcc_define_symbol(s, "__i386__", NULL);
@ -782,6 +798,18 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_define_symbol(s, "i386", NULL);
#elif defined(TCC_TARGET_X86_64)
tcc_define_symbol(s, "__x86_64__", NULL);
#elif defined(TCC_TARGET_RISCV64)
tcc_define_symbol(s, "__riscv", NULL);
tcc_define_symbol(s, "__riscv_xlen", "64");
tcc_define_symbol(s, "__riscv_flen", "64");
tcc_define_symbol(s, "__riscv_div", NULL);
tcc_define_symbol(s, "__riscv_mul", NULL);
tcc_define_symbol(s, "__riscv_fdiv", NULL);
tcc_define_symbol(s, "__riscv_fsqrt", NULL);
tcc_define_symbol(s, "__riscv_float_abi_double", NULL);
// This should be defined for every target but in riscv <wordsize.h>
// uses it to compare against __riscv_xlen, so we really need it.
tcc_define_symbol(s, "__SIZEOF_POINTER__", "8");
#elif defined(TCC_TARGET_ARM)
tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
tcc_define_symbol(s, "__arm_elf__", NULL);

57
link.sh Executable file
View File

@ -0,0 +1,57 @@
#! /bin/sh
set -ex
rm -f 1.a 2.a
MES_PREFIX=${MES_PREFIX-mes}
MES_SOURCE=${MES_SOURCE-mes-source}
arch=$(uname -m)
case $arch in
aarch*)
cpu=arm
triplet=arm-linux-gnueabihf
cross_prefix=${triplet}-
;;
arm*|aarch*)
cpu=arm
triplet=arm-unknown-linux-gnueabihf
cross_prefix=${triplet}-
;;
*)
cpu=x86
triplet=i686-unknown-linux-gnu
cross_prefix=${triplet}-
;;
esac
export cpu
export cross_prefix
export triplet
c=${1-$MES_PREFIX/scaffold/main}
b=scaffold/${c##*/}
rm -f "$b".mes-gcc-out
rm -f "$b".mes-out
./${cross_prefix}tcc\
-static -g -o "$b".mes-gcc-out\
-I.\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
"$c".c \
2> "$b".mes-gcc-stderr
set +e
${MES_TCC-./mes-tcc}\
-static -g -o "$b".mes-out
-I.\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
2> "$b".mes-stderr
objdump -d "$b".mes-gcc-out > "$b".mes-gcc-d
objdump -d "$b".mes-out > "$b".mes-d
#readelf -a a.${cross_prefix}out > 1.r
#readelf -a a.mes-out > 2.r
#diff -y 1.a 2.a
echo diff -y "$b".mes-gcc-stderr "$b".mes-stderr
echo diff -y "$b".mes-gcc-d "$b".mes-d
"$b".mes-out

12
manifest.scm Normal file
View File

@ -0,0 +1,12 @@
(load "guix.scm")
(define triplet "riscv64-linux-gnu")
(packages->manifest
(let* ((binutils (cross-binutils triplet))
(libc (cross-libc triplet)))
(list tcc-mine
(list gcc "lib")
binutils
libc
(list libc "static"))))

731
riscv64-asm.c Normal file
View File

@ -0,0 +1,731 @@
/*************************************************************/
/*
* RISCV64 assembler for TCC
*
*/
#ifdef TARGET_DEFS_ONLY
#define CONFIG_TCC_ASM
#define NB_ASM_REGS 32
ST_FUNC void g(int c);
ST_FUNC void gen_le16(int c);
ST_FUNC void gen_le32(int c);
/*************************************************************/
#else
/*************************************************************/
#define USING_GLOBALS
#include "tcc.h"
/* XXX: make it faster ? */
ST_FUNC void g(int c)
{
int ind1;
if (nocode_wanted)
return;
ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
cur_text_section->data[ind] = c;
ind = ind1;
}
ST_FUNC void gen_le16 (int i)
{
g(i);
g(i>>8);
}
ST_FUNC void gen_le32 (int i)
{
int ind1;
if (nocode_wanted)
return;
ind1 = ind + 4;
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
cur_text_section->data[ind++] = i & 0xFF;
cur_text_section->data[ind++] = (i >> 8) & 0xFF;
cur_text_section->data[ind++] = (i >> 16) & 0xFF;
cur_text_section->data[ind++] = (i >> 24) & 0xFF;
}
ST_FUNC void gen_expr32(ExprValue *pe)
{
gen_le32(pe->v);
}
static void asm_emit_opcode(uint32_t opcode) {
gen_le32(opcode);
}
static void asm_nullary_opcode(TCCState *s1, int token)
{
switch (token) {
// Sync instructions
case TOK_ASM_fence: // I
asm_emit_opcode((0x3 << 2) | 3 | (0 << 12));
return;
case TOK_ASM_fence_i: // I
asm_emit_opcode((0x3 << 2) | 3| (1 << 12));
return;
// System calls
case TOK_ASM_scall: // I (pseudo)
asm_emit_opcode((0x1C << 2) | 3 | (0 << 12));
return;
case TOK_ASM_sbreak: // I (pseudo)
asm_emit_opcode((0x1C << 2) | 3 | (0 << 12) | (1 << 20));
return;
// Privileged Instructions
case TOK_ASM_ecall:
asm_emit_opcode((0x1C << 2) | 3 | (0 << 20));
return;
case TOK_ASM_ebreak:
asm_emit_opcode((0x1C << 2) | 3 | (1 << 20));
return;
// Other
case TOK_ASM_wfi:
asm_emit_opcode((0x1C << 2) | 3 | (0x105 << 20));
return;
default:
expect("nullary instruction");
}
}
enum {
OPT_REG,
OPT_IM12S,
OPT_IM32,
};
#define OP_REG (1 << OPT_REG)
#define OP_IM32 (1 << OPT_IM32)
#define OP_IM12S (1 << OPT_IM12S)
typedef struct Operand {
uint32_t type;
union {
uint8_t reg;
uint16_t regset;
ExprValue e;
};
} Operand;
/* Parse a text containing operand and store the result in OP */
static void parse_operand(TCCState *s1, Operand *op)
{
ExprValue e;
int8_t reg;
op->type = 0;
if ((reg = asm_parse_regvar(tok)) != -1) {
next(); // skip register name
op->type = OP_REG;
op->reg = (uint8_t) reg;
return;
} else if (tok == '$') {
/* constant value */
next(); // skip '#' or '$'
}
asm_expr(s1, &e);
op->type = OP_IM32;
op->e = e;
if (!op->e.sym) {
if ((int) op->e.v >= -2048 && (int) op->e.v < 2048)
op->type = OP_IM12S;
} else
expect("operand");
}
#define ENCODE_RS1(register_index) ((register_index) << 15)
#define ENCODE_RS2(register_index) ((register_index) << 20)
#define ENCODE_RD(register_index) ((register_index) << 7)
// Note: Those all map to CSR--so they are pseudo-instructions.
static void asm_unary_opcode(TCCState *s1, int token)
{
uint32_t opcode = (0x1C << 2) | 3 | (2 << 12);
Operand op;
parse_operand(s1, &op);
if (op.type != OP_REG) {
expect("register");
return;
}
opcode |= ENCODE_RD(op.reg);
switch (token) {
case TOK_ASM_rdcycle:
asm_emit_opcode(opcode | (0xC00 << 20));
return;
case TOK_ASM_rdcycleh:
asm_emit_opcode(opcode | (0xC80 << 20));
return;
case TOK_ASM_rdtime:
asm_emit_opcode(opcode | (0xC01 << 20) | ENCODE_RD(op.reg));
return;
case TOK_ASM_rdtimeh:
asm_emit_opcode(opcode | (0xC81 << 20) | ENCODE_RD(op.reg));
return;
case TOK_ASM_rdinstret:
asm_emit_opcode(opcode | (0xC02 << 20) | ENCODE_RD(op.reg));
return;
case TOK_ASM_rdinstreth:
asm_emit_opcode(opcode | (0xC82 << 20) | ENCODE_RD(op.reg));
return;
default:
expect("unary instruction");
}
}
static void asm_emit_u(int token, uint32_t opcode, const Operand* rd, const Operand* rs2)
{
if (rd->type != OP_REG) {
tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs2->type != OP_IM12S && rs2->type != OP_IM32) {
tcc_error("'%s': Expected second source operand that is an immediate value", get_tok_str(token, NULL));
return;
} else if (rs2->e.v >= 0x100000) {
tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 0xfffff", get_tok_str(token, NULL));
return;
}
/* U-type instruction:
31...12 imm[31:12]
11...7 rd
6...0 opcode */
gen_le32(opcode | ENCODE_RD(rd->reg) | (rs2->e.v << 12));
}
static void asm_binary_opcode(TCCState* s1, int token)
{
Operand ops[2];
parse_operand(s1, &ops[0]);
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[1]);
switch (token) {
case TOK_ASM_lui:
asm_emit_u(token, (0xD << 2) | 3, &ops[0], &ops[1]);
return;
case TOK_ASM_auipc:
asm_emit_u(token, (0x05 << 2) | 3, &ops[0], &ops[1]);
return;
default:
expect("binary instruction");
}
}
/* caller: Add funct3, funct7 into opcode */
static void asm_emit_r(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
{
if (rd->type != OP_REG) {
tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs1->type != OP_REG) {
tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs2->type != OP_REG) {
tcc_error("'%s': Expected second source operand that is a register or immediate", get_tok_str(token, NULL));
return;
}
/* R-type instruction:
31...25 funct7
24...20 rs2
19...15 rs1
14...12 funct3
11...7 rd
6...0 opcode */
gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg));
}
/* caller: Add funct3 into opcode */
static void asm_emit_i(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
{
if (rd->type != OP_REG) {
tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs1->type != OP_REG) {
tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs2->type != OP_IM12S) {
tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 4095", get_tok_str(token, NULL));
return;
}
/* I-type instruction:
31...20 imm[11:0]
19...15 rs1
14...12 funct3
11...7 rd
6...0 opcode */
gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | (rs2->e.v << 20));
}
static void asm_shift_opcode(TCCState *s1, int token)
{
Operand ops[3];
parse_operand(s1, &ops[0]);
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[1]);
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[2]);
switch (token) {
case TOK_ASM_sll:
asm_emit_r(token, (0xC << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_slli:
asm_emit_i(token, (4 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_srl:
asm_emit_r(token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_srli:
asm_emit_i(token, (0x4 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sra:
asm_emit_r(token, (0xC << 2) | 3 | (5 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_srai:
asm_emit_i(token, (0x4 << 2) | 3 | (5 << 12) | (16 << 26), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sllw:
asm_emit_r(token, (0xE << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_slliw:
asm_emit_i(token, (6 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_srlw:
asm_emit_r(token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_srliw:
asm_emit_i(token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sraw:
asm_emit_r(token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sraiw:
asm_emit_i(token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
default:
expect("shift instruction");
}
}
static void asm_data_processing_opcode(TCCState* s1, int token)
{
Operand ops[3];
parse_operand(s1, &ops[0]);
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[1]);
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[2]);
switch (token) {
// Arithmetic (RD,RS1,(RS2|IMM)); R-format, I-format or U-format
case TOK_ASM_add:
asm_emit_r(token, (0xC << 2) | 3, &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_addi:
asm_emit_i(token, (4 << 2) | 3, &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sub:
asm_emit_r(token, (0xC << 2) | 3 | (32 << 25), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_addw:
asm_emit_r(token, (0xE << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_addiw: // 64 bit
asm_emit_i(token, (0x6 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_subw:
asm_emit_r(token, (0xE << 2) | 3 | (0 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]);
return;
// Logical (RD,RS1,(RS2|IMM)); R-format or I-format
case TOK_ASM_xor:
asm_emit_r(token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_xori:
asm_emit_i(token, (0x4 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_or:
asm_emit_r(token, (0xC << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_ori:
asm_emit_i(token, (0x4 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_and:
asm_emit_r(token, (0xC << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_andi:
asm_emit_i(token, (0x4 << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]);
return;
// Compare (RD,RS1,(RS2|IMM)); R-format or I-format
case TOK_ASM_slt:
asm_emit_r(token, (0xC << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_slti:
asm_emit_i(token, (0x4 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sltu:
asm_emit_r(token, (0xC << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sltiu:
asm_emit_i(token, (0x4 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
return;
default:
expect("known data processing instruction");
}
}
/* caller: Add funct3 to opcode */
static void asm_emit_s(int token, uint32_t opcode, const Operand* rs1, const Operand* rs2, const Operand* imm)
{
if (rs1->type != OP_REG) {
tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs2->type != OP_REG) {
tcc_error("'%s': Expected second source operand that is a register", get_tok_str(token, NULL));
return;
}
if (imm->type != OP_IM12S) {
tcc_error("'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(token, NULL));
return;
}
{
uint16_t v = imm->e.v;
/* S-type instruction:
31...25 imm[11:5]
24...20 rs2
19...15 rs1
14...12 funct3
11...7 imm[4:0]
6...0 opcode
opcode always fixed pos. */
gen_le32(opcode | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg) | ((v & 0x1F) << 7) | ((v >> 5) << 25));
}
}
static void asm_data_transfer_opcode(TCCState* s1, int token)
{
Operand ops[3];
parse_operand(s1, &ops[0]);
if (ops[0].type != OP_REG) {
expect("register");
return;
}
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[1]);
if (ops[1].type != OP_REG) {
expect("register");
return;
}
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[2]);
switch (token) {
// Loads (RD,RS1,I); I-format
case TOK_ASM_lb:
asm_emit_i(token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_lh:
asm_emit_i(token, (0x0 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_lw:
asm_emit_i(token, (0x0 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_lbu:
asm_emit_i(token, (0x0 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_lhu:
asm_emit_i(token, (0x0 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
// 64 bit
case TOK_ASM_ld:
asm_emit_i(token, (0x0 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_lwu:
asm_emit_i(token, (0x0 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
return;
// Stores (RS1,RS2,I); S-format
case TOK_ASM_sb:
asm_emit_s(token, (0x8 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sh:
asm_emit_s(token, (0x8 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sw:
asm_emit_s(token, (0x8 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sd:
asm_emit_s(token, (0x8 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
return;
default:
expect("known data transfer instruction");
}
}
static void asm_branch_opcode(TCCState* s1, int token)
{
// Branch (RS1,RS2,IMM); SB-format
uint32_t opcode = (0x18 << 2) | 3;
uint32_t offset = 0;
Operand ops[3];
parse_operand(s1, &ops[0]);
if (ops[0].type != OP_REG) {
expect("register");
return;
}
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[1]);
if (ops[1].type != OP_REG) {
expect("register");
return;
}
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[2]);
if (ops[2].type != OP_IM12S) {
tcc_error("'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(token, NULL));
return;
}
offset = ops[2].e.v;
if (offset & 1) {
tcc_error("'%s': Expected third operand that is an even immediate value", get_tok_str(token, NULL));
return;
}
switch (token) {
case TOK_ASM_beq:
opcode |= 0 << 12;
break;
case TOK_ASM_bne:
opcode |= 1 << 12;
break;
case TOK_ASM_blt:
opcode |= 4 << 12;
break;
case TOK_ASM_bge:
opcode |= 5 << 12;
break;
case TOK_ASM_bltu:
opcode |= 6 << 12;
break;
case TOK_ASM_bgeu:
opcode |= 7 << 12;
break;
default:
expect("known branch instruction");
}
asm_emit_opcode(opcode | ENCODE_RS1(ops[0].reg) | ENCODE_RS2(ops[1].reg) | (((offset >> 1) & 0xF) << 8) | (((offset >> 5) & 0x1f) << 25) | (((offset >> 11) & 1) << 7) | (((offset >> 12) & 1) << 31));
}
ST_FUNC void asm_opcode(TCCState *s1, int token)
{
switch (token) {
case TOK_ASM_fence:
case TOK_ASM_fence_i:
case TOK_ASM_scall:
case TOK_ASM_sbreak:
case TOK_ASM_ecall:
case TOK_ASM_ebreak:
case TOK_ASM_mrts:
case TOK_ASM_mrth:
case TOK_ASM_hrts:
case TOK_ASM_wfi:
asm_nullary_opcode(s1, token);
return;
case TOK_ASM_rdcycle:
case TOK_ASM_rdcycleh:
case TOK_ASM_rdtime:
case TOK_ASM_rdtimeh:
case TOK_ASM_rdinstret:
case TOK_ASM_rdinstreth:
asm_unary_opcode(s1, token);
return;
case TOK_ASM_lui:
case TOK_ASM_auipc:
asm_binary_opcode(s1, token);
return;
case TOK_ASM_sll:
case TOK_ASM_slli:
case TOK_ASM_srl:
case TOK_ASM_srli:
case TOK_ASM_sra:
case TOK_ASM_srai:
case TOK_ASM_sllw:
case TOK_ASM_slld:
case TOK_ASM_slliw:
case TOK_ASM_sllid:
case TOK_ASM_srlw:
case TOK_ASM_srld:
case TOK_ASM_srliw:
case TOK_ASM_srlid:
case TOK_ASM_sraw:
case TOK_ASM_srad:
case TOK_ASM_sraiw:
case TOK_ASM_sraid:
asm_shift_opcode(s1, token);
return;
case TOK_ASM_add:
case TOK_ASM_addi:
case TOK_ASM_sub:
case TOK_ASM_addw:
case TOK_ASM_addd:
case TOK_ASM_addiw:
case TOK_ASM_addid:
case TOK_ASM_subw:
case TOK_ASM_subd:
case TOK_ASM_xor:
case TOK_ASM_xori:
case TOK_ASM_or:
case TOK_ASM_ori:
case TOK_ASM_and:
case TOK_ASM_andi:
case TOK_ASM_slt:
case TOK_ASM_slti:
case TOK_ASM_sltu:
case TOK_ASM_sltiu:
asm_data_processing_opcode(s1, token);
return;
case TOK_ASM_lb:
case TOK_ASM_lh:
case TOK_ASM_lw:
case TOK_ASM_lbu:
case TOK_ASM_lhu:
case TOK_ASM_ld:
case TOK_ASM_lwu:
case TOK_ASM_sb:
case TOK_ASM_sh:
case TOK_ASM_sw:
case TOK_ASM_sd:
asm_data_transfer_opcode(s1, token);
return;
case TOK_ASM_beq:
case TOK_ASM_bne:
case TOK_ASM_blt:
case TOK_ASM_bge:
case TOK_ASM_bltu:
case TOK_ASM_bgeu:
asm_branch_opcode(s1, token);
return;
default:
expect("known instruction");
}
}
ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
{
tcc_error("RISCV64 asm not implemented.");
}
/* generate prolog and epilog code for asm statement */
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
int nb_outputs, int is_output,
uint8_t *clobber_regs,
int out_reg)
{
}
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
int nb_operands, int nb_outputs,
const uint8_t *clobber_regs,
int *pout_reg)
{
}
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
{
int reg;
TokenSym *ts;
if (!strcmp(str, "memory") ||
!strcmp(str, "cc") ||
!strcmp(str, "flags"))
return;
ts = tok_alloc(str, strlen(str));
reg = asm_parse_regvar(ts->tok);
if (reg == -1) {
tcc_error("invalid clobber register '%s'", str);
}
clobber_regs[reg] = 1;
}
ST_FUNC int asm_parse_regvar (int t)
{
if (t >= TOK_ASM_x0 && t <= TOK_ASM_pc) { /* register name */
if (t >= TOK_ASM_zero && t <= TOK_ASM_t6)
return t - TOK_ASM_zero;
switch (t) {
case TOK_ASM_s0:
return 8;
case TOK_ASM_pc:
tcc_error("PC register not implemented.");
default:
return t - TOK_ASM_x0;
}
} else
return -1;
}
/*************************************************************/
#endif /* ndef TARGET_DEFS_ONLY */

1538
riscv64-gen.c Normal file

File diff suppressed because it is too large Load Diff

359
riscv64-link.c Normal file
View File

@ -0,0 +1,359 @@
#ifdef TARGET_DEFS_ONLY
#define EM_TCC_TARGET EM_RISCV
#define R_DATA_32 R_RISCV_32
#define R_DATA_PTR R_RISCV_64
#define R_JMP_SLOT R_RISCV_JUMP_SLOT
#define R_GLOB_DAT R_RISCV_64
#define R_COPY R_RISCV_COPY
#define R_RELATIVE R_RISCV_RELATIVE
#define R_NUM R_RISCV_NUM
#define ELF_START_ADDR 0x00010000
#define ELF_PAGE_SIZE 0x1000
#define PCRELATIVE_DLLPLT 1
#define RELOCATE_DLLPLT 1
#else /* !TARGET_DEFS_ONLY */
//#define DEBUG_RELOC
#include "tcc.h"
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
relocations, returns -1. */
int code_reloc (int reloc_type)
{
switch (reloc_type) {
case R_RISCV_BRANCH:
case R_RISCV_CALL:
case R_RISCV_JAL:
return 1;
case R_RISCV_GOT_HI20:
case R_RISCV_PCREL_HI20:
case R_RISCV_PCREL_LO12_I:
case R_RISCV_PCREL_LO12_S:
case R_RISCV_32_PCREL:
case R_RISCV_SET6:
case R_RISCV_SUB6:
case R_RISCV_ADD16:
case R_RISCV_ADD32:
case R_RISCV_ADD64:
case R_RISCV_SUB16:
case R_RISCV_SUB32:
case R_RISCV_SUB64:
case R_RISCV_32:
case R_RISCV_64:
return 0;
case R_RISCV_CALL_PLT:
return 1;
}
return -1;
}
/* Returns an enumerator to describe whether and when the relocation needs a
GOT and/or PLT entry to be created. See tcc.h for a description of the
different values. */
int gotplt_entry_type (int reloc_type)
{
switch (reloc_type) {
case R_RISCV_ALIGN:
case R_RISCV_RELAX:
case R_RISCV_RVC_BRANCH:
case R_RISCV_RVC_JUMP:
case R_RISCV_JUMP_SLOT:
case R_RISCV_SET6:
case R_RISCV_SUB6:
case R_RISCV_ADD16:
case R_RISCV_SUB16:
return NO_GOTPLT_ENTRY;
case R_RISCV_BRANCH:
case R_RISCV_CALL:
case R_RISCV_PCREL_HI20:
case R_RISCV_PCREL_LO12_I:
case R_RISCV_PCREL_LO12_S:
case R_RISCV_32_PCREL:
case R_RISCV_ADD32:
case R_RISCV_ADD64:
case R_RISCV_SUB32:
case R_RISCV_SUB64:
case R_RISCV_32:
case R_RISCV_64:
case R_RISCV_JAL:
case R_RISCV_CALL_PLT:
return AUTO_GOTPLT_ENTRY;
case R_RISCV_GOT_HI20:
return ALWAYS_GOTPLT_ENTRY;
}
return -1;
}
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{
Section *plt = s1->plt;
uint8_t *p;
unsigned plt_offset;
if (plt->data_offset == 0)
section_ptr_add(plt, 32);
plt_offset = plt->data_offset;
p = section_ptr_add(plt, 16);
write64le(p, got_offset);
return plt_offset;
}
static ElfW_Rel *qrel; /* ptr to next reloc entry reused */
void relocate_init(Section *sr)
{
qrel = (ElfW_Rel *) sr->data;
}
/* relocate the PLT: compute addresses and offsets in the PLT now that final
address for PLT and GOT are known (see fill_program_header) */
ST_FUNC void relocate_plt(TCCState *s1)
{
uint8_t *p, *p_end;
if (!s1->plt)
return;
p = s1->plt->data;
p_end = p + s1->plt->data_offset;
if (p < p_end) {
uint64_t plt = s1->plt->sh_addr;
uint64_t got = s1->got->sh_addr;
uint64_t off = (got - plt + 0x800) >> 12;
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
write32le(p, 0x397 | (off << 12)); // auipc t2, %pcrel_hi(got)
write32le(p + 4, 0x41c30333); // sub t1, t1, t3
write32le(p + 8, 0x0003be03 // ld t3, %pcrel_lo(got)(t2)
| (((got - plt) & 0xfff) << 20));
write32le(p + 12, 0xfd430313); // addi t1, t1, -(32+12)
write32le(p + 16, 0x00038293 // addi t0, t2, %pcrel_lo(got)
| (((got - plt) & 0xfff) << 20));
write32le(p + 20, 0x00135313); // srli t1, t1, log2(16/PTRSIZE)
write32le(p + 24, 0x0082b283); // ld t0, PTRSIZE(t0)
write32le(p + 28, 0x000e0067); // jr t3
p += 32;
while (p < p_end) {
uint64_t pc = plt + (p - s1->plt->data);
uint64_t addr = got + read64le(p);
uint64_t off = (addr - pc + 0x800) >> 12;
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
write32le(p, 0xe17 | (off << 12)); // auipc t3, %pcrel_hi(func@got)
write32le(p + 4, 0x000e3e03 // ld t3, %pcrel_lo(func@got)(t3)
| (((addr - pc) & 0xfff) << 20));
write32le(p + 8, 0x000e0367); // jalr t1, t3
write32le(p + 12, 0x00000013); // nop
p += 16;
}
}
if (s1->plt->reloc) {
ElfW_Rel *rel;
p = s1->got->data;
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
write64le(p + rel->r_offset, s1->plt->sh_addr);
}
}
}
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
addr_t addr, addr_t val)
{
uint64_t off64;
uint32_t off32;
int sym_index = ELFW(R_SYM)(rel->r_info), esym_index;
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
switch(type) {
case R_RISCV_ALIGN:
case R_RISCV_RELAX:
return;
case R_RISCV_BRANCH:
off64 = val - addr;
if ((off64 + (1 << 12)) & ~(uint64_t)0x1ffe)
tcc_error("R_RISCV_BRANCH relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64 >> 1;
write32le(ptr, (read32le(ptr) & ~0xfe000f80)
| ((off32 & 0x800) << 20)
| ((off32 & 0x3f0) << 21)
| ((off32 & 0x00f) << 8)
| ((off32 & 0x400) >> 3));
return;
case R_RISCV_JAL:
off64 = val - addr;
if ((off64 + (1 << 21)) & ~(((uint64_t)1 << 22) - 2))
tcc_error("R_RISCV_JAL relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64;
write32le(ptr, (read32le(ptr) & 0xfff)
| (((off32 >> 12) & 0xff) << 12)
| (((off32 >> 11) & 1) << 20)
| (((off32 >> 1) & 0x3ff) << 21)
| (((off32 >> 20) & 1) << 31));
return;
case R_RISCV_CALL:
case R_RISCV_CALL_PLT:
write32le(ptr, (read32le(ptr) & 0xfff)
| ((val - addr + 0x800) & ~0xfff));
write32le(ptr + 4, (read32le(ptr + 4) & 0xfffff)
| (((val - addr) & 0xfff) << 20));
return;
case R_RISCV_PCREL_HI20:
#ifdef DEBUG_RELOC
printf("PCREL_HI20: val=%lx addr=%lx\n", (long)val, (long)addr);
#endif
off64 = (int64_t)(val - addr + 0x800) >> 12;
if ((off64 + ((uint64_t)1 << 20)) >> 21)
tcc_error("R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx sym=%s",
(long)off64, (long)((int64_t)(off64 + ((uint64_t)1 << 20)) >> 21),
symtab_section->link->data + sym->st_name);
write32le(ptr, (read32le(ptr) & 0xfff)
| ((off64 & 0xfffff) << 12));
last_hi.addr = addr;
last_hi.val = val;
return;
case R_RISCV_GOT_HI20:
val = s1->got->sh_addr + get_sym_attr(s1, sym_index, 0)->got_offset;
off64 = (int64_t)(val - addr + 0x800) >> 12;
if ((off64 + ((uint64_t)1 << 20)) >> 21)
tcc_error("R_RISCV_GOT_HI20 relocation failed");
last_hi.addr = addr;
last_hi.val = val;
write32le(ptr, (read32le(ptr) & 0xfff)
| ((off64 & 0xfffff) << 12));
return;
case R_RISCV_PCREL_LO12_I:
#ifdef DEBUG_RELOC
printf("PCREL_LO12_I: val=%lx addr=%lx\n", (long)val, (long)addr);
#endif
if (val != last_hi.addr)
tcc_error("unsupported hi/lo pcrel reloc scheme");
val = last_hi.val;
addr = last_hi.addr;
write32le(ptr, (read32le(ptr) & 0xfffff)
| (((val - addr) & 0xfff) << 20));
return;
case R_RISCV_PCREL_LO12_S:
if (val != last_hi.addr)
tcc_error("unsupported hi/lo pcrel reloc scheme");
val = last_hi.val;
addr = last_hi.addr;
off32 = val - addr;
write32le(ptr, (read32le(ptr) & ~0xfe000f80)
| ((off32 & 0xfe0) << 20)
| ((off32 & 0x01f) << 7));
return;
case R_RISCV_RVC_BRANCH:
off64 = (val - addr);
if ((off64 + (1 << 8)) & ~(uint64_t)0x1fe)
tcc_error("R_RISCV_RVC_BRANCH relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64;
write16le(ptr, (read16le(ptr) & 0xe383)
| (((off32 >> 5) & 1) << 2)
| (((off32 >> 1) & 3) << 3)
| (((off32 >> 6) & 3) << 5)
| (((off32 >> 3) & 3) << 10)
| (((off32 >> 8) & 1) << 12));
return;
case R_RISCV_RVC_JUMP:
off64 = (val - addr);
if ((off64 + (1 << 11)) & ~(uint64_t)0xffe)
tcc_error("R_RISCV_RVC_BRANCH relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64;
write16le(ptr, (read16le(ptr) & 0xe003)
| (((off32 >> 5) & 1) << 2)
| (((off32 >> 1) & 7) << 3)
| (((off32 >> 7) & 1) << 6)
| (((off32 >> 6) & 1) << 7)
| (((off32 >> 10) & 1) << 8)
| (((off32 >> 8) & 3) << 9)
| (((off32 >> 4) & 1) << 11)
| (((off32 >> 11) & 1) << 12));
return;
case R_RISCV_32:
if (s1->output_type == TCC_OUTPUT_DLL) {
/* XXX: this logic may depend on TCC's codegen
now TCC uses R_RISCV_RELATIVE even for a 64bit pointer */
qrel->r_offset = rel->r_offset;
qrel->r_info = ELFW(R_INFO)(0, R_RISCV_RELATIVE);
/* Use sign extension! */
qrel->r_addend = (int)read32le(ptr) + val;
qrel++;
}
add32le(ptr, val);
return;
case R_RISCV_64:
if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
qrel->r_offset = rel->r_offset;
if (esym_index) {
qrel->r_info = ELFW(R_INFO)(esym_index, R_RISCV_64);
qrel->r_addend = rel->r_addend;
qrel++;
break;
} else {
qrel->r_info = ELFW(R_INFO)(0, R_RISCV_RELATIVE);
qrel->r_addend = read64le(ptr) + val;
qrel++;
}
}
case R_RISCV_JUMP_SLOT:
add64le(ptr, val);
return;
case R_RISCV_ADD64:
write64le(ptr, read64le(ptr) + val);
return;
case R_RISCV_ADD32:
write32le(ptr, read32le(ptr) + val);
return;
case R_RISCV_SUB64:
write64le(ptr, read64le(ptr) - val);
return;
case R_RISCV_SUB32:
write32le(ptr, read32le(ptr) - val);
return;
case R_RISCV_ADD16:
write16le(ptr, read16le(ptr) + val);
return;
case R_RISCV_SUB16:
write16le(ptr, read16le(ptr) - val);
return;
case R_RISCV_SET6:
*ptr = (*ptr & ~0x3f) | (val & 0x3f);
return;
case R_RISCV_SUB6:
*ptr = (*ptr & ~0x3f) | ((*ptr - val) & 0x3f);
return;
case R_RISCV_32_PCREL:
case R_RISCV_COPY:
/* XXX */
return;
default:
fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
type, (unsigned)addr, ptr, (unsigned)val);
return;
}
}
#endif

193
riscv64-tok.h Normal file
View File

@ -0,0 +1,193 @@
/* ------------------------------------------------------------------ */
/* WARNING: relative order of tokens is important. */
// See https://riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf
/* register */
DEF_ASM(x0)
DEF_ASM(x1)
DEF_ASM(x2)
DEF_ASM(x3)
DEF_ASM(x4)
DEF_ASM(x5)
DEF_ASM(x6)
DEF_ASM(x7)
DEF_ASM(x8)
DEF_ASM(x9)
DEF_ASM(x10)
DEF_ASM(x11)
DEF_ASM(x12)
DEF_ASM(x13)
DEF_ASM(x14)
DEF_ASM(x15)
DEF_ASM(x16)
DEF_ASM(x17)
DEF_ASM(x18)
DEF_ASM(x19)
DEF_ASM(x20)
DEF_ASM(x21)
DEF_ASM(x22)
DEF_ASM(x23)
DEF_ASM(x24)
DEF_ASM(x25)
DEF_ASM(x26)
DEF_ASM(x27)
DEF_ASM(x28)
DEF_ASM(x29)
DEF_ASM(x30)
DEF_ASM(x31)
/* register macros */
DEF_ASM(zero)
DEF_ASM(ra)
DEF_ASM(sp)
DEF_ASM(gp)
DEF_ASM(tp)
DEF_ASM(t0)
DEF_ASM(t1)
DEF_ASM(t2)
DEF_ASM(fp)
DEF_ASM(s1)
DEF_ASM(a0)
DEF_ASM(a1)
DEF_ASM(a2)
DEF_ASM(a3)
DEF_ASM(a4)
DEF_ASM(a5)
DEF_ASM(a6)
DEF_ASM(a7)
DEF_ASM(s2)
DEF_ASM(s3)
DEF_ASM(s4)
DEF_ASM(s5)
DEF_ASM(s6)
DEF_ASM(s7)
DEF_ASM(s8)
DEF_ASM(s9)
DEF_ASM(s10)
DEF_ASM(s11)
DEF_ASM(t3)
DEF_ASM(t4)
DEF_ASM(t5)
DEF_ASM(t6)
DEF_ASM(s0) // = x8
DEF_ASM(pc)
#define DEF_ASM_WITH_SUFFIX(x, y) \
DEF(TOK_ASM_ ## x ## _ ## y, #x #y)
/* Loads */
DEF_ASM(lb)
DEF_ASM(lh)
DEF_ASM(lw)
DEF_ASM(lbu)
DEF_ASM(lhu)
DEF_ASM(ld)
DEF_ASM(lq)
DEF_ASM(lwu)
DEF_ASM(ldu)
/* Stores */
DEF_ASM(sb)
DEF_ASM(sh)
DEF_ASM(sw)
DEF_ASM(sd)
DEF_ASM(sq)
/* Shifts */
DEF_ASM(sll)
DEF_ASM(slli)
DEF_ASM(srl)
DEF_ASM(srli)
DEF_ASM(sra)
DEF_ASM(srai)
DEF_ASM(sllw)
DEF_ASM(slld)
DEF_ASM(slliw)
DEF_ASM(sllid)
DEF_ASM(srlw)
DEF_ASM(srld)
DEF_ASM(srliw)
DEF_ASM(srlid)
DEF_ASM(sraw)
DEF_ASM(srad)
DEF_ASM(sraiw)
DEF_ASM(sraid)
/* Arithmetic */
DEF_ASM(add)
DEF_ASM(addi)
DEF_ASM(sub)
DEF_ASM(lui)
DEF_ASM(auipc)
DEF_ASM(addw)
DEF_ASM(addd)
DEF_ASM(addiw)
DEF_ASM(addid)
DEF_ASM(subw)
DEF_ASM(subd)
/* Logical */
DEF_ASM(xor)
DEF_ASM(xori)
DEF_ASM(or)
DEF_ASM(ori)
DEF_ASM(and)
DEF_ASM(andi)
/* Compare */
DEF_ASM(slt)
DEF_ASM(slti)
DEF_ASM(sltu)
DEF_ASM(sltiu)
/* Branch */
DEF_ASM(beq)
DEF_ASM(bne)
DEF_ASM(blt)
DEF_ASM(bge)
DEF_ASM(bltu)
DEF_ASM(bgeu)
/* Sync */
DEF_ASM(fence)
DEF_ASM_WITH_SUFFIX(fence, i)
/* System call */
DEF_ASM(scall)
DEF_ASM(sbreak)
/* Counters */
DEF_ASM(rdcycle)
DEF_ASM(rdcycleh)
DEF_ASM(rdtime)
DEF_ASM(rdtimeh)
DEF_ASM(rdinstret)
DEF_ASM(rdinstreth)
/* Privileged Instructions */
DEF_ASM(ecall)
DEF_ASM(ebreak)
DEF_ASM(mrts)
DEF_ASM(mrth)
DEF_ASM(hrts)
DEF_ASM(wfi)

2
tcc.c
View File

@ -153,6 +153,8 @@ static const char version[] =
"ARM"
#elif defined TCC_TARGET_ARM64
"AArch64"
#elif defined TCC_TARGET_RISCV64
"riscv64"
#endif
#ifdef TCC_ARM_HARDFLOAT
" Hard Float"

62
tcc.h
View File

@ -126,11 +126,12 @@
/* #define TCC_TARGET_ARM *//* ARMv4 code generator */
/* #define TCC_TARGET_ARM64 *//* ARMv8 code generator */
/* #define TCC_TARGET_C67 *//* TMS320C67xx code generator */
/* #define TCC_TARGET_RISCV64 *//* risc-v code generator */
/* default target is I386 */
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
!defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_C67) && \
!defined(TCC_TARGET_X86_64)
!defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_RISCV64)
#define TCC_TARGET_I386
#endif
@ -149,6 +150,8 @@
# define TCC_IS_NATIVE
# elif defined __aarch64__ && defined TCC_TARGET_ARM64
# define TCC_IS_NATIVE
# elif defined __riscv && defined __LP64__ && defined TCC_TARGET_RISCV64
# define TCC_IS_NATIVE
# endif
#endif
@ -242,6 +245,8 @@
# else
# define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2"
# endif
# elif defined(TCC_TARGET_RISCV64)
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-riscv64-lp64d.so.1"
# elif !defined(TCC_ARM_EABI)
# if defined(TCC_MUSL)
# define CONFIG_TCC_ELFINTERP "/lib/ld-musl-arm.so.1"
@ -320,6 +325,11 @@
# include "c67-gen.c"
# include "c67-link.c"
#endif
#ifdef TCC_TARGET_RISCV64
# include "riscv64-gen.c"
# include "riscv64-link.c"
# include "riscv64-asm.c"
#endif
#undef TARGET_DEFS_ONLY
/* -------------------------------------------- */
@ -390,12 +400,21 @@ typedef union CValue {
long double ld;
double d;
float f;
#if HAVE_LONG_LONG_STUB || HAVE_LONG_LONG
uint64_t i;
#else
uint32_t i;
uint32_t i_padding;
#endif
struct {
int size;
const void *data;
} str;
#if BOOTSTRAP && __arm__
int tab[4];
#else
int tab[LDOUBLE_SIZE/4];
#endif
} CValue;
/* value on stack */
@ -407,9 +426,11 @@ typedef struct SValue {
CValue c; /* constant, if VT_CONST */
struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST), or if
result of unary() for an identifier. */
unsigned short cmp_r; // TODO
} SValue;
struct Attribute {
#if HAVE_BITFIELD
unsigned
func_call : 3, /* calling convention (0..5), see below */
aligned : 5, /* alignment as log2+1 (0 == unspecified) */
@ -423,6 +444,22 @@ struct Attribute {
visibility : 2,
unsigned_enum : 1,
fill : 7; // 7 bits left to fit well in union below
#else // !HAVE_BITFIELD
struct {
unsigned func_call;
unsigned aligned;
unsigned packed;
unsigned func_export;
unsigned func_import;
unsigned func_args;
unsigned func_body;
unsigned mode;
unsigned weak;
unsigned visibility;
unsigned unsigned_enum;
unsigned fill;
};
#endif // !HAVE_BITFIELD
};
/* GNUC attribute definition */
@ -589,7 +626,12 @@ typedef struct CachedInclude {
#ifdef CONFIG_TCC_ASM
typedef struct ExprValue {
#if HAVE_LONG_LONG_STUB || HAVE_LONG_LONG
uint64_t v;
#else
uint32_t v;
uint32_t v_padding;
#endif
Sym *sym;
int pcrel;
} ExprValue;
@ -772,6 +814,11 @@ struct TCCState {
/* tiny assembler state */
Sym *asm_labels;
#ifdef TCC_TARGET_RISCV64
struct pcrel_hi { addr_t addr, val; } last_hi;
#define last_hi s1->last_hi
#endif
#ifdef TCC_TARGET_PE
/* PE info */
int pe_subsystem;
@ -1499,6 +1546,7 @@ static inline void write32le(unsigned char *p, uint32_t x) {
static inline void add32le(unsigned char *p, int32_t x) {
write32le(p, read32le(p) + x);
}
#if HAVE_LONG_LONG
static inline uint64_t read64le(unsigned char *p) {
return read32le(p) | (uint64_t)read32le(p + 4) << 32;
}
@ -1508,7 +1556,7 @@ static inline void write64le(unsigned char *p, uint64_t x) {
static inline void add64le(unsigned char *p, int64_t x) {
write64le(p, read64le(p) + x);
}
#endif
/* ------------ i386-gen.c ------------ */
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
ST_FUNC void g(int c);
@ -1548,6 +1596,16 @@ ST_FUNC void gen_va_arg(CType *t);
ST_FUNC void gen_clear_cache(void);
#endif
/* ------------ riscv64-gen.c ------------ */
#ifdef TCC_TARGET_RISCV64
ST_FUNC void gen_opl(int op);
//ST_FUNC void gfunc_return(CType *func_type);
ST_FUNC void gen_va_start(void);
ST_FUNC void arch_transfer_ret_regs(int);
ST_FUNC void gen_cvt_sxtw(void);
ST_FUNC void gen_increment_tcov (SValue *sv);
#endif
/* ------------ c67-gen.c ------------ */
#ifdef TCC_TARGET_C67
#endif

View File

@ -18,7 +18,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#ifdef CONFIG_TCC_ASM
ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
@ -87,7 +90,11 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
{
Sym *sym;
int op, label;
#if HAVE_LONG_LONG
uint64_t n;
#else
uint32_t n;
#endif
const char *p;
switch(tok) {
@ -321,6 +328,7 @@ static inline void asm_expr_cmp(TCCState *s1, ExprValue *pe)
case TOK_NE:
pe->v = pe->v != e2.v;
break;
#if HAVE_LONG_LONG
case TOK_LT:
pe->v = (int64_t)pe->v < (int64_t)e2.v;
break;
@ -333,11 +341,29 @@ static inline void asm_expr_cmp(TCCState *s1, ExprValue *pe)
case TOK_GT:
pe->v = (int64_t)pe->v > (int64_t)e2.v;
break;
#else
case TOK_LT:
pe->v = (int32_t)pe->v < (int32_t)e2.v;
break;
case TOK_GE:
pe->v = (int32_t)pe->v >= (int32_t)e2.v;
break;
case TOK_LE:
pe->v = (int32_t)pe->v <= (int32_t)e2.v;
break;
case TOK_GT:
pe->v = (int32_t)pe->v > (int32_t)e2.v;
break;
#endif
default:
break;
}
#if HAVE_LONG_LONG
/* GAS compare results are -1/0 not 1/0. */
pe->v = -(int64_t)pe->v;
#else
pe->v = -(int32_t)pe->v;
#endif
}
}
@ -519,7 +545,11 @@ static void asm_parse_directive(TCCState *s1, int global)
#else
next();
for(;;) {
#if HAVE_LONG_LONG
uint64_t vl;
#else
uint32_t vl;
#endif
const char *p;
p = tokc.str.data;
@ -534,7 +564,9 @@ static void asm_parse_directive(TCCState *s1, int global)
if (sec->sh_type != SHT_NOBITS) {
/* XXX: endianness */
gen_le32(vl);
#if HAVE_LONG_LONG
gen_le32(vl >> 32);
#endif
} else {
ind += 8;
}

View File

@ -19,7 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
#define MAX_STR_TABLE 1000000

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/* Define this to get some debug output during relocation processing. */
#undef DEBUG_RELOC
@ -311,7 +313,12 @@ static void rebuild_hash(Section *s, unsigned int nb_buckets)
sym = (ElfW(Sym) *)s->data + 1;
for(sym_index = 1; sym_index < nb_syms; sym_index++) {
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
#if !BOOTSTRAP
h = elf_hash(strtab + sym->st_name) % nb_buckets;
#else
h = elf_hash(strtab + sym->st_name);
h = h % nb_buckets;
#endif
*ptr = hash[h];
hash[h] = sym_index;
} else {
@ -353,7 +360,12 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
if (ELFW(ST_BIND)(info) != STB_LOCAL) {
/* add another hashing entry */
nbuckets = base[0];
#if !BOOTSTRAP
h = elf_hash((unsigned char *) name) % nbuckets;
#else
h = elf_hash((unsigned char *) name);
h = h % nbuckets;
#endif
*ptr = base[2 + h];
base[2 + h] = sym_index;
base[1]++;
@ -383,7 +395,12 @@ ST_FUNC int find_elf_sym(Section *s, const char *name)
if (!hs)
return 0;
nbuckets = ((int *)hs->data)[0];
#if !BOOTSTRAP
h = elf_hash((unsigned char *) name) % nbuckets;
#else
h = elf_hash((unsigned char *) name);
h = h % nbuckets;
#endif
sym_index = ((int *)hs->data)[2 + h];
while (sym_index != 0) {
sym = &((ElfW(Sym) *)s->data)[sym_index];
@ -411,6 +428,14 @@ ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
return sym->st_value;
}
#if __MESC_MES__ || !__MESC__
#if !defined (__intptr_t_defined) && !defined (__MES_INTPTR_T)
typedef unsigned long uintptr_t;
#endif
#else // guile
#undef uintptr_t
#endif
/* return elf symbol value */
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
{
@ -425,6 +450,16 @@ ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
}
#endif
ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs)
{
int shn = sec ? sec->sh_num : offs || !name ? SHN_ABS : SHN_UNDEF;
if (sec && offs == -1)
offs = sec->data_offset;
return set_elf_sym(symtab_section, offs, 0,
ELFW(ST_INFO)(name ? STB_GLOBAL : STB_LOCAL, STT_NOTYPE), 0, shn, name);
}
/* add an elf symbol : check if it is already defined and patch
it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
@ -566,9 +601,13 @@ ST_FUNC void squeeze_multi_relocs(Section *s, size_t oldrelocoffset)
a simple insertion sort. */
for (a = oldrelocoffset + sizeof(*r); a < sr->data_offset; a += sizeof(*r)) {
ssize_t i = a - sizeof(*r);
addr = ((ElfW_Rel*)(sr->data + a))->r_offset;
///addr = ((ElfW_Rel*)(sr->data + a))->r_offset;
ElfW_Rel* ea = (ElfW_Rel*)(sr->data + a);
ElfW_Rel* ei = (ElfW_Rel*)(sr->data + i);
addr = ea->r_offset;
for (; i >= (ssize_t)oldrelocoffset &&
((ElfW_Rel*)(sr->data + i))->r_offset > addr; i -= sizeof(*r)) {
ei->r_offset > addr; i -= sizeof(*r)) {
ei = (ElfW_Rel*)(sr->data + i);
ElfW_Rel tmp = *(ElfW_Rel*)(sr->data + a);
*(ElfW_Rel*)(sr->data + a) = *(ElfW_Rel*)(sr->data + i);
*(ElfW_Rel*)(sr->data + i) = tmp;
@ -817,20 +856,36 @@ static void relocate_rel(TCCState *s1, Section *sr)
their space */
static int prepare_dynamic_rel(TCCState *s1, Section *sr)
{
int count = 0;
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) || \
defined(TCC_TARGET_ARM) || defined(TCC_TARGET_ARM64) || \
defined(TCC_TARGET_RISCV64)
ElfW_Rel *rel;
int sym_index, type, count;
count = 0;
for_each_elem(sr, 0, rel, ElfW_Rel) {
sym_index = ELFW(R_SYM)(rel->r_info);
type = ELFW(R_TYPE)(rel->r_info);
int sym_index = ELFW(R_SYM)(rel->r_info);
int type = ELFW(R_TYPE)(rel->r_info);
switch(type) {
#if defined(TCC_TARGET_I386)
case R_386_32:
if (!get_sym_attr(s1, sym_index, 0)->dyn_index
&& ((ElfW(Sym)*)symtab_section->data + sym_index)->st_shndx == SHN_UNDEF) {
/* don't fixup unresolved (weak) symbols */
rel->r_info = ELFW(R_INFO)(sym_index, R_386_RELATIVE);
break;
}
#elif defined(TCC_TARGET_X86_64)
case R_X86_64_32:
case R_X86_64_32S:
case R_X86_64_64:
#elif defined(TCC_TARGET_ARM)
case R_ARM_ABS32:
case R_ARM_TARGET1:
#elif defined(TCC_TARGET_ARM64)
case R_AARCH64_ABS32:
case R_AARCH64_ABS64:
#elif defined(TCC_TARGET_RISCV64)
case R_RISCV_32:
case R_RISCV_64:
#endif
count++;
break;
@ -851,6 +906,7 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
sr->sh_flags |= SHF_ALLOC;
sr->sh_size = count * sizeof(ElfW_Rel);
}
#endif
return count;
}
@ -1147,6 +1203,9 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
}
#endif
tcc_add_support(s1, TCC_LIBTCC1);
#if CONFIG_TCC_LIBTCC1_MES
tcc_add_support(s1, TCC_LIBTCC1_MES);
#endif
/* add crt end if not memory output */
if (s1->output_type != TCC_OUTPUT_MEMORY)
tcc_add_crt(s1, "crtn.o");
@ -1174,6 +1233,10 @@ ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
bss_section->data_offset, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
bss_section->sh_num, "_end");
#ifdef TCC_TARGET_RISCV64
/* XXX should be .sdata+0x800, not .data+0x800 */
set_global_sym(s1, "__global_pointer$", data_section, 0x800);
#endif
#ifndef TCC_TARGET_PE
/* horrible new standard ldscript defines */
add_init_array_defines(s1, ".preinit_array");
@ -1835,7 +1898,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
#endif
#ifdef TCC_TARGET_ARM
#ifdef TCC_ARM_EABI
#if defined (TCC_ARM_EABI) || BOOTSTRAP
ehdr.e_ident[EI_OSABI] = 0;
ehdr.e_flags = EF_ARM_EABI_VER4;
if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
@ -1847,6 +1910,8 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
#else
ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
#endif
#elif defined TCC_TARGET_RISCV64
ehdr.e_flags = EF_RISCV_FLOAT_ABI_DOUBLE;
#endif
switch(file_type) {
default:
@ -2167,7 +2232,9 @@ static int elf_output_file(TCCState *s1, const char *filename)
ret = final_sections_reloc(s1);
if (ret)
goto the_end;
#if !BOOTSTRAP
tidy_section_headers(s1, sec_order);
#endif
}
/* Perform relocation to GOT or PLT entries */
@ -2482,6 +2549,9 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
if (!sym_index && !sm->link_once
#ifdef TCC_TARGET_ARM
&& type != R_ARM_V4BX
#elif defined TCC_TARGET_RISCV64
&& type != R_RISCV_ALIGN
&& type != R_RISCV_RELAX
#endif
) {
invalid_reloc:

184
tccgen.c
View File

@ -18,7 +18,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#if BOOTSTRAP && __arm__
void
tccgen_ok ()
{
}
#endif
/********************************************************/
/* global variables */
@ -62,7 +71,11 @@ ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
ST_DATA struct switch_t {
struct case_t {
#if HAVE_LONG_LONG_STUB || HAVE_LONG_LONG
int64_t v1, v2;
#else
int32_t v1, v1_padding, v2, v2_padding;
#endif
int sym;
} **p; int n; /* list of case ranges */
int def_sym; /* default symbol */
@ -86,8 +99,12 @@ static void vla_runtime_type_size(CType *type, int *a);
static void vla_sp_restore(void);
static void vla_sp_restore_root(void);
static int is_compatible_parameter_types(CType *type1, CType *type2);
#if HAVE_LONG_LONG
static inline int64_t expr_const64(void);
ST_FUNC void vpush64(int ty, unsigned long long v);
#else
static inline int32_t expr_const32(void);
#endif
ST_FUNC void vpush(CType *type);
ST_FUNC int gvtst(int inv, int t);
ST_FUNC int is_btype_size(int bt);
@ -270,13 +287,16 @@ static void update_storage(Sym *sym)
t = sym->type.t;
esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
#if !__MESC__ // Nyacc 0.80.40 cpp-bug
if (t & VT_VIS_MASK)
esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
| ((t & VT_VIS_MASK) >> VT_VIS_SHIFT);
if (t & VT_WEAK)
esym->st_info = ELFW(ST_INFO)(STB_WEAK, ELFW(ST_TYPE)(esym->st_info));
#else //__MESC__
// #warning work around Nyacc 0.80.42 bug.
#endif // __MESC__
#ifdef TCC_TARGET_PE
if (t & VT_EXPORT)
esym->st_other |= ST_PE_EXPORT;
@ -1297,7 +1317,9 @@ static void lexpand(void)
v = vtop->r & (VT_VALMASK | VT_LVAL);
if (v == VT_CONST) {
vdup();
#if HAVE_LONG_LONG_STUB || HAVE_LONG_LONG
vtop[0].c.i >>= 32;
#endif
} else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
vdup();
vtop[0].c.i += 4;
@ -1324,7 +1346,9 @@ ST_FUNC void lexpand_nr(void)
v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
if (v == VT_CONST) {
vtop[-1].c.i = vtop->c.i;
#if HAVE_LONG_LONG_STUB || HAVE_LONG_LONG
vtop->c.i = vtop->c.i >> 32;
#endif
vtop->r = VT_CONST;
} else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
vtop->c.i += 4;
@ -1649,16 +1673,38 @@ static void gen_opl(int op)
}
#endif
#if HAVE_LONG_LONG_STUB || HAVE_LONG_LONG
static uint64_t gen_opic_sdiv(uint64_t a, uint64_t b)
{
#if HAVE_LONG_LONG
uint64_t x = (a >> 63 ? -a : a) / (b >> 63 ? -b : b);
return (a ^ b) >> 63 ? -x : x;
#else
uint32_t x = (a >> 31 ? -a : a) / (b >> 31 ? -b : b);
return (a ^ b) >> 31 ? -x : x;
#endif
}
static int gen_opic_lt(uint64_t a, uint64_t b)
{
#if HAVE_LONG_LONG
return (a ^ (uint64_t)1 << 63) < (b ^ (uint64_t)1 << 63);
#else
return (a ^ (uint32_t)1 << 31) < (b ^ (uint32_t)1 << 31);
#endif
}
#else
static uint32_t gen_opic_sdiv(uint32_t a, uint32_t b)
{
uint32_t x = (a >> 31 ? -a : a) / (b >> 31 ? -b : b);
return (a ^ b) >> 31 ? -x : x;
}
static int gen_opic_lt(uint32_t a, uint32_t b)
{
return (a ^ (uint32_t)1 << 31) < (b ^ (uint32_t)1 << 31);
}
#endif
/* handle integer constant optimizations and various machine
independent opt */
@ -1670,10 +1716,15 @@ static void gen_opic(int op)
int t2 = v2->type.t & VT_BTYPE;
int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
int c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
#if HAVE_LONG_LONG
uint64_t l1 = c1 ? v1->c.i : 0;
uint64_t l2 = c2 ? v2->c.i : 0;
int shm = (t1 == VT_LLONG) ? 63 : 31;
#else
uint32_t l1 = c1 ? v1->c.i : 0;
uint32_t l2 = c2 ? v2->c.i : 0;
int shm = 31;
#endif
if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR))
l1 = ((uint32_t)l1 |
(v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000)));
@ -1711,7 +1762,11 @@ static void gen_opic(int op)
case TOK_SHL: l1 <<= (l2 & shm); break;
case TOK_SHR: l1 >>= (l2 & shm); break;
case TOK_SAR:
#if HAVE_LONG_LONG
l1 = (l1 >> 63) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm);
#else
l1 = (l1 >> 31) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm);
#endif
break;
/* tests */
case TOK_ULT: l1 = l1 < l2; break;
@ -1845,11 +1900,13 @@ static void gen_opif(int op)
case '-': f1 -= f2; break;
case '*': f1 *= f2; break;
case '/':
#if HAVE_FLOAT
if (f2 == 0.0) {
if (const_wanted)
tcc_error("division by zero in constant");
goto general_case;
}
#endif
f1 /= f2;
break;
/* XXX: also handles tests ? */
@ -2267,6 +2324,7 @@ static void gen_cast(CType *type)
if (c) {
/* constant case: we can do it now */
/* XXX: in ISOC, cannot do it if error in convert */
#if HAVE_FLOAT
if (sbt == VT_FLOAT)
vtop->c.ld = vtop->c.f;
else if (sbt == VT_DOUBLE)
@ -2289,14 +2347,20 @@ static void gen_cast(CType *type)
vtop->c.f = (float)vtop->c.ld;
else if (dbt == VT_DOUBLE)
vtop->c.d = (double)vtop->c.ld;
} else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
}
else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
vtop->c.i = vtop->c.ld;
} else if (sf && dbt == VT_BOOL) {
vtop->c.i = (vtop->c.ld != 0);
} else {
} else
#endif
{
#if HAVE_FLOAT
if(sf)
vtop->c.i = vtop->c.ld;
else if (sbt == (VT_LLONG|VT_UNSIGNED))
else
#endif
if (sbt == (VT_LLONG|VT_UNSIGNED))
;
else if (sbt & VT_UNSIGNED)
vtop->c.i = (uint32_t)vtop->c.i;
@ -2388,7 +2452,7 @@ static void gen_cast(CType *type)
/* need to convert from 32bit to 64bit */
gv(RC_INT);
if (sbt != (VT_INT | VT_UNSIGNED)) {
#if defined(TCC_TARGET_ARM64)
#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_RISCV64)
gen_cvt_sxtw();
#elif defined(TCC_TARGET_X86_64)
int r = gv(RC_INT);
@ -2906,7 +2970,11 @@ ST_FUNC void vstore(void)
else
#endif
/* Use memmove, rather than memcpy, as dest and src may be same: */
#if BOOTSTRAP && __arm__
vpush_global_sym(&func_old_type, TOK___memmove);
#else
vpush_global_sym(&func_old_type, TOK_memmove);
#endif
vswap();
/* source */
@ -3760,7 +3828,7 @@ static int parse_btype(CType *type, AttributeDef *ad)
goto basic_type1;
}
break;
#ifdef TCC_TARGET_ARM64
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
case TOK_UINT128:
/* GCC's __uint128_t appears in some Linux header files. Make it a
synonym for long double to get the size and alignment right. */
@ -4524,10 +4592,18 @@ ST_FUNC void unary(void)
break;
case TOK_builtin_choose_expr:
{
#if HAVE_LONG_LONG_STUB || HAVE_LONG_LONG
int64_t c;
#else
int32_t c;
#endif
next();
skip('(');
#if HAVE_LONG_LONG
c = expr_const64();
#else
c = expr_const32();
#endif
skip(',');
if (!c) {
nocode_wanted++;
@ -4655,12 +4731,14 @@ ST_FUNC void unary(void)
/* In IEEE negate(x) isn't subtract(0,x), but rather
subtract(-0, x). */
vpush(&vtop->type);
#if HAVE_FLOAT
if (t == VT_FLOAT)
vtop->c.f = -1.0 * 0.0;
else if (t == VT_DOUBLE)
vtop->c.d = -1.0 * 0.0;
else
vtop->c.ld = -1.0 * 0.0;
#endif
} else
vpushi(0);
vswap();
@ -4691,15 +4769,31 @@ ST_FUNC void unary(void)
// special qnan , snan and infinity values
case TOK___NAN__:
#if HAVE_LONG_LONG
vpush64(VT_DOUBLE, 0x7ff8000000000000ULL);
#else
vpush64(VT_DOUBLE, 0x7ff80000);
vtop->c.i = vtop->c.i << 32;
#endif
next();
break;
case TOK___SNAN__:
#if HAVE_LONG_LONG
vpush64(VT_DOUBLE, 0x7ff0000000000001ULL);
#else
vpush64(VT_DOUBLE, 0x7ff00000);
vtop->c.i = vtop->c.i << 32;
vtop->c.i = vtop->c.i | 1;
#endif
next();
break;
case TOK___INF__:
#if HAVE_LONG_LONG
vpush64(VT_DOUBLE, 0x7ff0000000000000ULL);
#else
vpush64(VT_DOUBLE, 0x7ff00000);
vtop->c.i = vtop->c.i << 32;
#endif
next();
break;
@ -5332,6 +5426,7 @@ static void expr_const1(void)
const_wanted--;
}
#if HAVE_LONG_LONG
/* parse an integer constant and return its value. */
static inline int64_t expr_const64(void)
{
@ -5343,13 +5438,30 @@ static inline int64_t expr_const64(void)
vpop();
return c;
}
#else
/* parse an integer constant and return its value. */
static inline int32_t expr_const32(void)
{
int32_t c;
expr_const1();
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
expect("constant expression");
c = vtop->c.i;
vpop();
return c;
}
#endif
/* parse an integer constant and return its value.
Complain if it doesn't fit 32bit (signed or unsigned). */
ST_FUNC int expr_const(void)
{
int c;
#if HAVE_LONG_LONG
int64_t wc = expr_const64();
#else
int32_t wc = expr_const32();
#endif
c = wc;
if (c != wc && (unsigned)c != wc)
tcc_error("constant exceeds 32 bit");
@ -5444,8 +5556,13 @@ static void gfunc_return(CType *func_type)
static int case_cmp(const void *pa, const void *pb)
{
#if HAVE_LONG_LONG
int64_t a = (*(struct case_t**) pa)->v1;
int64_t b = (*(struct case_t**) pb)->v1;
#else
int32_t a = (*(struct case_t**) pa)->v1;
int32_t b = (*(struct case_t**) pb)->v1;
#endif
return a < b ? -1 : a > b;
}
@ -5770,10 +5887,18 @@ static void block(int *bsym, int *csym, int is_expr)
expect("switch");
nocode_wanted &= ~0x20000000;
next();
#if HAVE_LONG_LONG
cr->v1 = cr->v2 = expr_const64();
#else
cr->v1 = cr->v2 = expr_const32();
#endif
if (gnu_ext && tok == TOK_DOTS) {
next();
#if HAVE_LONG_LONG
cr->v2 = expr_const64();
#else
cr->v2 = expr_const32();
#endif
if (cr->v2 < cr->v1)
tcc_warning("empty case range");
}
@ -5938,7 +6063,11 @@ static void init_putz(Section *sec, unsigned long c, int size)
if (sec) {
/* nothing to do because globals are already set to zero */
} else {
#if BOOTSTRAP && __arm__
vpush_global_sym(&func_old_type, TOK___memset);
#else
vpush_global_sym(&func_old_type, TOK_memset);
#endif
vseti(VT_LOCAL, c);
#ifdef TCC_TARGET_ARM
vpushs(size);
@ -6068,6 +6197,15 @@ static int decl_designator(CType *type, Section *sec, unsigned long c,
return al;
}
#if BOOTSTRAP && HAVE_FLOAT
struct long_double
{
int one;
int two;
int three;
};
#endif
/* store a value or an expression directly in global data or in local array */
static void init_putv(CType *type, Section *sec, unsigned long c)
{
@ -6177,20 +6315,49 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
*(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
break;
case VT_FLOAT:
#if HAVE_FLOAT
#if !(BOOTSTRAP && __arm__)
*(float*)ptr = vtop->c.f;
#else
{
long *lptr = ptr;
*lptr = vtop->c.f;
}
#endif
#endif
break;
case VT_DOUBLE:
#if HAVE_FLOAT
#if !(BOOTSTRAP && __arm__)
*(double *)ptr = vtop->c.d;
#else
{
long long *llptr = ptr;
*llptr = vtop->c.d;
}
#endif
#endif
break;
case VT_LDOUBLE:
#if HAVE_FLOAT
if (sizeof(long double) == LDOUBLE_SIZE)
#if !(BOOTSTRAP && __arm__)
*(long double *)ptr = vtop->c.ld;
#else
{
// XXX TODO: breaks on mescc/mes-tcc based build
// maybe disable with HAVE_LONG_DOUBLE?
//struct long_double *ldptr = ptr;
//struct long_double tmp = (struct long_double)vtop->c.ld;
//*ldptr = (struct long_double)tmp;
}
#endif
else if (sizeof(double) == LDOUBLE_SIZE)
*(double *)ptr = (double)vtop->c.ld;
#if (defined __i386__ || defined __x86_64__) && (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64)
else if (sizeof (long double) >= 10)
memcpy(memset(ptr, 0, LDOUBLE_SIZE), &vtop->c.ld, 10);
#ifdef __TINYC__
#if defined (__TINYC__)
else if (sizeof (long double) == sizeof (double))
__asm__("fldl %1\nfstpt %0\n" : "=m"
(memset(ptr, 0, LDOUBLE_SIZE), ptr) : "m" (vtop->c.ld));
@ -6198,6 +6365,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
#endif
else
tcc_error("can't cross compile long double constants");
#endif
break;
#if PTR_SIZE != 8
case VT_LLONG:

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define PE_MERGE_DATA
/* #define PE_PRINT_SECTIONS */

22
tccpp.c
View File

@ -18,7 +18,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#if BOOTSTRAP && __arm__
void
tccpp_ok ()
{
}
#endif
/********************************************************/
/* global variables */
@ -2282,7 +2291,9 @@ static void parse_number(const char *p)
/* now we can generate the number */
/* XXX: should patch directly float number */
#if HAVE_FLOAT
d = (double)bn[1] * 4294967296.0 + (double)bn[0];
#endif
d = ldexp(d, exp_val - frac_bits);
t = toup(ch);
if (t == 'F') {
@ -2353,11 +2364,15 @@ static void parse_number(const char *p)
tokc.d = strtod(token_buf, NULL);
#else
tok = TOK_CLDOUBLE;
#if HAVE_FLOAT
tokc.ld = strtold(token_buf, NULL);
#endif
#endif
} else {
tok = TOK_CDOUBLE;
#if HAVE_FLOAT
tokc.d = strtod(token_buf, NULL);
#endif
}
}
} else {
@ -2388,10 +2403,12 @@ static void parse_number(const char *p)
tcc_error("invalid digit");
n1 = n;
n = n * b + t;
#if HAVE_LONG_LONG
/* detect overflow */
/* XXX: this test is not reliable */
if (n < n1)
tcc_error("integer constant overflow");
#endif
}
/* Determine the characteristics (unsigned and/or 64bit) the type of
@ -2421,11 +2438,14 @@ static void parse_number(const char *p)
}
}
#if HAVE_LONG_LONG
/* Whether 64 bits are needed to hold the constant's value */
if (n & 0xffffffff00000000LL || must_64bit) {
tok = TOK_CLLONG;
n1 = n >> 32;
} else {
} else
#endif
{
tok = TOK_CINT;
n1 = n;
}

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/* only native compiler supports -run */
#ifdef TCC_IS_NATIVE
@ -271,7 +273,9 @@ static void set_pages_executable(void *ptr, unsigned long length)
if (mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC))
tcc_error("mprotect failed: did you mean to configure --with-selinux?");
# if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64
#if !BOOTSTRAP
__clear_cache(ptr, (char *)ptr + length);
#endif
# endif
#endif
}
@ -694,6 +698,23 @@ static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
}
}
#elif defined(__riscv)
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
{
// TODO make sure api matches
if (level == 0) {
*paddr = uc->uc_mcontext.pc;
} else {
addr_t *fp = (addr_t*)uc->uc_mcontext.__gregs[REG_S0]; // REG_S0 == 8
while (--level && fp >= (addr_t*)0x1000)
fp = (addr_t *)fp[-2];
if (fp < (addr_t*)0x1000)
return -1;
*paddr = fp[-1];
}
return 0;
}
/* ------------------------------------------------------------- */
#else

View File

@ -59,7 +59,7 @@
DEF(TOK_ASM2, "__asm")
DEF(TOK_ASM3, "__asm__")
#ifdef TCC_TARGET_ARM64
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
DEF(TOK_UINT128, "__uint128_t")
#endif
@ -144,6 +144,11 @@
DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types")
#endif
#endif
#ifdef TCC_TARGET_RISCV64
DEF(TOK_builtin_va_start, "__builtin_va_start")
#endif
DEF(TOK_REGPARM1, "regparm")
DEF(TOK_REGPARM2, "__regparm__")
@ -167,6 +172,11 @@
/* builtin functions or variables */
#ifndef TCC_ARM_EABI
#if BOOTSTRAP && __arm__
DEF(TOK___memcpy, "__memcpy")
DEF(TOK___memmove, "__memmove")
DEF(TOK___memset, "__memset")
#endif
DEF(TOK_memcpy, "memcpy")
DEF(TOK_memmove, "memmove")
DEF(TOK_memset, "memset")
@ -252,7 +262,7 @@
#if defined TCC_TARGET_PE
DEF(TOK___chkstk, "__chkstk")
#endif
#ifdef TCC_TARGET_ARM64
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
DEF(TOK___arm64_clear_cache, "__arm64_clear_cache")
DEF(TOK___addtf3, "__addtf3")
DEF(TOK___subtf3, "__subtf3")
@ -346,3 +356,7 @@
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
#include "i386-tok.h"
#endif
#if defined TCC_TARGET_RISCV64
#include "riscv64-tok.h"
#endif

View File

@ -28,7 +28,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
//#define ARMAG "!<arch>\n"
#define ARFMAG "`\n"

143
test.sh Executable file
View File

@ -0,0 +1,143 @@
#! /bin/sh
set -e
export V
if test "$V" = 1 -o "$V" = 2; then
set -x
fi
arch=$(uname -m)
case $arch in
aarch*)
cpu=arm
tcc_cpu=arm
triplet=arm-linux-gnueabihf
cross_prefix=${triplet}-
;;
arm*|aarch*)
cpu=arm
tcc_cpu=arm
triplet=arm-unknown-linux-gnueabihf
cross_prefix=${triplet}-
;;
*)
cpu=x86
tcc_cpu=i386
triplet=i686-unknown-linux-gnu
cross_prefix=${triplet}-
;;
esac
export cpu
export cross_prefix
export tcc_cpu
export triplet
GCC_TCC=${GCC_TCC-./${cross_prefix}tcc}
TCC=${TCC-./tcc}
MES_PREFIX=${MES_PREFIX-mes}
OBJDUMP=${OBJDUMP-objdump}
DIFF=${DIFF-diff}
unset C_INCLUDE_PATH LIBRARY_PATH
if test "$tcc_cpu" = i386; then
libtcc1=-ltcc1
elif test "$tcc_cpu" = arm; then
libtcc1='-lc -ltcc1 -ltcc1-mes'
libtcc1=
elif test "$tcc_cpu" = x86_64; then
libtcc1=-ltcc1
else
echo "cpu not supported: $mes_cpu"
fi
timeout=${timeout-timeout 5}
if ! $timeout echo; then
timeout=
fi
t=${1-lib/tests/scaffold/t.c}
b=$(dirname "$t")/$(basename "$t" .c)
co="$b"-$triplet-tcc
mo="$b"-mes-tcc
o="$co"
rm -f 1 1.s 1.link
rm -f 2 2.s 2.link
rm -f "$co" "$co".1
rm -f "$mo" "$mo".1
r=0
if [ -x $GCC_TCC ]; then
$GCC_TCC \
-c \
-g \
-nostdlib \
-I $MES_PREFIX/include \
-I $MES_PREFIX/scaffold/tinycc \
-o "$o".o \
"$t" \
2> 1
$GCC_TCC \
-g \
-L . \
-o "$o" \
"$o".o \
-lc \
$libtcc1 \
2> 1.link
set +e
d=$(dirname "$t")
d=$(dirname "$d")
if [ "$d" = lib/tests ]; then
$timeout "$o" -s --long file0 file1 > "$o".1
else
$timeout "$o" arg1 arg2 arg3 arg4 arg5 > "$o".1
fi
m=$?
set -e
[ -f "$b".exit ] && r=$(cat "$b".exit)
[ $m = $r ]
if [ -f "$b".expect ]; then
$DIFF -ub "$b".expect "$o".1;
fi
fi
o="$b"-mes-tcc
$TCC \
-c \
-g \
-nostdlib \
-I $MES_PREFIX/include \
-I $MES_PREFIX/scaffold/tinycc \
-o "$o".o \
"$t" \
2> 2
$TCC \
-g \
-L . \
-o "$o" \
"$o".o \
-lc \
$libtcc1 \
2> 2.link
set +e
d=$(dirname "$t")
d=$(dirname "$d")
if [ "$d" = lib/tests ]; then
$timeout "$o" -s --long file0 file1 > "$o".1
else
$timeout "$o" arg1 arg2 arg3 arg4 arg5 > "$o".1
fi
m=$?
set -e
[ $m = $r ]
[ -f "$b".exit ] && r=$(cat "$b".exit)
if [ -f "$b".expect ]; then
$DIFF -ub "$b".expect "$co".1;
$DIFF -ub "$co".1 "$mo".1;
fi

View File

@ -237,6 +237,7 @@ cross-test :
$(TOP)/x86_64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
$(TOP)/arm-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
$(TOP)/c67-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
$(TOP)/riscv64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
$(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
$(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
$(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/win32/examples/hello_win.c && echo "ok"

View File

@ -3698,8 +3698,10 @@ void builtin_frame_address_test(void)
char *fp0 = __builtin_frame_address(0);
printf("str: %s\n", str);
#ifndef __riscv // gcc dumps core. tcc, clang work
bfa1(str-fp0);
#endif
#endif
}
char via_volatile (char i)

View File

@ -1,568 +0,0 @@
/*
* The information in this document is subject to change
* without notice and should not be construed as a commitment
* by Digital Equipment Corporation or by DECUS.
*
* Neither Digital Equipment Corporation, DECUS, nor the authors
* assume any responsibility for the use or reliability of this
* document or the described software.
*
* Copyright (C) 1980, DECUS
*
* General permission to copy or modify, but not for profit, is
* hereby granted, provided that the above copyright notice is
* included and reference made to the fact that reproduction
* privileges were granted by DECUS.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> // tolower()
/*
* grep
*
* Runs on the Decus compiler or on vms, On vms, define as:
* grep :== "$disk:[account]grep" (native)
* grep :== "$disk:[account]grep grep" (Decus)
* See below for more information.
*/
char *documentation[] = {
"grep searches a file for a given pattern. Execute by",
" grep [flags] regular_expression file_list\n",
"Flags are single characters preceded by '-':",
" -c Only a count of matching lines is printed",
" -f Print file name for matching lines switch, see below",
" -n Each line is preceded by its line number",
" -v Only print non-matching lines\n",
"The file_list is a list of files (wildcards are acceptable on RSX modes).",
"\nThe file name is normally printed if there is a file given.",
"The -f flag reverses this action (print name no file, not if more).\n",
0 };
char *patdoc[] = {
"The regular_expression defines the pattern to search for. Upper- and",
"lower-case are always ignored. Blank lines never match. The expression",
"should be quoted to prevent file-name translation.",
"x An ordinary character (not mentioned below) matches that character.",
"'\\' The backslash quotes any character. \"\\$\" matches a dollar-sign.",
"'^' A circumflex at the beginning of an expression matches the",
" beginning of a line.",
"'$' A dollar-sign at the end of an expression matches the end of a line.",
"'.' A period matches any character except \"new-line\".",
"':a' A colon matches a class of characters described by the following",
"':d' character. \":a\" matches any alphabetic, \":d\" matches digits,",
"':n' \":n\" matches alphanumerics, \": \" matches spaces, tabs, and",
"': ' other control characters, such as new-line.",
"'*' An expression followed by an asterisk matches zero or more",
" occurrences of that expression: \"fo*\" matches \"f\", \"fo\"",
" \"foo\", etc.",
"'+' An expression followed by a plus sign matches one or more",
" occurrences of that expression: \"fo+\" matches \"fo\", etc.",
"'-' An expression followed by a minus sign optionally matches",
" the expression.",
"'[]' A string enclosed in square brackets matches any character in",
" that string, but no others. If the first character in the",
" string is a circumflex, the expression matches any character",
" except \"new-line\" and the characters in the string. For",
" example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\"",
" matches \"abc\" but not \"axb\". A range of characters may be",
" specified by two characters separated by \"-\". Note that,",
" [a-z] matches alphabetics, while [z-a] never matches.",
"The concatenation of regular expressions is a regular expression.",
0};
#define LMAX 512
#define PMAX 256
#define CHAR 1
#define BOL 2
#define EOL 3
#define ANY 4
#define CLASS 5
#define NCLASS 6
#define STAR 7
#define PLUS 8
#define MINUS 9
#define ALPHA 10
#define DIGIT 11
#define NALPHA 12
#define PUNCT 13
#define RANGE 14
#define ENDPAT 15
int cflag=0, fflag=0, nflag=0, vflag=0, nfile=0, debug=0;
char *pp, lbuf[LMAX], pbuf[PMAX];
char *cclass();
char *pmatch();
void store(int);
void error(char *);
void badpat(char *, char *, char *);
int match(void);
/*** Display a file name *******************************/
void file(char *s)
{
printf("File %s:\n", s);
}
/*** Report unopenable file ****************************/
void cant(char *s)
{
fprintf(stderr, "%s: cannot open\n", s);
}
/*** Give good help ************************************/
void help(char **hp)
{
char **dp;
for (dp = hp; *dp; ++dp)
printf("%s\n", *dp);
}
/*** Display usage summary *****************************/
void usage(char *s)
{
fprintf(stderr, "?GREP-E-%s\n", s);
fprintf(stderr,
"Usage: grep [-cfnv] pattern [file ...]. grep ? for help\n");
exit(1);
}
/*** Compile the pattern into global pbuf[] ************/
void compile(char *source)
{
char *s; /* Source string pointer */
char *lp; /* Last pattern pointer */
int c; /* Current character */
int o; /* Temp */
char *spp; /* Save beginning of pattern */
s = source;
if (debug)
printf("Pattern = \"%s\"\n", s);
pp = pbuf;
while (c = *s++) {
/*
* STAR, PLUS and MINUS are special.
*/
if (c == '*' || c == '+' || c == '-') {
if (pp == pbuf ||
(o=pp[-1]) == BOL ||
o == EOL ||
o == STAR ||
o == PLUS ||
o == MINUS)
badpat("Illegal occurrence op.", source, s);
store(ENDPAT);
store(ENDPAT);
spp = pp; /* Save pattern end */
while (--pp > lp) /* Move pattern down */
*pp = pp[-1]; /* one byte */
*pp = (c == '*') ? STAR :
(c == '-') ? MINUS : PLUS;
pp = spp; /* Restore pattern end */
continue;
}
/*
* All the rest.
*/
lp = pp; /* Remember start */
switch(c) {
case '^':
store(BOL);
break;
case '$':
store(EOL);
break;
case '.':
store(ANY);
break;
case '[':
s = cclass(source, s);
break;
case ':':
if (*s) {
switch(tolower(c = *s++)) {
case 'a':
case 'A':
store(ALPHA);
break;
case 'd':
case 'D':
store(DIGIT);
break;
case 'n':
case 'N':
store(NALPHA);
break;
case ' ':
store(PUNCT);
break;
default:
badpat("Unknown : type", source, s);
}
break;
}
else badpat("No : type", source, s);
case '\\':
if (*s)
c = *s++;
default:
store(CHAR);
store(tolower(c));
}
}
store(ENDPAT);
store(0); /* Terminate string */
if (debug) {
for (lp = pbuf; lp < pp;) {
if ((c = (*lp++ & 0377)) < ' ')
printf("\\%o ", c);
else printf("%c ", c);
}
printf("\n");
}
}
/*** Compile a class (within []) ***********************/
char *cclass(char *source, char *src)
/* char *source; // Pattern start -- for error msg. */
/* char *src; // Class start */
{
char *s; /* Source pointer */
char *cp; /* Pattern start */
int c; /* Current character */
int o; /* Temp */
s = src;
o = CLASS;
if (*s == '^') {
++s;
o = NCLASS;
}
store(o);
cp = pp;
store(0); /* Byte count */
while ((c = *s++) && c!=']') {
if (c == '\\') { /* Store quoted char */
if ((c = *s++) == '\0') /* Gotta get something */
badpat("Class terminates badly", source, s);
else store(tolower(c));
}
else if (c == '-' &&
(pp - cp) > 1 && *s != ']' && *s != '\0') {
c = pp[-1]; /* Range start */
pp[-1] = RANGE; /* Range signal */
store(c); /* Re-store start */
c = *s++; /* Get end char and*/
store(tolower(c)); /* Store it */
}
else {
store(tolower(c)); /* Store normal char */
}
}
if (c != ']')
badpat("Unterminated class", source, s);
if ((c = (pp - cp)) >= 256)
badpat("Class too large", source, s);
if (c == 0)
badpat("Empty class", source, s);
*cp = c;
return(s);
}
/*** Store an entry in the pattern buffer **************/
void store(int op)
{
if (pp >= &pbuf[PMAX])
error("Pattern too complex\n");
*pp++ = op;
}
/*** Report a bad pattern specification ****************/
void badpat(char *message, char *source, char *stop)
/* char *message; // Error message */
/* char *source; // Pattern start */
/* char *stop; // Pattern end */
{
fprintf(stderr, "-GREP-E-%s, pattern is\"%s\"\n", message, source);
fprintf(stderr, "-GREP-E-Stopped at byte %ld, '%c'\n",
stop-source, stop[-1]);
error("?GREP-E-Bad pattern\n");
}
/*** Scan the file for the pattern in pbuf[] ***********/
void grep(FILE *fp, char *fn)
/* FILE *fp; // File to process */
/* char *fn; // File name (for -f option) */
{
int lno, count, m;
lno = 0;
count = 0;
while (fgets(lbuf, LMAX, fp)) {
++lno;
m = match();
if ((m && !vflag) || (!m && vflag)) {
++count;
if (!cflag) {
if (fflag && fn) {
file(fn);
fn = 0;
}
if (nflag)
printf("%d\t", lno);
printf("%s\n", lbuf);
}
}
}
if (cflag) {
if (fflag && fn)
file(fn);
printf("%d\n", count);
}
}
/*** Match line (lbuf) with pattern (pbuf) return 1 if match ***/
int match()
{
char *l; /* Line pointer */
for (l = lbuf; *l; ++l) {
if (pmatch(l, pbuf))
return(1);
}
return(0);
}
/*** Match partial line with pattern *******************/
char *pmatch(char *line, char *pattern)
/* char *line; // (partial) line to match */
/* char *pattern; // (partial) pattern to match */
{
char *l; /* Current line pointer */
char *p; /* Current pattern pointer */
char c; /* Current character */
char *e; /* End for STAR and PLUS match */
int op; /* Pattern operation */
int n; /* Class counter */
char *are; /* Start of STAR match */
l = line;
if (debug > 1)
printf("pmatch(\"%s\")\n", line);
p = pattern;
while ((op = *p++) != ENDPAT) {
if (debug > 1)
printf("byte[%ld] = 0%o, '%c', op = 0%o\n",
l-line, *l, *l, op);
switch(op) {
case CHAR:
if (tolower(*l++) != *p++)
return(0);
break;
case BOL:
if (l != lbuf)
return(0);
break;
case EOL:
if (*l != '\0')
return(0);
break;
case ANY:
if (*l++ == '\0')
return(0);
break;
case DIGIT:
if ((c = *l++) < '0' || (c > '9'))
return(0);
break;
case ALPHA:
c = tolower(*l++);
if (c < 'a' || c > 'z')
return(0);
break;
case NALPHA:
c = tolower(*l++);
if (c >= 'a' && c <= 'z')
break;
else if (c < '0' || c > '9')
return(0);
break;
case PUNCT:
c = *l++;
if (c == 0 || c > ' ')
return(0);
break;
case CLASS:
case NCLASS:
c = tolower(*l++);
n = *p++ & 0377;
do {
if (*p == RANGE) {
p += 3;
n -= 2;
if (c >= p[-2] && c <= p[-1])
break;
}
else if (c == *p++)
break;
} while (--n > 1);
if ((op == CLASS) == (n <= 1))
return(0);
if (op == CLASS)
p += n - 2;
break;
case MINUS:
e = pmatch(l, p); /* Look for a match */
while (*p++ != ENDPAT); /* Skip over pattern */
if (e) /* Got a match? */
l = e; /* Yes, update string */
break; /* Always succeeds */
case PLUS: /* One or more ... */
if ((l = pmatch(l, p)) == 0)
return(0); /* Gotta have a match */
case STAR: /* Zero or more ... */
are = l; /* Remember line start */
while (*l && (e = pmatch(l, p)))
l = e; /* Get longest match */
while (*p++ != ENDPAT); /* Skip over pattern */
while (l >= are) { /* Try to match rest */
if (e = pmatch(l, p))
return(e);
--l; /* Nope, try earlier */
}
return(0); /* Nothing else worked */
default:
printf("Bad op code %d\n", op);
error("Cannot happen -- match\n");
}
}
return(l);
}
/*** Report an error ***********************************/
void error(char *s)
{
fprintf(stderr, "%s", s);
exit(1);
}
/*** Main program - parse arguments & grep *************/
int main(int argc, char **argv)
{
char *p;
int c, i;
int gotpattern;
FILE *f;
if (argc <= 1)
usage("No arguments");
if (argc == 2 && argv[1][0] == '?' && argv[1][1] == 0) {
help(documentation);
help(patdoc);
return 0;
}
nfile = argc-1;
gotpattern = 0;
for (i=1; i < argc; ++i) {
p = argv[i];
if (*p == '-') {
++p;
while (c = *p++) {
switch(tolower(c)) {
case '?':
help(documentation);
break;
case 'C':
case 'c':
++cflag;
break;
case 'D':
case 'd':
++debug;
break;
case 'F':
case 'f':
++fflag;
break;
case 'n':
case 'N':
++nflag;
break;
case 'v':
case 'V':
++vflag;
break;
default:
usage("Unknown flag");
}
}
argv[i] = 0;
--nfile;
} else if (!gotpattern) {
compile(p);
argv[i] = 0;
++gotpattern;
--nfile;
}
}
if (!gotpattern)
usage("No pattern");
if (nfile == 0)
grep(stdin, 0);
else {
fflag = fflag ^ (nfile > 0);
for (i=1; i < argc; ++i) {
if (p = argv[i]) {
if ((f=fopen(p, "r")) == NULL)
cant(p);
else {
grep(f, p);
fclose(f);
}
}
}
}
return 0;
}
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/

View File

@ -1,3 +0,0 @@
File 46_grep.c:
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/

View File

@ -1032,15 +1032,15 @@ static void gadd_sp(int val)
}
}
typedef enum X86_64_Mode {
enum {
x86_64_mode_none,
x86_64_mode_memory,
x86_64_mode_integer,
x86_64_mode_sse,
x86_64_mode_x87
} X86_64_Mode;
};
static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b)
static int classify_x86_64_merge(int a, int b)
{
if (a == b)
return a;
@ -1058,9 +1058,9 @@ static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b)
return x86_64_mode_sse;
}
static X86_64_Mode classify_x86_64_inner(CType *ty)
static int classify_x86_64_inner(CType *ty)
{
X86_64_Mode mode;
int mode;
Sym *f;
switch (ty->t & VT_BTYPE) {
@ -1093,9 +1093,9 @@ static X86_64_Mode classify_x86_64_inner(CType *ty)
return 0;
}
static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count)
static int classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count)
{
X86_64_Mode mode;
int mode;
int size, align, ret_t = 0;
if (ty->t & (VT_BITFIELD|VT_ARRAY)) {
@ -1158,7 +1158,7 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty)
__va_gen_reg, __va_float_reg, __va_stack
};
int size, align, reg_count;
X86_64_Mode mode = classify_x86_64_arg(ty, NULL, &size, &align, &reg_count);
int mode = classify_x86_64_arg(ty, NULL, &size, &align, &reg_count);
switch (mode) {
default: return __va_stack;
case x86_64_mode_integer: return __va_gen_reg;
@ -1194,7 +1194,7 @@ static int arg_prepare_reg(int idx) {
parameters and the function address. */
void gfunc_call(int nb_args)
{
X86_64_Mode mode;
int mode;
CType type;
int size, align, r, args_size, stack_adjust, run_start, run_end, i, reg_count;
int nb_reg_args = 0;
@ -1483,7 +1483,7 @@ static void push_arg_reg(int i) {
/* generate function prolog of type 't' */
void gfunc_prolog(CType *func_type)
{
X86_64_Mode mode;
int mode;
int i, addr, align, size, reg_count;
int param_addr = 0, reg_param_index, sse_param_index;
Sym *sym;