Compare commits

...

95 Commits

Author SHA1 Message Date
Alexander Sosedkin 7b74b2733c Don't skip weak symbols during ar creation
```
$ echo 'int __attribute__((__weak__)) f(void) { return 4; }' > w.c
$ tcc -c w.c -o w.o

$ tcc-old -ar rc w.a w.o; nm -s w.a  # previous behaviour, not indexed
w.o:
0000000000000000 W f

$ ar rc w.a w.o; nm -s w.a           # GNU binutils behaviour, indexed
Archive index:
f in w.o

0000000000000000 W f

$ tcc-new rc w.a w.o; nm -s w.a      # new behaviour, indexed
Archive index:
f in w.o

0000000000000000 W f
```
2023-10-19 23:21:19 +02:00
Ekaitz 743710064f WIP: add riscv support for scripts and bootstrap 2023-10-19 18:00:57 +02:00
Andrius Štikonas 691ee7dd19 fixup for 5054ff8239 2023-10-16 21:10:31 +01:00
Ekaitz c3b3d422b1 riscv64-asm: remove binary literals
Binary literals are not standard C. They are implemented in GCC, but in
the bootstrap we should avoid them.
2023-10-14 01:16:31 +02:00
Ekaitz 72c3d38814 Add support for varargs in RISCV 2023-10-11 01:00:43 +02:00
Ekaitz 5a0ef8d062 Fix if (x < 8) being broken:
During the backporting effort this passed unnoticed. This part of TCC
converts this:

   if x < 8:

To something like:

    if x < 8:
       x <-- 1
    else:
       x <-- 0
    if x set?

This is done for several reasons: the case of a large constant, to stay
compatible with architectures that use flags for comparison and so on.

In RISC-V we had:

    if ( x < 8 )

Converted to:

  28:	 slti	a0,a0,8             // set a0 to 1 if a0 < 8
  2c:	 bltz	a0,34 <main+0x34>   // branch if a0 less than zero
  30:	 j	3c <main+0x3c>      // jump over the `true` case
  34:    ...                        // the `true` case of the if
  ...
  3c

This assembly is wrong, because a0 is never less than zero. This
happened because the applied comparison is the one that was in the `if`
clause *before* the conversion happened: a < 8 => less than.

It wasn't comparing against 8 anymore though because the code that
assigned the operands was working correctly, comparing against 0: which
is the value you have to compare the flags against in order to know if
they are set or not.

The problem in the code was that after making the conversion, the
pending comparison operator was not updated to the case of comparing
against the flag. That happened because the code was re-setting
`vtop->c.i` to op (which already was there) instead of changing it for
the future operation: check if the flag is not equal to zero => TOK_NE
(NE means not-equal).

After this commit this is the result of the compilation:

  28:	slti	a0,a0,8             // set a0 to 1 if a0 < 8
  2c:	bnez	a0,34 <main+0x34>   // branch if not equal to zero
  30:	j	3c <main+0x3c>      // same as before ...
  ...

So now it is correctly checking against the flag.
2023-10-06 01:33:52 +02:00
Andrius Štikonas f636cf3d48 Fix relocation of got table. 2023-10-02 19:48:34 +02:00
Ekaitz 900be40e8b Rename scall and sbreak to e* to conform with the standard 2023-10-02 19:48:34 +02:00
Ekaitz dc52a81586 RISC-V: Cast ints to 32 bit integers when needed
Mes defaults to 64 bit integers, which is perfectly OK according to the
C standard. TCC supposes ints are 32 bits, which is not necessarily true
and in Mes everything falls apart.

Casting intermediate values avoid this kind of issue and make TCC more
stable throughout C implementations. If we don't do this:

0b1001 << 30 >> 30
^^^^^^^^^^^^
this overflows in 32 bit integers but in 64 bit integers it doesn't.

Casting avoids this issue, truncating intermediate values.
2023-10-02 19:48:34 +02:00
Ekaitz 613c511c56 Fix RV64 cross-compiler package to link lib-arm64
Commit a7f3da33 fixed `long double` support but some missing symbol
error appeared, it was because the libtcc1.o was empty, instead of being
lib-arm64.o, which contains the floating point arithmetic needed for
RV64. Read the `lib/Makefile` for more information.
2023-08-16 19:47:19 +02:00
Ekaitz a7f3da3345 Fix `long double` issue:
In RV64 there are no `long double` registers (if we suppose they are 16
Bytes wide), as registers have only 8 bytes. During the backport I
missed some extra code needed in tccgen.c, because it needs special
handling of the 16 Byte case.

Before this, fix, the following program was failing in the assertion at
riscv64-gen.c:449 (`assert(size == 4 || size == 8)`), as it was
expecting only to use `double`s or `float`s:

```
long double f(int a){
    return  a;
}

int main(int argc, char*argv[]){
    return 1;
}
```

PROBLEM: with the changes in this commit, it fails with:

```
tcc: error: undefined symbol '__floatsitf'
```

That symbol is defined in `lib/lib-arm64.c`, which is reused in RV64.
We need to check it because it's probably loaded incorrectly or not
loaded at all.
2023-08-16 17:20:25 +02:00
Andrius Štikonas 29ac0f40a7 Add a workaround for mes not zero-initializing the whole label. 2023-08-13 22:26:50 +02:00
Ekaitz 4cf19b8b3b Add the dynamic linker to the riscv cross-package 2023-08-13 22:26:50 +02:00
Ekaitz c9e425682e WIP: Make a package to build this tcc with mes
- Mes must be located in an adjacent folder:
    ..
    ├── mes
    └── tinycc

  And you must be located in `tinycc` and run:

    SYSTEM=riscv64-linux      # if you want this for RV64
    guix build -f guix/package_with_mes.scm --system=$SYSTEM

- Mes' package has also been altered to use GUILE in order to be faster
  to build.

- TODO: fix the crt locations because when it runs it fails to locate
  them
2023-08-13 22:26:50 +02:00
Ekaitz 53def017f6 Avoid -f error: default dollars-in-identifiers set
-f is broken with mescc compiled tcc. It's a mes bug. We avoid it
setting dollars-in-identifiers as default as it's needed for the
`__global_pointer$` symbol in RISC-V
2023-08-06 00:35:39 +02:00
Ekaitz 6fbd17852a Fix casting issues (missing func_vt in riscvgen.c):
When compiling a file like:

    long cast_charp_to_long (char const *i)
    {
      return (long)i;
    }

    long cast_int_to_long (int i)
    {
      return (long)i;
    }

    long cast_voidp_to_long (void const *i)
    {
      return (long)i;
    }

    void main(int argc, char* argv[]){
        unsigned long a = 19;
        char b = a;
        return;
    }

We had this error message:

    cannot cast from/to void

It happened because the return type of the functions (`func_vt`) was not
set properly by `riscv-gen.c` and it was VT_VOID by default. In the
`mob` branch they moved all this code to `tccgen.c` to avoid repeating
it in every single architecture, but that made me miss it during the
backport of the RISC-V backend.

This commit adds that piece of code but there might be more places where
a similar thing happens.
2023-08-05 23:50:21 +02:00
Ekaitz aa727e57d2 Take large constant generation routines from upstream 2023-08-05 23:50:21 +02:00
Ekaitz 3b114c1fbd Add `jal rd, symbol` 2023-08-05 23:50:21 +02:00
Ekaitz 1e597f3d23 WIP: starting to understand how it works add lla
Adds `lla` with proper relocations and also removes the broken jal
things and OP_LABEL which was a test with no sense.

Things we understood:
- Operands can have expresions (op.e)
- Expressions can have symbols (e.sym)
- From there we can manage to obtain proper relocations for our
  instructions. See lla as an example for this.

Extra:
- The parser is not implemented as gas' but we could actually do it with
  if we had the time for it. All we can do is manage to read `tok` which
  is the current character being read and then decide how do we process
  the rest of the thing.
  Currently we are taking the offsets as a third argument:
  jalr a0, a1, offset
  instead of:
  jalr a0, offset(a1)
  It could be doable to do it the proper gas' way.
2023-08-01 01:31:48 +02:00
Ekaitz c0df75653d Merge remote-tracking branch 'janneke/wip-riscv' into riscv-mes 2023-07-24 00:34:56 +02:00
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
Juliana Sims ac6f6ca36d Make TCC compile on RISC-V 64
This is a quick-and-dirty set of changes to make tcc compile for RISCV64 using a
native, emulated gcc. It's not clear that any of these changes are "correct,"
just that they compile. Notably, the change to rt_get_caller_pc requires
breaking into opaque structs; the actual internals of these structs aren't
available anywhere I could find. Also, it would be nice to use for_each_elem in
riscv64-link.c; this would require relocating that code to an appropriate
header.

* riscv64-asm.c: Properly initialize union inside Operand structs to 0.
(asm_shift_opcode): Separate variable declaration and initialization for C90
compliance.
* riscv64-link.c (relocate_plt): Replace for_each_elem macro with its
definition.
* tccelf.c (put_elf_reloc): Separate variable declaration and initialization for
C90 compliance.
* tccpp.c (parse_number): Initialize uninitialized values.
* tccrun.c (rt_get_caller_pc): Properly access PC in uc_mcontext, return -1 on
level < 0.
2023-07-21 22:08:40 +00:00
Ekaitz 420559f392 Reorganize guix related things -> move to a folder 2023-07-21 11:18:00 +02:00
Ekaitz 74fa23f5a4 Guix package and manifest for RISC-V and i386 for testing 2023-06-30 23:44:09 +02:00
Ekaitz 928c097cab WIP: ASM add missing RISC-V missing instructions 2023-06-30 13:30:09 +02: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
60 changed files with 7251 additions and 628 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 */

264
boot.sh Executable file
View File

@ -0,0 +1,264 @@
#! /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}-
;;
riscv*)
cpu=riscv64
mes_cpu=riscv64
tcc_cpu=riscv64
triplet=riscv64-unknown-linux-gnu
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"
elif test "$mes_cpu" = riscv64; then
BOOT_CPPFLAGS_TCC="$BOOT_CPPFLAGS_TCC -D HAVE_SETJMP=1"
CPP_TARGET_FLAG="-D TCC_TARGET_RISC64=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
if [ $mes_cpu = riscv64 ]; then
./${program_prefix}tcc -c -g $BOOT_CPPFLAGS lib/lib-arm64.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 lib-arm64.o
./${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 lib-arm64.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 lib-arm64.o
cp -f libtcc1-mes.a $prefix/lib/tcc
fi
cp -f libtcc1.a $prefix/lib/tcc
fi
echo "boot.sh: done"

292
bootstrap.sh Executable file
View File

@ -0,0 +1,292 @@
#! /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}
;;
riscv*)
cpu=riscv64
mes_cpu=riscv64
tcc_cpu=riscv64
triplet=riscv64-unknown-linux-gnu
cross_prefix=${triplet}-
;;
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"
elif test "$mes_cpu" = riscv64; then
CPP_TARGET_FLAG=" -D TCC_TARGET_RISCV64=1 -D HAVE_LONG_LONG=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
if [ $mes_cpu = riscv64]; then
$CC -c $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG lib/lib-arm64.c
$CC -c $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG lib/libtcc1.c
$AR cr libtcc1.a libtcc1.o lib-arm64.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
if [ $mes_cpu = riscv64 ]; then
$CC -c -g $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG lib/lib-arm64.c
$CC -c -g $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG -o libtcc1-tcc.o lib/libtcc1.c
$AR rc libtcc1-tcc.a libtcc1-tcc.o lib-arm64.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 lib-arm64.o
$CC -c -g $CPP_TARGET_FLAG $CFLAGS -o libtcc1.o lib/libtcc1.c
$AR cr libtcc1.a libtcc1.o lib-arm64.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

256
build.sh Executable file
View File

@ -0,0 +1,256 @@
#! /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"
elif test "$mes_cpu" = riscv64; then
CPP_TARGET_FLAG="-D TCC_TARGET_RISCV64=1 -D CONFIG_TCC_LIBTCC1_MES=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
if [ $mes_cpu = riscv64 ]; then
$CC -c -g $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG lib/lib-arm64.c
$CC -c -g $CPPFLAGS $CFLAGS $CPP_TARGET_FLAG -o libtcc1-tcc.o lib/libtcc1.c
$AR rc libtcc1-tcc.a libtcc1-tcc.o lib-arm64.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 lib-arm64.o
$CC -c -g $CPP_TARGET_FLAG $CFLAGS -o libtcc1.o lib/libtcc1.c
$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
if [ $mes_cpu = riscv64]; then
$CC -c $CPPFLAGS $CFLAGS $MES_LIB/libtcc1.c
$CC -c $CPPFLAGS $CFLAGS lib/lib-arm64.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

423
check.sh Executable file
View File

@ -0,0 +1,423 @@
#! /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}-
;;
riscv64*)
cpu=riscv64
tcc_cpu=riscv64
triplet=riscv64-unknown-linux
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

141
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.
@ -27,13 +28,17 @@
typedef signed char int8_t;
typedef short int int16_t;
typedef int int32_t;
#if HAVE_LONG_LONG
typedef 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
#endif
/* Standard ELF types. */
@ -47,19 +52,25 @@ typedef int32_t Elf32_Sword;
typedef uint32_t Elf64_Word;
typedef int32_t Elf64_Sword;
#if HAVE_LONG_LONG
/* Types for signed and unsigned 64-bit quantities. */
typedef uint64_t Elf32_Xword;
typedef int64_t Elf32_Sxword;
typedef uint64_t Elf64_Xword;
typedef int64_t Elf64_Sxword;
#endif
/* Type of addresses. */
typedef uint32_t Elf32_Addr;
#if HAVE_LONG_LONG
typedef uint64_t Elf64_Addr;
#endif
/* Type of file offsets. */
typedef uint32_t Elf32_Off;
#if HAVE_LONG_LONG
typedef uint64_t Elf64_Off;
#endif
/* Type for section indices, which are 16-bit quantities. */
typedef uint16_t Elf32_Section;
@ -67,7 +78,9 @@ typedef uint16_t Elf64_Section;
/* Type for version symbol information. */
typedef Elf32_Half Elf32_Versym;
#if HAVE_LONG_LONG
typedef Elf64_Half Elf64_Versym;
#endif
/* The ELF file header. This appears at the start of every ELF file. */
@ -92,6 +105,7 @@ typedef struct
Elf32_Half e_shstrndx; /* Section header string table index */
} Elf32_Ehdr;
#if HAVE_LONG_LONG
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
@ -109,6 +123,7 @@ typedef struct
Elf64_Half e_shnum; /* Section header table entry count */
Elf64_Half e_shstrndx; /* Section header string table index */
} Elf64_Ehdr;
#endif
/* Fields in the e_ident array. The EI_* macros are indices into the
array. The macros under each EI_* macro are the values the byte
@ -232,7 +247,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 +277,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
@ -293,6 +309,7 @@ typedef struct
Elf32_Word sh_entsize; /* Entry size if section holds table */
} Elf32_Shdr;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word sh_name; /* Section name (string tbl index) */
@ -306,6 +323,7 @@ typedef struct
Elf64_Xword sh_addralign; /* Section alignment */
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
#endif
/* Special section indices. */
@ -381,7 +399,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. */
@ -399,6 +417,7 @@ typedef struct
Elf32_Section st_shndx; /* Section index */
} Elf32_Sym;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word st_name; /* Symbol name (string tbl index) */
@ -408,6 +427,7 @@ typedef struct
Elf64_Addr st_value; /* Symbol value */
Elf64_Xword st_size; /* Symbol size */
} Elf64_Sym;
#endif
/* The syminfo section if available contains additional information about
every dynamic symbol. */
@ -418,11 +438,13 @@ typedef struct
Elf32_Half si_flags; /* Per symbol flags */
} Elf32_Syminfo;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Half si_boundto; /* Direct bindings, symbol bound to */
Elf64_Half si_flags; /* Per symbol flags */
} Elf64_Syminfo;
#endif
/* Possible values for si_boundto. */
#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */
@ -510,6 +532,7 @@ typedef struct
Elf32_Word r_info; /* Relocation type and symbol index */
} Elf32_Rel;
#if HAVE_LONG_LONG
/* I have seen two different definitions of the Elf64_Rel and
Elf64_Rela structures, so we'll leave them out until Novell (or
whoever) gets their act together. */
@ -520,6 +543,7 @@ typedef struct
Elf64_Addr r_offset; /* Address */
Elf64_Xword r_info; /* Relocation type and symbol index */
} Elf64_Rel;
#endif
/* Relocation table entry with addend (in section of type SHT_RELA). */
@ -530,12 +554,14 @@ typedef struct
Elf32_Sword r_addend; /* Addend */
} Elf32_Rela;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Addr r_offset; /* Address */
Elf64_Xword r_info; /* Relocation type and symbol index */
Elf64_Sxword r_addend; /* Addend */
} Elf64_Rela;
#endif
/* How to extract and insert information held in the r_info field. */
@ -561,6 +587,7 @@ typedef struct
Elf32_Word p_align; /* Segment alignment */
} Elf32_Phdr;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word p_type; /* Segment type */
@ -572,6 +599,7 @@ typedef struct
Elf64_Xword p_memsz; /* Segment size in memory */
Elf64_Xword p_align; /* Segment alignment */
} Elf64_Phdr;
#endif
/* Special value for e_phnum. This indicates that the real number of
program headers is too large to fit into e_phnum. Instead the real
@ -665,6 +693,7 @@ typedef struct
} d_un;
} Elf32_Dyn;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Sxword d_tag; /* Dynamic entry type */
@ -674,6 +703,7 @@ typedef struct
Elf64_Addr d_ptr; /* Address value */
} d_un;
} Elf64_Dyn;
#endif
/* Legal values for d_tag (dynamic entry type). */
@ -817,7 +847,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. */
@ -843,6 +873,7 @@ typedef struct
entry */
} Elf32_Verdef;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Half vd_version; /* Version revision */
@ -854,7 +885,7 @@ typedef struct
Elf64_Word vd_next; /* Offset in bytes to next verdef
entry */
} Elf64_Verdef;
#endif
/* Legal values for vd_version (version revision). */
#define VER_DEF_NONE 0 /* No version */
@ -880,13 +911,14 @@ typedef struct
entry */
} Elf32_Verdaux;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word vda_name; /* Version or dependency names */
Elf64_Word vda_next; /* Offset in bytes to next verdaux
entry */
} Elf64_Verdaux;
#endif
/* Version dependency section. */
@ -901,6 +933,7 @@ typedef struct
entry */
} Elf32_Verneed;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Half vn_version; /* Version of structure */
@ -911,7 +944,7 @@ typedef struct
Elf64_Word vn_next; /* Offset in bytes to next verneed
entry */
} Elf64_Verneed;
#endif
/* Legal values for vn_version (version revision). */
#define VER_NEED_NONE 0 /* No version */
@ -930,6 +963,7 @@ typedef struct
entry */
} Elf32_Vernaux;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word vna_hash; /* Hash value of dependency name */
@ -939,7 +973,7 @@ typedef struct
Elf64_Word vna_next; /* Offset in bytes to next vernaux
entry */
} Elf64_Vernaux;
#endif
/* Legal values for vna_flags. */
#define VER_FLG_WEAK 0x2 /* Weak version identifier */
@ -966,6 +1000,7 @@ typedef struct
} a_un;
} Elf32_auxv_t;
#if HAVE_LONG_LONG
typedef struct
{
uint64_t a_type; /* Entry type */
@ -977,6 +1012,7 @@ typedef struct
on 64-bit platforms and vice versa. */
} a_un;
} Elf64_auxv_t;
#endif
/* Legal values for a_type (entry type). */
@ -1045,12 +1081,14 @@ typedef struct
Elf32_Word n_type; /* Type of the note. */
} Elf32_Nhdr;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word n_namesz; /* Length of the note's name. */
Elf64_Word n_descsz; /* Length of the note's descriptor. */
Elf64_Word n_type; /* Type of the note. */
} Elf64_Nhdr;
#endif
/* Known names of notes. */
@ -1104,13 +1142,18 @@ typedef struct
/* Move records. */
typedef struct
{
#if HAVE_LONG_LONG
Elf32_Xword m_value; /* Symbol value. */
#else
Elf32_Word m_info; /* Size and index. */
Elf32_Word m_info_padding;
#endif
Elf32_Word m_poffset; /* Symbol offset. */
Elf32_Half m_repeat; /* Repeat count. */
Elf32_Half m_stride; /* Stride info. */
} Elf32_Move;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Xword m_value; /* Symbol value. */
@ -1119,6 +1162,7 @@ typedef struct
Elf64_Half m_repeat; /* Repeat count. */
Elf64_Half m_stride; /* Stride info. */
} Elf64_Move;
#endif
/* Macro to construct move records. */
#define ELF32_M_SYM(info) ((info) >> 8)
@ -1313,7 +1357,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 */
@ -1732,6 +1776,7 @@ typedef struct
Elf32_Word l_flags; /* Flags */
} Elf32_Lib;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word l_name; /* Name (string table index) */
@ -1740,7 +1785,7 @@ typedef struct
Elf64_Word l_version; /* Interface version */
Elf64_Word l_flags; /* Flags */
} Elf64_Lib;
#endif
/* Legal values for l_flags. */
@ -2494,22 +2539,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 +2960,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 +3288,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 */

6
guix/channels.scm Normal file
View File

@ -0,0 +1,6 @@
(list (channel
(name 'guix)
(url "https://git.savannah.gnu.org/git/guix.git")
(branch "master")
(commit
"a0d2ecde943bd1854ddbb7c0cad35a1fc64dc5ab")))

624
guix/commencement.scm Normal file
View File

@ -0,0 +1,624 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2012-2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2014 Andreas Enge <andreas@enge.fr>
;;; Copyright © 2012 Nikita Karetnikov <nikita@karetnikov.org>
;;; Copyright © 2014, 2015, 2017 Mark H Weaver <mhw@netris.org>
;;; Copyright © 2017, 2018, 2019, 2021, 2022 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2018 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2018, 2019, 2020, 2021, 2022, 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2019-2022 Marius Bakke <marius@gnu.org>
;;; Copyright © 2020, 2022 Timothy Sample <samplet@ngyro.com>
;;; Copyright © 2020 Guy Fleury Iteriteka <gfleury@disroot.org>
;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2021 Chris Marusich <cmmarusich@gmail.com>
;;; Copyright © 2021 Julien Lepiller <julien@lepiller.eu>
;;; Copyright © 2022 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2022 Ekaitz Zarraga <ekaitz@elenq.tech>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (commencement)
#:use-module (gnu packages)
#:use-module (gnu packages bootstrap)
#:use-module (gnu packages autotools)
#:use-module (gnu packages base)
#:use-module (gnu packages bash)
#:use-module (gnu packages c)
#:use-module (gnu packages gcc)
#:use-module (gnu packages m4)
#:use-module (gnu packages gawk)
#:use-module (gnu packages bison)
#:use-module (gnu packages flex)
#:use-module (gnu packages guile)
#:use-module (gnu packages gettext)
#:use-module (gnu packages multiprecision)
#:use-module (gnu packages compression)
#:use-module (gnu packages mes)
#:use-module (gnu packages perl)
#:use-module (gnu packages python)
#:use-module (gnu packages linux)
#:use-module (gnu packages hurd)
#:use-module (gnu packages shells)
#:use-module (gnu packages texinfo)
#:use-module (gnu packages pkg-config)
#:use-module (gnu packages xml)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module ((guix store) #:select (%store-monad))
#:use-module (guix monads)
#:use-module (guix download)
#:use-module (guix git-download)
#:use-module (guix build-system gnu)
#:use-module (guix build-system trivial)
#:use-module ((guix licenses) #:prefix license:)
#:use-module (guix memoization)
#:use-module (guix utils)
#:use-module (srfi srfi-1)
#:use-module (ice-9 popen)
#:use-module (ice-9 rdelim)
#:use-module (ice-9 vlist)
#:use-module (ice-9 match)
#:export (make-gcc-toolchain))
;;; Commentary:
;;;
;;; This is the commencement, this is where things start. Before the
;;; commencement, of course, there's the 'bootstrap' module, which provides us
;;; with the initial binaries. This module uses those bootstrap binaries to
;;; actually build up the whole tool chain that make up the implicit inputs of
;;; 'gnu-build-system'.
;;;
;;; To avoid circular dependencies, this module should not be imported
;;; directly from anywhere.
;;;
;;; Below, we frequently use "inherit" to create modified packages. The
;;; reason why we use "inherit" instead of "package/inherit" is because we do
;;; not want these commencement packages to inherit grafts. By definition,
;;; these packages are not depended on at run time by any of the packages we
;;; use. Thus it does not make sense to inherit grafts. Furthermore, those
;;; grafts would often lead to extra overhead for users who would end up
;;; downloading those "-boot0" packages just to build package replacements
;;; that are in fact not going to be used.
;;;
;;; Code:
(define* (git-fetch-from-tarball tarball)
"Return an <origin> method equivalent to 'git-fetch', except that it fetches
the checkout from TARBALL, a tarball containing said checkout.
The purpose of this procedure is to work around bootstrapping issues:
'git-fetch' depends on Git, which is much higher in the dependency graph."
(lambda* (url hash-algo hash
#:optional name
#:key (system (%current-system))
(guile %bootstrap-guile))
(mlet %store-monad ((guile (package->derivation guile system)))
(gexp->derivation
(or name "git-checkout")
(with-imported-modules '((guix build utils))
#~(begin
(use-modules (guix build utils)
(ice-9 ftw)
(ice-9 match))
(setenv "PATH"
#+(file-append %bootstrap-coreutils&co "/bin"))
(invoke "tar" "xf" #$tarball)
(match (scandir ".")
(("." ".." directory)
(copy-recursively directory #$output)))))
#:recursive? #t
#:hash-algo hash-algo
#:hash hash
#:system system
#:guile-for-build guile
#:graft? #f
#:local-build? #t))))
(define bootar
(package
(name "bootar")
(version "1b")
(source (origin
(method url-fetch)
(uri (list (string-append
"mirror://gnu/guix/mirror/bootar-" version ".ses")
(string-append
"https://files.ngyro.com/bootar/bootar-"
version ".ses")))
(sha256
(base32
"0cf5vj5yxfvkgzvjvh2l7b2nz5ji5l534n9g4mfp8f5jsjqdrqjc"))))
(build-system gnu-build-system)
(arguments
`(#:implicit-inputs? #f
#:tests? #f
#:guile ,%bootstrap-guile
#:imported-modules ((guix build gnu-bootstrap)
,@%gnu-build-system-modules)
#:phases
(begin
(use-modules (guix build gnu-bootstrap))
(modify-phases %standard-phases
(replace 'unpack
(lambda* (#:key inputs #:allow-other-keys)
(let* ((source (assoc-ref inputs "source"))
(guile-dir (assoc-ref inputs "guile"))
(guile (string-append guile-dir "/bin/guile")))
(invoke guile "--no-auto-compile" source)
(chdir "bootar"))))
(replace 'configure (bootstrap-configure "Bootar" ,version
'(".") "scripts"))
(replace 'build (bootstrap-build '(".")))
(replace 'install (bootstrap-install '(".") "scripts"))))))
(inputs `(("guile" ,%bootstrap-guile)))
(home-page "https://git.ngyro.com/bootar")
(synopsis "Tar decompression and extraction in Guile Scheme")
(description "Bootar is a simple Tar extractor written in Guile
Scheme. It supports running 'tar xvf' on uncompressed tarballs or
tarballs that are compressed with BZip2, GZip, or XZ. It also provides
standalone scripts for 'bzip2', 'gzip', and 'xz' that each support
decompression to standard output.
What makes this special is that Bootar is distributed as a
self-extracting Scheme (SES) program. That is, a little script that
outputs the source code of Bootar. This makes it possible to go from
pure Scheme to Tar and decompression in one easy step.")
(license license:gpl3+)))
(define gash-boot
(package
(inherit gash)
(name "gash-boot")
(arguments
`(#:implicit-inputs? #f
#:tests? #f
#:guile ,%bootstrap-guile
#:imported-modules ((guix build gnu-bootstrap)
,@%gnu-build-system-modules)
#:phases
(begin
(use-modules (guix build gnu-bootstrap))
(modify-phases %standard-phases
(replace 'configure
(bootstrap-configure "Gash" ,(package-version gash)
'("gash") "scripts"))
(replace 'build (bootstrap-build '("gash")))
(replace 'install (bootstrap-install '("gash") "scripts"))
(add-after 'install 'install-symlinks
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "out")))
(symlink (string-append out "/bin/gash")
(string-append out "/bin/sh"))
(symlink (string-append out "/bin/gash")
(string-append out "/bin/bash")))))))))
(inputs `(("guile" ,%bootstrap-guile)))
(native-inputs `(("bootar" ,bootar)))))
(define gash-utils-boot
(package
(inherit gash-utils)
(name "gash-utils-boot")
(arguments
`(#:implicit-inputs? #f
#:tests? #f
#:guile ,%bootstrap-guile
#:imported-modules ((guix build gnu-bootstrap)
,@%gnu-build-system-modules)
#:phases
(begin
(use-modules (guix build gnu-bootstrap))
(modify-phases %standard-phases
(add-after 'unpack 'set-load-path
(lambda* (#:key inputs #:allow-other-keys)
(let ((gash (assoc-ref inputs "gash")))
(add-to-load-path (string-append gash "/share/guile/site/"
(effective-version))))))
(add-before 'configure 'pre-configure
(lambda _
(format #t "Creating gash/commands/testb.scm~%")
(copy-file "gash/commands/test.scm"
"gash/commands/testb.scm")
(substitute* "gash/commands/testb.scm"
(("gash commands test") "gash commands testb")
(("apply test [(]cdr") "apply test/bracket (cdr"))
(for-each (lambda (script)
(let ((target (string-append "scripts/"
script ".in")))
(format #t "Creating scripts/~a~%" target)
(copy-file "scripts/template.in" target)
(substitute* target
(("@UTILITY@") script))))
'("awk" "basename" "cat" "chmod" "cmp" "command"
"compress" "cp" "cut" "diff" "dirname" "env"
"expr" "false" "find" "grep" "head" "ln" "ls"
"mkdir" "mv" "printf" "pwd" "reboot" "rm" "rmdir"
"sed" "sleep" "sort" "tar" "test" "touch" "tr"
"true" "uname" "uniq" "wc" "which"))
(format #t "Creating scripts/[.in~%")
(copy-file "scripts/template.in" "scripts/[.in")
(substitute* "scripts/[.in"
(("@UTILITY@") "testb"))
(delete-file "scripts/template.in")))
(replace 'configure
(bootstrap-configure "Gash-Utils" ,(package-version gash-utils)
'("gash" "gash-utils") "scripts"))
(replace 'build (bootstrap-build '("gash" "gash-utils")))
(replace 'install
(bootstrap-install '("gash" "gash-utils") "scripts"))
;; XXX: The scripts should add Gash to their load paths and
;; this phase should not exist.
(add-after 'install 'copy-gash
(lambda* (#:key inputs outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(moddir (string-append out "/share/guile/site/"
(effective-version)))
(godir (string-append out "/lib/guile/"
(effective-version)
"/site-ccache"))
(gash (assoc-ref inputs "gash"))
(gash-moddir (string-append gash "/share/guile/site/"
(effective-version)))
(gash-godir (string-append gash "/lib/guile/"
(effective-version)
"/site-ccache")))
(copy-file (string-append gash-moddir "/gash/compat.scm")
(string-append moddir "/gash/compat.scm"))
(copy-recursively (string-append gash-moddir "/gash/compat")
(string-append moddir "/gash/compat"))
(copy-file (string-append gash-godir "/gash/compat.go")
(string-append godir "/gash/compat.go"))
(copy-recursively (string-append gash-godir "/gash/compat")
(string-append godir "/gash/compat")))))
;; We need an external echo.
(add-after 'install 'make-echo
(lambda* (#:key inputs outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(gash (assoc-ref inputs "gash")))
(with-output-to-file (string-append out "/bin/echo")
(lambda ()
(display (string-append "#!" gash "/bin/gash\n"))
(newline)
(display "echo \"$@\"")
(newline)))
(chmod (string-append out "/bin/echo") #o755))))))))
(inputs `(("gash" ,gash-boot)
("guile" ,%bootstrap-guile)))
(native-inputs `(("bootar" ,bootar)))))
(define (%boot-gash-inputs)
`(("bash" , gash-boot) ; gnu-build-system wants "bash"
("coreutils" , gash-utils-boot)
("bootar" ,bootar)
("guile" ,%bootstrap-guile)))
(define bootstrap-seeds
(package
(name "bootstrap-seeds")
(version "1.0.0")
(source (origin
(method url-fetch)
(uri (list
(string-append "mirror://gnu/guix/mirror/"
"bootstrap-seeds-" version ".tar.gz")
(string-append
"https://lilypond.org/janneke/guix/20220501/"
"bootstrap-seeds-" version ".tar.gz")))
(sha256
(base32
"0scz2bx8fd8c821h6y1j3x6ywgxxns7iinyn9z32dnkiacfdcpfn"))))
(native-inputs (list bootar))
(build-system trivial-build-system)
(arguments
(list #:guile %bootstrap-guile
#:modules '((guix build utils))
#:builder
#~(begin
(use-modules (guix build utils))
(let ((source #$(package-source this-package))
(tar #$(this-package-native-input "bootar"))
(out #$output))
(setenv "PATH" (string-append tar "/bin:"))
(invoke "tar" "xvf" source)
(mkdir-p out)
(copy-recursively "bootstrap-seeds" out)))))
(home-page "https://github.com/oriansj/bootstrap-seeds")
(synopsis "The initial bootstrap seeds: 357-byte hex0 and kaem shell")
(description
"This package provides pre-built binaries of the bootstrap seeds. It
contains a hex0-seed and an optional kaem-minimal shell. The size of the hex0
seeds are for knight: 250 bytes, x86-linux: 357 bytes, x86_64-linux: 431
bytes, and aarch64-linux 526 bytes. These can be used to build stage0: hex0,
hex1, hex2, M1, and M2-Planet.")
(license license:gpl3+)))
(define stage0-posix
;; The initial bootstrap package: no binary inputs except those from
;; `bootstrap-seeds, for x86 a 357 byte binary seed: `x86/hex0-seed'.
(package
(name "stage0-posix")
(version "1.4")
(source (origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/oriansj/stage0-posix/")
(commit "master")
(recursive? #t)))
(sha256
(base32
"0mp0d0q0776571igw62j9hvqy4lq9gb5819wanw0hxi8pyhsk3z6"))))
(supported-systems '("i686-linux" "x86_64-linux"
"aarch64-linux"
"riscv64-linux"))
(native-inputs
`(("bootstrap-seeds" ,bootstrap-seeds)
,@(%boot-gash-inputs)))
(build-system trivial-build-system)
(arguments
(list
#:guile %bootstrap-guile
#:modules '((guix build utils))
#:builder
#~(begin
(use-modules (guix build utils))
(let* ((bootstrap-seeds #$(this-package-native-input
"bootstrap-seeds"))
(source #$(package-source this-package))
(tar #$(this-package-native-input "bootar"))
(bash #$(this-package-native-input "bash"))
(coreutils #$(this-package-native-input "coreutils"))
(guile #$(this-package-input "guile"))
(out #$output)
(bindir (string-append out "/bin"))
(target (or #$(%current-target-system)
#$(%current-system)))
(stage0-cpu
(cond
((or #$(target-x86-64?) #$(target-x86-32?))
"x86")
(#$(target-aarch64?)
"AArch64")
(#$(target-riscv64?)
"riscv64")
(else
(error "stage0-posix: system not supported" target))))
(kaem (string-append "bootstrap-seeds/POSIX/"
stage0-cpu "/kaem-optional-seed")))
(setenv "PATH" (string-append tar "/bin:"
coreutils "/bin:"
bash "/bin"))
(copy-recursively source "stage0-posix")
(chdir "stage0-posix")
(invoke kaem (string-append "kaem." stage0-cpu))
(with-directory-excursion (string-append stage0-cpu "/bin")
(install-file "hex2" bindir)
(install-file "M1" bindir)
(install-file "blood-elf" bindir)
(install-file "kaem" bindir)
(install-file "get_machine" bindir)
(install-file "M2-Planet" bindir))))))
(home-page "https://github.com/oriansj/stage0-posix/")
(synopsis "The initial bootstrap package, builds stage0 up to M2-Planet")
(description "Starting from the 357-byte hex0-seed binary provided by
the bootstrap-seeds, the stage0-posix package first builds hex0 and then all
the way up: hex1, catm, hex2, M0, cc_x86, M1, M2, get_machine (that's all of
MesCC-Tools), and finally M2-Planet.")
(license license:gpl3+)))
(define mes-boot
(package
(inherit mes)
(name "mes-boot")
(version "0.24.2")
(source (origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/ekaitz-zarraga/mes/")
(commit "wip-riscv")))
(file-name (git-file-name name version))
(sha256
(base32
"19wkdwqh1bsd1hz3ip2w5q7nnkkddcbpr4cmwh81d95q8zf60rm1"))))
(inputs '())
(propagated-inputs '())
(supported-systems '("i686-linux" "x86_64-linux" "riscv64-linux"))
(native-inputs
`(("m2-planet" ,stage0-posix)
("nyacc-source" ,(bootstrap-origin
(origin (inherit (package-source nyacc-1.00.2))
(snippet #f))))
,@(%boot-gash-inputs)))
(arguments
(list
#:implicit-inputs? #f
#:tests? #f
#:guile %bootstrap-guile
#:strip-binaries? #f ;no strip yet
#:phases
#~(modify-phases %standard-phases
(add-after 'unpack 'unpack-seeds
(lambda _
(let ((nyacc-source #$(this-package-native-input "nyacc-source")))
(with-directory-excursion ".."
(invoke "tar" "-xvf" nyacc-source)))))
(replace 'configure
(lambda* (#:key inputs outputs #:allow-other-keys)
(let ((out #$output)
(gash #$(this-package-native-input "bash"))
(dir (with-directory-excursion ".." (getcwd))))
(setenv "GUILE_LOAD_PATH" (string-append
dir "/nyacc-1.00.2/module"))
(invoke "gash" "configure.sh"
(string-append "--prefix=" out)
"--host=riscv64-linux-gnu"))))
(replace 'build
(lambda _
(invoke "gash" "bootstrap.sh")))
(delete 'check)
(replace 'install
(lambda* (#:key outputs #:allow-other-keys)
(substitute* "install.sh" ; show some progress
((" -xf") " -xvf")
(("^( *)((cp|mkdir|tar) [^']*[^\\])\n" all space cmd)
(string-append space "echo '" cmd "'\n"
space cmd "\n")))
(invoke "gash" "install.sh")
;; Keep ASCII output, for friendlier comparison and bisection
(let* ((out #$output)
(cache (string-append out "/lib/cache")))
(define (objects-in-dir dir)
(find-files dir
(lambda (name stat)
(and (equal? (dirname name) dir)
(or (string-suffix? ".M1" name)
(string-suffix? ".hex2" name)
(string-suffix? ".o" name)
(string-suffix? ".s" name))))))
(for-each (lambda (x) (install-file x cache))
(append (objects-in-dir "m2")
(objects-in-dir ".")
(objects-in-dir "mescc-lib")))))))))
(native-search-paths
(list (search-path-specification
(variable "C_INCLUDE_PATH")
(files '("include")))
(search-path-specification
(variable "LIBRARY_PATH")
(files '("lib")))
(search-path-specification
(variable "MES_PREFIX")
(separator #f)
(files '("")))))))
(define %source-dir-this (dirname (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-this)) )
(end (+ 4 start)))
(not (false-if-exception (equal? ".git" (substring path start end))))))
(define-public tcc-boot0
;; Pristine tcc cannot be built by MesCC, we are keeping a delta of 30
;; patches. In a very early and rough form they were presented to the
;; TinyCC developers, who at the time showed no interest in supporting the
;; bootstrappable effort; we will try again later. These patches have been
;; ported to 0.9.27, alas the resulting tcc is buggy. Once MesCC is more
;; mature, this package should use the 0.9.27 sources (or later).
;;
;;
;; TODO: Read and adjust configure.sh and boostrap.sh...
(package
(inherit tcc)
(name "tcc-boot0")
(version "0.9.26-1136-g5bba73cc")
(source (origin
(method url-fetch)
(uri (list
(string-append "mirror://gnu/guix/mirror/"
"tcc-" version ".tar.gz")
(string-append "https://lilypond.org/janneke/tcc/"
"tcc-" version ".tar.gz")))
(sha256
(base32
"1y2f04qwdqg7dgxiscbf0ibybx2gclniwbbcsxpayazzii2cvji3"))))
(source (local-file %source-dir-this
#:recursive? #t
#:select? discard-git))
(build-system gnu-build-system)
(supported-systems '("i686-linux" "x86_64-linux" "riscv64-linux"))
(inputs '())
(propagated-inputs '())
(native-inputs
`(("mes" ,mes-boot)
("mescc-tools" ,stage0-posix)
("nyacc-source" ,(bootstrap-origin
(origin (inherit (package-source nyacc-1.00.2))
(snippet #f))))
,@(%boot-gash-inputs)))
(arguments
(list
#:implicit-inputs? #f
#:guile %bootstrap-guile
#:validate-runpath? #f ; no dynamic executables
#:strip-binaries? #f ; no strip yet
#:phases
#~(modify-phases %standard-phases
(add-after 'unpack 'unpack-extra-sources
(lambda* (#:key outputs #:allow-other-keys)
(let ((nyacc-source #$(this-package-native-input "nyacc-source")))
(with-directory-excursion ".."
(invoke "tar" "-xvf" nyacc-source)))))
(replace 'configure
(lambda* (#:key inputs outputs #:allow-other-keys)
(let* ((out #$output)
(dir (with-directory-excursion ".." (getcwd)))
(interpreter "/lib/mes-loader")
(mes #$(this-package-native-input "mes"))
(mescc (string-append mes "/bin/mescc")))
(substitute* "conftest.c"
(("volatile") ""))
(setenv "prefix" out)
(setenv "GUILE_LOAD_PATH"
(string-append dir "/nyacc-1.00.2/module"))
(invoke "sh" "configure"
"--cc=mescc"
(string-append "--prefix=" out)
(string-append "--elfinterp=" interpreter)
"--crtprefix=."
"--tccdir=."))))
(replace 'build
(lambda _
(setenv "V" "2")
(substitute* "bootstrap.sh" ; Show some progress
(("^( *)((cp|ls|mkdir|rm|[.]/tcc|[.]/[$][{program_prefix[}]tcc) [^\"]*[^\\])\n" all space cmd)
(string-append space "echo \"" cmd "\"\n"
space cmd "\n")))
(invoke "sh" "bootstrap.sh")))
(replace 'check
(lambda _
;; fail fast tests
(system* "./tcc" "--help") ; --help exits 1
;; (invoke "sh" "test.sh" "mes/scaffold/tests/30-strlen")
;; (invoke "sh" "-x" "test.sh" "mes/scaffold/tinycc/00_assignment")
;; TODO: add sensible check target (without depending on make)
;; (invoke "sh" "check.sh")
))
(replace 'install
(lambda _
(substitute* "install.sh" ; Show some progress
(("^( *)((cp|ls|mkdir|rm|tar|./[$][{PROGRAM_PREFIX[}]tcc) [^\"]*[^\\])\n" all space cmd)
(string-append space "echo \"" cmd "\"\n"
space cmd "\n")))
(invoke "sh" "install.sh"))))))
(native-search-paths
(list (search-path-specification
(variable "C_INCLUDE_PATH")
(files '("include")))
(search-path-specification
(variable "LIBRARY_PATH")
(files '("lib")))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
tcc-boot0

1
guix/manifest.scm Symbolic link
View File

@ -0,0 +1 @@
manifest_riscv.scm

13
guix/manifest_i386.scm Normal file
View File

@ -0,0 +1,13 @@
(load "package_i386.scm")
(use-modules (gnu packages gdb))
(define triplet "i686-linux-gnu")
(packages->manifest
(let* ((binutils (cross-binutils triplet))
(libc (cross-libc triplet)))
(list tcc-mine-i386
(list gcc "lib")
binutils
libc
gdb
(list libc "static"))))

13
guix/manifest_riscv.scm Normal file
View File

@ -0,0 +1,13 @@
(load "package_riscv.scm")
(use-modules (gnu packages gdb))
(define triplet "riscv64-linux-gnu")
(packages->manifest
(let* ((binutils (cross-binutils triplet))
(libc (cross-libc triplet)))
(list tcc-mine-riscv
(list gcc "lib")
binutils
libc
gdb
(list libc "static"))))

111
guix/package_i386.scm Normal file
View File

@ -0,0 +1,111 @@
(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 (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 libccross-i386 (cross-libc "i686-linux-gnu"))
(define-public tcc-mine-i386
(package
(name "tcc") ;aka. "tinycc"
(version "i386-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 -DASM_DEBUG=1")
#:tests? #f
#:validate-runpath? #f
#:phases #~(modify-phases %standard-phases
(replace 'build
(lambda _
(invoke "make" "cross-i386")))
;; 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-i386 = " #$libccross-i386 "/lib") port)
(newline port)
(display
(string-append "LIB-i386 = " #$libccross-i386 "/lib") port)
(newline port)
(display
(string-append "INC-i386 = " #$libccross-i386 "/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 "./i386-tcc" "-c" "lib/libtcc1.c" "-o" "libtcc1.o")
(invoke "./i386-tcc" "-ar" "cr" "libtcc1-i386.a" "libtcc1.o")
;; Now install
(install-file "libtcc1-i386.a"
(string-append (assoc-ref outputs "out") "/lib/tcc"))
(install-file "i386-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-i386

113
guix/package_riscv.scm Normal file
View File

@ -0,0 +1,113 @@
(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 (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 libccross-i386 (cross-libc "i686-linux-gnu"))
(define-public tcc-mine-riscv
(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"
(string-append "--extra-cflags="
"-DHAVE_FLOAT=1 "
"-DHAVE_BITFIELD=1 "
"-DHAVE_LONG_LONG=1 "
"-DHAVE_SETJMP=1 "
"-DASM_DEBUG=1 "
"-DCONFIG_TCC_ELFINTERP=\\\\\"\\\"" #$libccross "/lib/ld-linux-riscv64-lp64d.so.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)))))
;; Use lib/lib-arm64.c. Needed for long-double support.
;; - Later it'll try to link it (needed)
(add-before 'install 'build-libtcc1
(lambda* (#:key inputs outputs #:allow-other-keys)
(invoke "./riscv64-tcc" "-c" "lib/lib-arm64.c" "-o" "libtcc1.o")
(invoke "./riscv64-tcc" "-ar" "cr" "libtcc1-riscv64.a" "libtcc1.o")))
;; 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)
(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-riscv

160
guix/package_with_mes.scm Normal file
View File

@ -0,0 +1,160 @@
(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 c)
(gnu packages guile)
(gnu packages cross-base)
(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-this (dirname (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-this)) )
(end (+ 4 start)))
(not (false-if-exception (equal? ".git" (substring path start end))))))
;; From mes source
;; NOTE: It expects Mes to be in a folder adjacent to the tcc project folder
(define %source-dir-mes (string-append (dirname (dirname (dirname (current-filename)))) "/mes/guix.scm"))
(chdir (dirname %source-dir-mes))
(load %source-dir-mes)
(chdir %source-dir-this)
(package
(name "tcc-MES")
(version "0.0.1")
(source (local-file %source-dir-this
#:recursive? #t
#:select? discard-git))
(build-system gnu-build-system)
(inputs '())
(propagated-inputs '())
(native-inputs (list mes.git mescc-tools nyacc guile-3.0))
(arguments
(list
#:validate-runpath? #f
#:phases
#~(modify-phases %standard-phases
;(add-before 'configure 'fail (lambda _ (error ":)"))
(add-before 'configure 'conftest
(lambda* (#:key inputs outputs #:allow-other-keys)
(substitute* "conftest.c"
(("volatile") ""))))
;; Uses live-bootstrap as a reference
;; https://git.stikonas.eu/andrius/live-bootstrap/src/branch/mes-x86_64/sysa/tcc-0.9.26/tcc-0.9.26.kaem#L62
;; TODO: ADD THE CRTS properly
(replace 'configure
(lambda _
(let ((target-system (or #$(%current-target-system)
#$(%current-system))))
;; TODO: set other variables
(setenv "MES" "guile") ; This literally reduces build times x20
(setenv "MES_STACK" "15000000")
(setenv "MES_ARENA" "30000000")
(setenv "MES_MAX_ARENA" "30000000")
(setenv "MES_LIB" (string-append #$mes.git "/lib"))
(cond
((string-prefix? "x86_64-linux" target-system)
(begin
(display "Preparing for x86_64-linux...\n")
(setenv "MES_ARCH" "x86_64")
(setenv "TCC_TARGET_ARCH" "X86_64")
(setenv "MES_LIBC_SUFFIX" "gcc")))
((string-prefix? "aarch64-linux" target-system)
(begin
(display "Preparing for aarch64-linux...\n")
(error "Not supported")))
((string-prefix? "riscv64-linux" target-system)
(begin
(display "Preparing for riscv64-linux...\n")
(setenv "MES_ARCH" "riscv64")
(setenv "TCC_TARGET_ARCH" "RISCV64")
(setenv "MES_LIBC_SUFFIX" "tcc")))
(else (error "NO architecture matched\n"))))))
(replace 'build
(lambda _
(define-syntax invoke-and-show
(syntax-rules (invoke-and-show)
((invoke-and-show expr ...)
(begin
(display (string-join (list "INVOKING: " expr ...) " ") (current-error-port))
(force-output (current-error-port))
(invoke expr ...)))))
(invoke-and-show
(string-append #$mes.git "/bin/mescc")
"-S"
"-o" "tcc.s"
(string-append "-I" #$mes.git "/include")
"-DBOOTSTRAP=1"
"-DHAVE_LONG_LONG=1"
"-I."
(string-append "-DTCC_TARGET_" (getenv "TCC_TARGET_ARCH") "=1")
"-Dinline="
(string-append "-DCONFIG_TCC_CRTPREFIX=\"" #$mes.git "/lib\"")
"-DCONFIG_TCC_ELFINTERP=\"/mes/loader\""
(string-append "-DCONFIG_TCC_SYSINCLUDEPATHS=\"" #$mes.git "/include:/include\"")
(string-append "-DTCC_LIBGCC=\"" #$mes.git "/lib/libc.a\"")
"-DCONFIG_TCC_LIBTCC1_MES=0"
"-DCONFIG_TCCBOOT=1"
"-DCONFIG_TCC_STATIC=1"
"-DCONFIG_USE_LIBGCC=1"
"-DTCC_MES_LIBC=1"
"-DTCC_VERSION=\"0.9.26\""
"-DONE_SOURCE=1"
"tcc.c")))
(add-after 'build 'link
(lambda _
(invoke (string-append #$mes.git "/bin/mescc")
"--base-address" "0x08048000"
"-o" "mes-tcc"
(string-append "-L" #$mes.git "/lib")
"tcc.s"
"-lc+tcc")))
;; There's a better way to do this today but...
(replace 'install
(lambda* (#:key inputs outputs #:allow-other-keys)
(chmod "mes-tcc" #o775)
(install-file "mes-tcc"
(string-append (assoc-ref outputs "out") "/bin/"))))
(replace 'check
(lambda _
(system* "./mes-tcc" "--help"))))))
(native-search-paths
(list (search-path-specification
(variable "C_INCLUDE_PATH")
(files '("include")))
(search-path-specification
(variable "LIBRARY_PATH")
(files '("lib")))))
(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/")
(license license:lgpl2.1+))

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

@ -67,6 +67,25 @@ typedef struct {
#define va_end(ap)
#define va_copy(dest, src) ((dest) = (src))
#elif __riscv
typedef __builtin_va_list va_list;
typedef char *__builtin_va_list;
#define __va_reg_size (__riscv_xlen >> 3)
#define va_start __builtin_va_start
#define va_arg __builtin_va_arg
#define va_copy __builtin_va_copy
#define va_end __builtin_va_end
typedef char *__builtin_va_list;
#define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \
& -(__alignof__(type)))
#define __builtin_va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size)))))
#define __builtin_va_end(ap) (void)(ap)
#ifndef __builtin_va_copy
# define __builtin_va_copy(dest, src) (dest) = (src)
#endif
#else /* __i386__ */
typedef char *va_list;
/* only correct for i386 */

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

856
riscv64-asm.c Normal file
View File

@ -0,0 +1,856 @@
/*************************************************************/
/*
* 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_ecall: // I (pseudo)
asm_emit_opcode((0x1C << 2) | 3 | (0 << 12));
return;
case TOK_ASM_ebreak: // I (pseudo)
asm_emit_opcode((0x1C << 2) | 3 | (0 << 12) | (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,
OPT_IM20S,
};
#define OP_REG (1 << OPT_REG)
#define OP_IM32 (1 << OPT_IM32)
#define OP_IM12S (1 << OPT_IM12S)
#define OP_IM20S (1 << OPT_IM20S)
typedef struct Operand {
uint32_t type;
union {
uint8_t reg;
uint16_t regset;
ExprValue e;
};
} Operand;
/* Fixed operands for pseudoinstructions */
const Operand zero_imm = {OP_IM12S, {0}};
const Operand zero = {OP_REG, {0}};
/* 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->e = e;
if (!op->e.sym) {
if ((int) op->e.v >= -2048 && (int) op->e.v < 2048)
op->type = OP_IM12S;
else if ((int) op->e.v >= -1<<19 && (int) op->e.v < 1<<19)
op->type = OP_IM20S;
else
op->type = OP_IM32;
return;
} else {
/*TODO: Deal with offsets and stuff like that for the moment it's ok to
leave it like this as we are only taking the symbol case*/
}
}
#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");
}
}
/* 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));
}
/* 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));
}
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 gen_lla(int token, Operand* op1, Operand* op2) {
// 1. Generate the symbol first
// 2. Generate a R_RISCV_PCREL_HI20 relocation pointing to the auipc for
// the symbol
// 3. Generate an auipc with 0x0
// 4. Generate a R_RISCV_PCREL_LO12_I relocation pointing to the addi for
// the symbol
// 5. Generate an addi with 0x0
// OPTIONAL. Add R_RISCV_RELAX
//
Sym *sym, label = {0};
sym = op2->e.sym;
label.type.t = VT_VOID | VT_STATIC;
put_extern_sym(&label, cur_text_section, ind, 0);
greloca(cur_text_section, sym, ind, R_RISCV_PCREL_HI20, 0);
asm_emit_u(token, (0x05 << 2) | 3, op1, &zero_imm); // auipc rd, 0x0
greloca(cur_text_section, &label, ind, R_RISCV_PCREL_LO12_I, 0);
asm_emit_i(token, (4 << 2) | 3, op1, op1, &zero_imm); // addi rd, rd, 0x0
// NOTE: We need to use an empty label (see `label` above) for this to
// work, if we don't it fails saying the second relocation's value is not
// the same as the addr of the previous one, and it's true.
//
// It returns this if we use sym in both relocations:
// > PCREL_HI20: val=10230 addr=10260
// > PCREL_LO12_I: val=10230 addr=10264
// > tcc: error: unsupported hi/lo pcrel reloc scheme
//
// If we do it as in the code above it works properly.
// I don't know why it should be like this, but it happens to work
}
static void gen_jal(int token, Operand* op1, Operand* op2) {
Sym *sym;
sym = op2->e.sym;
greloca(cur_text_section, sym, ind, R_RISCV_JAL, 0);
gen_le32( 0x6f | ENCODE_RD(op1->reg));
}
static void asm_binary_opcode(TCCState* s1, int token)
{
Operand ops[2];
/* Parsing */
parse_operand(s1, &ops[0]);
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[1]);
switch (token) {
case TOK_ASM_la:
/* TODO: implement la*/
tcc_error("la is not implemented yet");
case TOK_ASM_lla:
if(!ops[1].e.sym){
tcc_error("(%s): expected symbol as second argument", token);
}
gen_lla(token, &ops[0], &ops[1]);
return;
case TOK_ASM_mv:
asm_emit_i(token, (4 << 2) | 3, &ops[0], &ops[1], &zero_imm);
return;
case TOK_ASM_neg:
asm_emit_r(token, (0xC << 2) | 3 | (32 << 25), &ops[0], &zero, &ops[1]);
return;
case TOK_ASM_negw:
asm_emit_r(token, (0xE << 2) | 3 | (0 << 12) | (32 << 25), &ops[0], &zero, &ops[1]);
return;
case TOK_ASM_li:
/* NOTE: only works with small values! */
asm_emit_i(token, (4 << 2) | 3, &ops[0], &zero, &ops[1]);
return;
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");
}
}
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_jump_opcode(TCCState* s1, int token)
{
Operand ops[3];
int offset;
parse_operand(s1, &ops[0]);
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[1]);
if (token != TOK_ASM_jal){
if (tok == ',')
next();
else
expect("','");
parse_operand(s1, &ops[2]);
}
switch (token) {
case TOK_ASM_jalr:
asm_emit_i(token, 0x67, &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_jal:
if(ops[1].e.sym){
// This handles `jal rd, symbol`
gen_jal(token, &ops[0], &ops[1]);
return;
} else if(ops[1].type != OP_IM20S && ops[1].type != OP_IM12S) {
tcc_error("jal jump too large");
} else {
// This is for immediates like `jal rd, -1201`
// TODO: Make sure it works with positive and negative relative
// jumps
/* Weird encoding. It doesn't let us use `asm_emit_u` easily */
offset = 0;
offset = ((ops[1].e.v & 0x100000)>>20) <<19 |
((ops[1].e.v & 0x0FF000)>>12) |
((ops[1].e.v & 0x000800)>>11) <<8 |
((ops[1].e.v & 0x0007FE)>> 1) <<9;
gen_le32( 0x6f | ENCODE_RD(ops[0].reg) | offset<<12);
return;
}
default:
expect("jump operation");
}
}
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_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_li: /* pseudoinstruction */
case TOK_ASM_mv: /* pseudoinstruction */
case TOK_ASM_la: /* pseudoinstruction */
case TOK_ASM_neg: /* pseudoinstruction */
case TOK_ASM_negw: /* pseudoinstruction */
case TOK_ASM_lla: /* pseudoinstruction */
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_jalr:
case TOK_ASM_jal:
asm_jump_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 */

1561
riscv64-gen.c Normal file

File diff suppressed because it is too large Load Diff

361
riscv64-link.c Normal file
View File

@ -0,0 +1,361 @@
#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 (rel = (ElfW_Rel *) s1->plt->reloc->data; \
rel < (ElfW_Rel *) (s1->plt->reloc->data + s1->plt->reloc->data_offset); \
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

204
riscv64-tok.h Normal file
View File

@ -0,0 +1,204 @@
/* ------------------------------------------------------------------ */
/* 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)
/* Pseudo*/
DEF_ASM(li)
DEF_ASM(la)
DEF_ASM(lla)
DEF_ASM(mv)
DEF_ASM(neg)
DEF_ASM(negw)
/* Jumps */
DEF_ASM(jalr)
DEF_ASM(jal)
/* 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(ecall)
DEF_ASM(ebreak)
/* Counters */
DEF_ASM(rdcycle)
DEF_ASM(rdcycleh)
DEF_ASM(rdtime)
DEF_ASM(rdtimeh)
DEF_ASM(rdinstret)
DEF_ASM(rdinstreth)
/* Privileged Instructions */
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,
@ -554,7 +589,7 @@ ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
ST_FUNC void squeeze_multi_relocs(Section *s, size_t oldrelocoffset)
{
Section *sr = s->reloc;
ElfW_Rel *r, *dest;
ElfW_Rel *r, *dest, tmp;
ssize_t a;
ElfW(Addr) addr;
@ -566,10 +601,14 @@ 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)) {
ElfW_Rel tmp = *(ElfW_Rel*)(sr->data + a);
ei->r_offset > addr; i -= sizeof(*r)) {
ei = (ElfW_Rel*)(sr->data + i);
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");
@ -1781,7 +1844,7 @@ static int final_sections_reloc(TCCState *s1)
/* On X86 gdb 7.3 works in any case but gdb 6.6 will crash if SHF_ALLOC
checking is removed */
#else
if (s->reloc && s != s1->got)
if (s->reloc)
/* On X86_64 gdb 7.3 will crash if SHF_ALLOC checking is present */
#endif
relocate_section(s1, s);
@ -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:
@ -2161,13 +2226,14 @@ static int elf_output_file(TCCState *s1, const char *filename)
}
}
/* if building executable or DLL, then relocate each section
except the GOT which is already relocated */
/* if building executable or DLL, then relocate each section */
if (file_type != TCC_OUTPUT_OBJ) {
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 +2548,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:

234
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;
@ -1113,6 +1133,11 @@ ST_FUNC int gv(int rc)
if (vtop->r & VT_MUSTBOUND)
gbound();
#endif
#ifdef TCC_TARGET_RISCV64
/* XXX mega hack */
if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE && rc == RC_FLOAT)
rc = RC_INT;
#endif
r = vtop->r & VT_VALMASK;
rc2 = (rc & RC_FLOAT) ? RC_FLOAT : RC_INT;
@ -1131,7 +1156,10 @@ ST_FUNC int gv(int rc)
if (r >= VT_CONST
|| (vtop->r & VT_LVAL)
|| !(reg_classes[r] & rc)
#if PTR_SIZE == 8
#ifdef TCC_TARGET_RISCV64
|| ((vtop->type.t & VT_BTYPE) == VT_QLONG && (vtop->r2 >= NB_REGS || !(reg_classes[vtop->r2] & rc2)))
|| ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE && (vtop->r2 >= NB_REGS || !(reg_classes[vtop->r2] & rc2)))
#elif PTR_SIZE == 8
|| ((vtop->type.t & VT_BTYPE) == VT_QLONG && !(reg_classes[vtop->r2] & rc2))
|| ((vtop->type.t & VT_BTYPE) == VT_QFLOAT && !(reg_classes[vtop->r2] & rc2))
#else
@ -1140,7 +1168,10 @@ ST_FUNC int gv(int rc)
)
{
r = get_reg(rc);
#if PTR_SIZE == 8
#ifdef TCC_TARGET_RISCV64
if (((vtop->type.t & VT_BTYPE) == VT_QLONG) || ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)) {
int addr_type = VT_LLONG, load_size = 8, load_type = VT_LLONG;
#elif PTR_SIZE == 8
if (((vtop->type.t & VT_BTYPE) == VT_QLONG) || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT)) {
int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
#else
@ -1272,6 +1303,9 @@ static int rc_fret(int t)
if (t == VT_LDOUBLE) {
return RC_ST0;
}
#elif defined TCC_TARGET_RISCV64
if (t == VT_LDOUBLE)
return RC_IRET;
#endif
return RC_FRET;
}
@ -1284,6 +1318,9 @@ static int reg_fret(int t)
if (t == VT_LDOUBLE) {
return TREG_ST0;
}
#elif defined TCC_TARGET_RISCV64
if (t == VT_LDOUBLE)
return REG_IRET;
#endif
return REG_FRET;
}
@ -1297,7 +1334,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 +1363,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;
@ -1385,6 +1426,9 @@ static void gv_dup(void)
if ((t & VT_BTYPE) == VT_LDOUBLE) {
rc = RC_ST0;
}
#elif defined TCC_TARGET_RISCV64
if ((t & VT_BTYPE) == VT_LDOUBLE)
rc = RC_INT;
#endif
sv.type.t = t;
}
@ -1649,16 +1693,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 +1736,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 +1782,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 +1920,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 +2344,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 +2367,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 +2472,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 +2990,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 */
@ -2981,6 +3069,9 @@ ST_FUNC void vstore(void)
} else if ((ft & VT_BTYPE) == VT_QFLOAT) {
rc = RC_FRET;
}
#elif defined TCC_TARGET_RISCV64
if (dbt == VT_LDOUBLE)
rc = RC_INT;
#endif
}
r = gv(rc); /* generate value */
@ -2999,7 +3090,10 @@ ST_FUNC void vstore(void)
vtop[-1].r = t | VT_LVAL;
}
/* two word case handling : store second register at word + 4 (or +8 for x86-64) */
#if PTR_SIZE == 8
#ifdef TCC_TARGET_RISCV64
if (dbt == VT_QLONG || dbt == VT_LDOUBLE) {
int addr_type = VT_LLONG, load_size = 8, load_type = VT_LLONG;
#elif PTR_SIZE == 8
if (((ft & VT_BTYPE) == VT_QLONG) || ((ft & VT_BTYPE) == VT_QFLOAT)) {
int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
#else
@ -3760,7 +3854,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 +4618,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++;
@ -4588,6 +4690,18 @@ ST_FUNC void unary(void)
}
}
break;
#ifdef TCC_TARGET_RISCV64
case TOK_builtin_va_start:
parse_builtin_params(0, "ee");
r = vtop->r & VT_VALMASK;
if (r == VT_LLOCAL)
r = VT_LOCAL;
if (r != VT_LOCAL)
tcc_error("__builtin_va_start expects a local variable");
gen_va_start();
vstore();
break;
#endif
#ifdef TCC_TARGET_X86_64
#ifdef TCC_TARGET_PE
case TOK_builtin_va_start:
@ -4655,12 +4769,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 +4807,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;
@ -5141,6 +5273,9 @@ static void expr_cond(void)
if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
rc = RC_ST0;
}
#elif defined TCC_TARGET_RISCV64
if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)
rc = RC_INT;
#endif
} else
rc = RC_INT;
@ -5252,6 +5387,9 @@ static void expr_cond(void)
if ((type.t & VT_BTYPE) == VT_LDOUBLE) {
rc = RC_ST0;
}
#elif defined TCC_TARGET_RISCV64
if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE)
rc = RC_INT;
#endif
} else if ((type.t & VT_BTYPE) == VT_LLONG) {
/* for long longs, we use fixed registers to avoid having
@ -5332,6 +5470,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 +5482,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 +5600,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 +5931,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 +6107,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 +6241,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 +6359,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 +6409,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 */

28
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 */
@ -2171,6 +2180,10 @@ static void parse_number(const char *p)
unsigned int bn[BN_SIZE];
double d;
/* initialize values */
d = 0;
bn_zero(bn);
/* number */
q = token_buf;
ch = *p++;
@ -2282,7 +2295,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 +2368,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 +2407,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 +2442,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;
}
@ -3485,7 +3509,7 @@ ST_FUNC void preprocess_start(TCCState *s1)
s1->pack_stack[0] = 0;
s1->pack_stack_ptr = s1->pack_stack;
set_idnum('$', s1->dollars_in_identifiers ? IS_ID : 0);
set_idnum('$', IS_ID); // Activate dollars-in-identifiers always
set_idnum('.', (parse_flags & PARSE_FLAG_ASM_FILE) ? IS_ID : 0);
buf = tcc_malloc(3 + strlen(file->filename));

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,25 @@ 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) {
return -1;
} else if (level == 0) {
*paddr = uc->uc_mcontext.__gregs[REG_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"
@ -207,6 +209,9 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
(sym->st_info == 0x10
|| sym->st_info == 0x11
|| sym->st_info == 0x12
|| sym->st_info == 0x20
|| sym->st_info == 0x21
|| sym->st_info == 0x22
)) {
//printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
istrlen = strlen(strtab + sym->st_name)+1;

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;