2009-05-05 18:17:11 +00:00
|
|
|
/*
|
|
|
|
* TCC - Tiny C Compiler
|
2017-09-26 05:16:23 +00:00
|
|
|
*
|
2009-05-05 18:17:11 +00:00
|
|
|
* Copyright (c) 2001-2004 Fabrice Bellard
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
2009-12-20 00:53:49 +00:00
|
|
|
#ifndef _TCC_H
|
|
|
|
#define _TCC_H
|
|
|
|
|
2009-05-05 18:17:26 +00:00
|
|
|
#define _GNU_SOURCE
|
2020-05-22 03:27:30 +00:00
|
|
|
#define _DARWIN_C_SOURCE
|
2009-05-05 18:17:26 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2025-02-08 17:38:14 +00:00
|
|
|
#include <stdarg.h>
|
2025-02-11 19:16:44 +00:00
|
|
|
|
2020-12-19 19:33:36 +00:00
|
|
|
/* gnu headers use to #define __attribute__ to empty for non-gcc compilers */
|
|
|
|
#ifdef __TINYC__
|
|
|
|
# undef __attribute__
|
|
|
|
#endif
|
2025-02-08 14:45:16 +00:00
|
|
|
|
2025-02-11 19:40:33 +00:00
|
|
|
#include <stdint.h>
|
2009-05-05 18:17:26 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <setjmp.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
2025-02-11 19:40:33 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/time.h>
|
2014-04-04 18:18:39 +00:00
|
|
|
/* XXX: need to define this to use them in non ISOC99 context */
|
2017-07-09 10:07:40 +00:00
|
|
|
extern float strtof (const char *__nptr, char **__endptr);
|
|
|
|
extern long double strtold (const char *__nptr, char **__endptr);
|
2009-05-05 18:17:26 +00:00
|
|
|
|
|
|
|
#ifndef O_BINARY
|
2013-02-12 18:13:28 +00:00
|
|
|
# define O_BINARY 0
|
2010-09-10 18:55:54 +00:00
|
|
|
#endif
|
|
|
|
|
2017-07-23 19:24:11 +00:00
|
|
|
#ifndef offsetof
|
|
|
|
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef countof
|
|
|
|
#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
|
|
|
|
#endif
|
|
|
|
|
2011-08-06 14:11:12 +00:00
|
|
|
/* ------------ path configuration ------------ */
|
2009-05-05 18:17:26 +00:00
|
|
|
|
2011-08-11 14:55:30 +00:00
|
|
|
#ifndef CONFIG_SYSROOT
|
|
|
|
# define CONFIG_SYSROOT ""
|
|
|
|
#endif
|
2025-02-11 19:40:33 +00:00
|
|
|
#if !defined CONFIG_TCCDIR
|
2017-07-23 19:24:11 +00:00
|
|
|
# define CONFIG_TCCDIR "/usr/local/lib/tcc"
|
2013-02-14 05:53:07 +00:00
|
|
|
#endif
|
|
|
|
#ifndef CONFIG_LDDIR
|
2016-10-17 21:22:21 +00:00
|
|
|
# define CONFIG_LDDIR "lib"
|
2013-02-14 05:53:07 +00:00
|
|
|
#endif
|
2016-10-17 21:22:21 +00:00
|
|
|
#ifdef CONFIG_TRIPLET
|
|
|
|
# define USE_TRIPLET(s) s "/" CONFIG_TRIPLET
|
|
|
|
# define ALSO_TRIPLET(s) USE_TRIPLET(s) ":" s
|
2014-01-06 18:56:26 +00:00
|
|
|
#else
|
2016-10-17 21:22:21 +00:00
|
|
|
# define USE_TRIPLET(s) s
|
|
|
|
# define ALSO_TRIPLET(s) s
|
2013-09-07 17:26:36 +00:00
|
|
|
#endif
|
2011-08-11 14:55:30 +00:00
|
|
|
|
2011-08-03 20:26:39 +00:00
|
|
|
/* path to find crt1.o, crti.o and crtn.o */
|
2011-08-06 14:11:12 +00:00
|
|
|
#ifndef CONFIG_TCC_CRTPREFIX
|
2022-09-24 07:19:59 +00:00
|
|
|
# define CONFIG_TCC_CRTPREFIX USE_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR)
|
2011-08-03 20:26:39 +00:00
|
|
|
#endif
|
|
|
|
|
2020-05-22 03:27:30 +00:00
|
|
|
#ifndef CONFIG_USR_INCLUDE
|
|
|
|
# define CONFIG_USR_INCLUDE "/usr/include"
|
|
|
|
#endif
|
|
|
|
|
2011-08-11 14:55:30 +00:00
|
|
|
/* Below: {B} is substituted by CONFIG_TCCDIR (rsp. -B option) */
|
|
|
|
|
2011-08-06 14:11:12 +00:00
|
|
|
/* system include paths */
|
various stuff
win32/Makefile ("for cygwin") removed
- On cygwin, the normal ./configure && make can be used with either
cygwin's "GCC for Win32 Toolchain"
./configure --cross-prefix=i686-w64-mingw32-
or with an existing tcc:
./configure --cc=<old-tccdir>/tcc.exe
tcctest.c:
- exclude test_high_clobbers() on _WIN64 (does not work)
tests2/95_bitfield.c:
- use 'signed char' for ARM (where default 'char' is unsigned)
tests:
- remove -I "expr" diff option to allow tests with
busybox-diff.
libtcc.c, tcc.c:
- removed -iwithprefix option. It is supposed to be
combined with -iprefix which we don't have either.
tccgen.c:
- fix assignments and return of 'void', as in
void f() {
void *p, *q;
*p = *q:
return *p;
}
This appears to be allowed but should do nothing.
tcc.h, libtcc.c, tccpp.c:
- Revert "Introduce VIP sysinclude paths which are always searched first"
This reverts commit 1d5e386b0a78393ac6b670c209a185849ec798a1.
The patch was giving tcc's system includes priority over -I which
is not how it should be.
tccelf.c:
- add DT_TEXTREL tag only if text relocations are actually
used (which is likely not the case on x86_64)
- prepare_dynamic_rel(): avoid relocation of unresolved
(weak) symbols
tccrun.c:
- for HAVE_SELINUX, use two mappings to the same (real) file.
(it was so once except the RX mapping wasn't used at all).
tccpe.c:
- fix relocation constant used for x86_64 (by Andrei E. Warentin)
- #ifndef _WIN32 do "chmod 755 ..." to get runnable exes on cygwin.
tccasm.c:
- keep forward asm labels static, otherwise they will endup
in dynsym eventually.
configure, Makefile:
- mingw32: respect ./configure options --bindir --docdir --libdir
- allow overriding tcc when building libtcc1.a and libtcc.def with
make XTCC=<tcc program to use>
- use $(wildcard ...) for install to allow installing just
a cross compiler for example
make cross-arm
make install
- use name <target>-libtcc1.a
build-tcc.bat:
- add options: -clean, -b bindir
2017-10-11 16:13:43 +00:00
|
|
|
#ifndef CONFIG_TCC_SYSINCLUDEPATHS
|
2025-02-08 14:45:16 +00:00
|
|
|
|
|
|
|
# define CONFIG_TCC_SYSINCLUDEPATHS \
|
various stuff
win32/Makefile ("for cygwin") removed
- On cygwin, the normal ./configure && make can be used with either
cygwin's "GCC for Win32 Toolchain"
./configure --cross-prefix=i686-w64-mingw32-
or with an existing tcc:
./configure --cc=<old-tccdir>/tcc.exe
tcctest.c:
- exclude test_high_clobbers() on _WIN64 (does not work)
tests2/95_bitfield.c:
- use 'signed char' for ARM (where default 'char' is unsigned)
tests:
- remove -I "expr" diff option to allow tests with
busybox-diff.
libtcc.c, tcc.c:
- removed -iwithprefix option. It is supposed to be
combined with -iprefix which we don't have either.
tccgen.c:
- fix assignments and return of 'void', as in
void f() {
void *p, *q;
*p = *q:
return *p;
}
This appears to be allowed but should do nothing.
tcc.h, libtcc.c, tccpp.c:
- Revert "Introduce VIP sysinclude paths which are always searched first"
This reverts commit 1d5e386b0a78393ac6b670c209a185849ec798a1.
The patch was giving tcc's system includes priority over -I which
is not how it should be.
tccelf.c:
- add DT_TEXTREL tag only if text relocations are actually
used (which is likely not the case on x86_64)
- prepare_dynamic_rel(): avoid relocation of unresolved
(weak) symbols
tccrun.c:
- for HAVE_SELINUX, use two mappings to the same (real) file.
(it was so once except the RX mapping wasn't used at all).
tccpe.c:
- fix relocation constant used for x86_64 (by Andrei E. Warentin)
- #ifndef _WIN32 do "chmod 755 ..." to get runnable exes on cygwin.
tccasm.c:
- keep forward asm labels static, otherwise they will endup
in dynsym eventually.
configure, Makefile:
- mingw32: respect ./configure options --bindir --docdir --libdir
- allow overriding tcc when building libtcc1.a and libtcc.def with
make XTCC=<tcc program to use>
- use $(wildcard ...) for install to allow installing just
a cross compiler for example
make cross-arm
make install
- use name <target>-libtcc1.a
build-tcc.bat:
- add options: -clean, -b bindir
2017-10-11 16:13:43 +00:00
|
|
|
"{B}/include" \
|
|
|
|
":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/include") \
|
2020-05-22 03:27:30 +00:00
|
|
|
":" ALSO_TRIPLET(CONFIG_SYSROOT CONFIG_USR_INCLUDE)
|
2011-08-03 20:26:39 +00:00
|
|
|
#endif
|
|
|
|
|
2011-08-06 14:11:12 +00:00
|
|
|
/* library search paths */
|
|
|
|
#ifndef CONFIG_TCC_LIBPATHS
|
2025-02-08 14:45:16 +00:00
|
|
|
# define CONFIG_TCC_LIBPATHS \
|
2022-07-23 15:19:56 +00:00
|
|
|
"{B}" \
|
|
|
|
":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \
|
2016-10-17 21:22:21 +00:00
|
|
|
":" ALSO_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) \
|
|
|
|
":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR)
|
2014-01-07 07:23:54 +00:00
|
|
|
#endif
|
|
|
|
|
2017-02-23 07:41:57 +00:00
|
|
|
/* (target specific) libtcc1.a */
|
|
|
|
#ifndef TCC_LIBTCC1
|
|
|
|
# define TCC_LIBTCC1 "libtcc1.a"
|
2016-10-01 19:06:33 +00:00
|
|
|
#endif
|
|
|
|
|
2024-11-21 11:03:32 +00:00
|
|
|
/* <cross-prefix-to->libtcc1.a */
|
|
|
|
#ifndef CONFIG_TCC_CROSSPREFIX
|
|
|
|
# define CONFIG_TCC_CROSSPREFIX ""
|
|
|
|
#endif
|
|
|
|
|
2016-10-17 21:24:01 +00:00
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
2025-02-08 14:45:16 +00:00
|
|
|
#include <libtcc.h>
|
2025-02-21 14:10:26 +00:00
|
|
|
/*#include <tcc/elf.h>*/
|
2025-02-11 19:16:44 +00:00
|
|
|
#include <tcc/object/coff.h>
|
2025-02-11 12:07:04 +00:00
|
|
|
#include <tcc/utils/cstring.h>
|
2016-10-17 21:24:01 +00:00
|
|
|
|
2017-02-23 07:41:57 +00:00
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
|
|
|
#ifndef PUB_FUNC /* functions used by tcc.c but not in libtcc.h */
|
|
|
|
# define PUB_FUNC
|
|
|
|
#endif
|
|
|
|
|
2013-02-08 18:07:11 +00:00
|
|
|
/* -------------------------------------------- */
|
|
|
|
/* include the target specific definitions */
|
2025-02-08 14:45:16 +00:00
|
|
|
# include "tcc/i386/gen.h"
|
2013-02-08 18:07:11 +00:00
|
|
|
|
2017-05-13 06:59:06 +00:00
|
|
|
# define ELFCLASSW ELFCLASS32
|
|
|
|
# define ElfW(type) Elf##32##_##type
|
|
|
|
# define ELFW(type) ELF##32##_##type
|
|
|
|
# define ElfW_Rel ElfW(Rel)
|
|
|
|
# define SHT_RELX SHT_REL
|
|
|
|
# define REL_SECTION_FMT ".rel%s"
|
2025-02-06 10:42:10 +00:00
|
|
|
|
2017-05-13 06:59:06 +00:00
|
|
|
/* target address type */
|
2025-02-11 12:07:04 +00:00
|
|
|
typedef uint32_t addr_t;
|
2017-11-27 03:03:03 +00:00
|
|
|
#define ElfSym ElfW(Sym)
|
2017-05-13 06:59:06 +00:00
|
|
|
|
2025-02-08 14:45:16 +00:00
|
|
|
#define LONG_SIZE 4
|
2017-09-24 16:57:48 +00:00
|
|
|
|
2017-05-13 06:59:06 +00:00
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
2009-05-05 18:17:26 +00:00
|
|
|
#define INCLUDE_STACK_SIZE 32
|
|
|
|
#define IFDEF_STACK_SIZE 64
|
2023-03-11 06:40:56 +00:00
|
|
|
#define VSTACK_SIZE 512
|
2009-05-05 18:17:26 +00:00
|
|
|
#define STRING_MAX_SIZE 1024
|
2016-04-17 13:37:23 +00:00
|
|
|
#define TOKSTR_MAX_SIZE 256
|
2009-05-05 18:17:26 +00:00
|
|
|
#define PACK_STACK_SIZE 8
|
|
|
|
|
2016-04-17 13:37:23 +00:00
|
|
|
#define TOK_HASH_SIZE 16384 /* must be a power of two */
|
2009-05-05 18:17:26 +00:00
|
|
|
#define TOK_ALLOC_INCR 512 /* must be a power of two */
|
|
|
|
#define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
|
|
|
|
|
|
|
|
/* token symbol management */
|
|
|
|
typedef struct TokenSym {
|
|
|
|
struct TokenSym *hash_next;
|
|
|
|
struct Sym *sym_define; /* direct pointer to define */
|
|
|
|
struct Sym *sym_label; /* direct pointer to label */
|
|
|
|
struct Sym *sym_struct; /* direct pointer to structure */
|
|
|
|
struct Sym *sym_identifier; /* direct pointer to identifier */
|
|
|
|
int tok; /* token number */
|
|
|
|
int len;
|
|
|
|
char str[1];
|
|
|
|
} TokenSym;
|
|
|
|
|
|
|
|
typedef int nwchar_t;
|
|
|
|
|
|
|
|
/* type definition */
|
|
|
|
typedef struct CType {
|
|
|
|
int t;
|
|
|
|
struct Sym *ref;
|
|
|
|
} CType;
|
|
|
|
|
|
|
|
/* constant value */
|
|
|
|
typedef union CValue {
|
|
|
|
long double ld;
|
|
|
|
double d;
|
|
|
|
float f;
|
2015-11-17 19:09:35 +00:00
|
|
|
uint64_t i;
|
2015-11-21 11:23:53 +00:00
|
|
|
struct {
|
2024-03-22 00:02:30 +00:00
|
|
|
char *data;
|
2020-06-20 19:56:53 +00:00
|
|
|
int size;
|
2015-11-21 11:23:53 +00:00
|
|
|
} str;
|
2013-02-08 18:07:11 +00:00
|
|
|
int tab[LDOUBLE_SIZE/4];
|
2009-05-05 18:17:26 +00:00
|
|
|
} CValue;
|
|
|
|
|
|
|
|
/* value on stack */
|
|
|
|
typedef struct SValue {
|
|
|
|
CType type; /* type */
|
|
|
|
unsigned short r; /* register + flags */
|
|
|
|
unsigned short r2; /* second register, used for 'long long'
|
|
|
|
type. If not used, set to VT_CONST */
|
jump optimizations
This unifies VT_CMP with VT_JMP(i) by using mostly VT_CMP
with both a positive and a negative jump target list.
Such we can delay putting the non-inverted or inverted jump
until we can see which one is nore suitable (in most cases).
example:
if (a && b || c && d)
e = 0;
before this patch:
a: 8b 45 fc mov 0xfffffffc(%ebp),%eax
d: 83 f8 00 cmp $0x0,%eax
10: 0f 84 11 00 00 00 je 27 <main+0x27>
16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
19: 83 f8 00 cmp $0x0,%eax
1c: 0f 84 05 00 00 00 je 27 <main+0x27>
22: e9 22 00 00 00 jmp 49 <main+0x49>
27: 8b 45 f4 mov 0xfffffff4(%ebp),%eax
2a: 83 f8 00 cmp $0x0,%eax
2d: 0f 84 11 00 00 00 je 44 <main+0x44>
33: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
36: 83 f8 00 cmp $0x0,%eax
39: 0f 84 05 00 00 00 je 44 <main+0x44>
3f: e9 05 00 00 00 jmp 49 <main+0x49>
44: e9 08 00 00 00 jmp 51 <main+0x51>
49: b8 00 00 00 00 mov $0x0,%eax
4e: 89 45 ec mov %eax,0xffffffec(%ebp)
51: ...
with this patch:
a: 8b 45 fc mov 0xfffffffc(%ebp),%eax
d: 83 f8 00 cmp $0x0,%eax
10: 0f 84 0c 00 00 00 je 22 <main+0x22>
16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
19: 83 f8 00 cmp $0x0,%eax
1c: 0f 85 18 00 00 00 jne 3a <main+0x3a>
22: 8b 45 f4 mov 0xfffffff4(%ebp),%eax
25: 83 f8 00 cmp $0x0,%eax
28: 0f 84 14 00 00 00 je 42 <main+0x42>
2e: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
31: 83 f8 00 cmp $0x0,%eax
34: 0f 84 08 00 00 00 je 42 <main+0x42>
3a: b8 00 00 00 00 mov $0x0,%eax
3f: 89 45 ec mov %eax,0xffffffec(%ebp)
42: ...
2019-06-22 09:45:35 +00:00
|
|
|
union {
|
|
|
|
struct { int jtrue, jfalse; }; /* forward jmps */
|
|
|
|
CValue c; /* constant, if VT_CONST */
|
|
|
|
};
|
|
|
|
union {
|
|
|
|
struct { unsigned short cmp_op, cmp_r; }; /* VT_CMP operation */
|
|
|
|
struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST), or if */
|
|
|
|
}; /* result of unary() for an identifier. */
|
|
|
|
|
2009-05-05 18:17:26 +00:00
|
|
|
} SValue;
|
|
|
|
|
2017-07-09 10:34:11 +00:00
|
|
|
/* symbol attributes */
|
|
|
|
struct SymAttr {
|
|
|
|
unsigned short
|
|
|
|
aligned : 5, /* alignment as log2+1 (0 == unspecified) */
|
|
|
|
packed : 1,
|
|
|
|
weak : 1,
|
|
|
|
visibility : 2,
|
|
|
|
dllexport : 1,
|
2018-07-21 23:54:01 +00:00
|
|
|
nodecorate : 1,
|
2017-07-09 10:34:11 +00:00
|
|
|
dllimport : 1,
|
2020-01-16 00:19:59 +00:00
|
|
|
addrtaken : 1,
|
2023-03-10 11:41:43 +00:00
|
|
|
nodebug : 1,
|
|
|
|
xxxx : 2; /* not used */
|
2017-07-09 10:34:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* function attributes or temporary attributes for parsing */
|
|
|
|
struct FuncAttr {
|
2014-01-07 13:57:07 +00:00
|
|
|
unsigned
|
2017-07-09 10:34:11 +00:00
|
|
|
func_call : 3, /* calling convention (0..5), see below */
|
|
|
|
func_type : 2, /* FUNC_OLD/NEW/ELLIPSIS */
|
2019-04-29 11:53:07 +00:00
|
|
|
func_noreturn : 1, /* attribute((noreturn)) */
|
2020-01-17 21:58:39 +00:00
|
|
|
func_ctor : 1, /* attribute((constructor)) */
|
|
|
|
func_dtor : 1, /* attribute((destructor)) */
|
2020-05-22 03:17:02 +00:00
|
|
|
func_args : 8, /* PE __stdcall args */
|
|
|
|
func_alwinl : 1, /* always_inline */
|
2020-08-14 13:00:29 +00:00
|
|
|
xxxx : 15;
|
2014-01-07 13:57:07 +00:00
|
|
|
};
|
|
|
|
|
2009-05-05 18:17:26 +00:00
|
|
|
/* symbol management */
|
|
|
|
typedef struct Sym {
|
2017-07-09 10:34:11 +00:00
|
|
|
int v; /* symbol token */
|
|
|
|
unsigned short r; /* associated register or VT_CONST/VT_LOCAL and LVAL type */
|
|
|
|
struct SymAttr a; /* symbol attributes */
|
2014-01-07 13:57:07 +00:00
|
|
|
union {
|
2017-07-09 10:34:11 +00:00
|
|
|
struct {
|
|
|
|
int c; /* associated number or Elf symbol index */
|
|
|
|
union {
|
|
|
|
int sym_scope; /* scope level for locals */
|
2019-12-02 18:20:56 +00:00
|
|
|
int jnext; /* next jump label */
|
2024-11-17 19:56:12 +00:00
|
|
|
int jind; /* label position */
|
2017-07-09 10:34:11 +00:00
|
|
|
struct FuncAttr f; /* function attributes */
|
2017-07-09 10:38:59 +00:00
|
|
|
int auxtype; /* bitfield access type */
|
2017-07-09 10:34:11 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
long long enum_val; /* enum constant if IS_ENUM_VAL */
|
|
|
|
int *d; /* define token stream */
|
2024-11-17 19:56:12 +00:00
|
|
|
struct Sym *cleanup_func;
|
2014-01-07 13:57:07 +00:00
|
|
|
};
|
2024-11-17 19:56:12 +00:00
|
|
|
|
2017-07-09 10:34:11 +00:00
|
|
|
CType type; /* associated type */
|
2009-07-18 20:05:58 +00:00
|
|
|
union {
|
2016-10-06 02:05:30 +00:00
|
|
|
struct Sym *next; /* next related symbol (for fields and anoms) */
|
2024-02-09 15:07:43 +00:00
|
|
|
int *e; /* expanded token stream */
|
2017-07-09 10:34:11 +00:00
|
|
|
int asm_label; /* associated asm label */
|
2024-02-09 15:07:43 +00:00
|
|
|
struct Sym *cleanupstate; /* in defined labels */
|
|
|
|
int *vla_array_str; /* vla array code */
|
2009-07-18 20:05:58 +00:00
|
|
|
};
|
2009-05-05 18:17:26 +00:00
|
|
|
struct Sym *prev; /* prev symbol in stack */
|
|
|
|
struct Sym *prev_tok; /* previous symbol for this token */
|
|
|
|
} Sym;
|
|
|
|
|
2025-02-21 14:10:26 +00:00
|
|
|
#if 0
|
2009-05-05 18:17:26 +00:00
|
|
|
/* section definition */
|
|
|
|
typedef struct Section {
|
|
|
|
unsigned long data_offset; /* current data offset */
|
|
|
|
unsigned char *data; /* section data */
|
|
|
|
unsigned long data_allocated; /* used for realloc() handling */
|
2021-10-22 05:39:54 +00:00
|
|
|
TCCState *s1;
|
2025-02-11 12:07:04 +00:00
|
|
|
|
|
|
|
/**/
|
2025-02-11 19:16:44 +00:00
|
|
|
char name[8];
|
|
|
|
addr_t addr;
|
|
|
|
int32_t flags;
|
|
|
|
int32_t size;
|
2025-02-11 12:07:04 +00:00
|
|
|
|
2025-02-11 19:16:44 +00:00
|
|
|
COFFReloc *coff_reloc;
|
2025-02-11 12:07:04 +00:00
|
|
|
/**/
|
|
|
|
|
2009-05-05 18:17:26 +00:00
|
|
|
int sh_name; /* elf section name (only used during output) */
|
|
|
|
int sh_num; /* elf section number */
|
|
|
|
int sh_type; /* elf section type */
|
|
|
|
int sh_flags; /* elf section flags */
|
|
|
|
int sh_info; /* elf section info */
|
|
|
|
int sh_addralign; /* elf section alignment */
|
|
|
|
int sh_entsize; /* elf entry size */
|
|
|
|
unsigned long sh_size; /* section size (only used during output) */
|
2013-02-04 15:08:06 +00:00
|
|
|
addr_t sh_addr; /* address at which the section is relocated */
|
2012-03-03 17:10:15 +00:00
|
|
|
unsigned long sh_offset; /* file offset */
|
2009-05-05 18:17:26 +00:00
|
|
|
int nb_hashed_syms; /* used to resize the hash table */
|
|
|
|
struct Section *link; /* link to another section */
|
|
|
|
struct Section *reloc; /* corresponding section for relocation, if any */
|
2016-06-28 13:11:06 +00:00
|
|
|
struct Section *hash; /* hash table for symbols */
|
|
|
|
struct Section *prev; /* previous section on section stack */
|
2025-02-11 19:16:44 +00:00
|
|
|
char old_name[1]; /* section name */
|
2009-05-05 18:17:26 +00:00
|
|
|
} Section;
|
|
|
|
|
2025-02-21 14:10:26 +00:00
|
|
|
#endif
|
|
|
|
|
2009-05-05 18:17:26 +00:00
|
|
|
/* -------------------------------------------------- */
|
|
|
|
|
|
|
|
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
|
|
|
|
#define SYM_FIELD 0x20000000 /* struct/union field symbol space */
|
|
|
|
#define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
|
|
|
|
|
2017-07-09 10:34:11 +00:00
|
|
|
/* stored in 'Sym->f.func_type' field */
|
2009-05-05 18:17:26 +00:00
|
|
|
#define FUNC_NEW 1 /* ansi function prototype */
|
|
|
|
#define FUNC_OLD 2 /* old function prototype */
|
|
|
|
#define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
|
|
|
|
|
2017-07-09 10:34:11 +00:00
|
|
|
/* stored in 'Sym->f.func_call' field */
|
2009-05-05 18:17:26 +00:00
|
|
|
#define FUNC_CDECL 0 /* standard c call */
|
|
|
|
#define FUNC_STDCALL 1 /* pascal c call */
|
|
|
|
#define FUNC_FASTCALL1 2 /* first param in %eax */
|
|
|
|
#define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
|
|
|
|
#define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
|
|
|
|
#define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
|
2024-06-03 11:52:34 +00:00
|
|
|
#define FUNC_THISCALL 6 /* first param in %ecx */
|
2009-05-05 18:17:26 +00:00
|
|
|
|
|
|
|
/* field 'Sym.t' for macros */
|
|
|
|
#define MACRO_OBJ 0 /* object like macro */
|
|
|
|
#define MACRO_FUNC 1 /* function like macro */
|
2024-02-09 15:07:43 +00:00
|
|
|
#define MACRO_JOIN 2 /* macro uses ## */
|
2009-05-05 18:17:26 +00:00
|
|
|
|
|
|
|
/* field 'Sym.r' for C labels */
|
|
|
|
#define LABEL_DEFINED 0 /* label is defined */
|
|
|
|
#define LABEL_FORWARD 1 /* label is forward defined */
|
|
|
|
#define LABEL_DECLARED 2 /* label is declared but never used */
|
2020-04-14 20:35:58 +00:00
|
|
|
#define LABEL_GONE 3 /* label isn't in scope, but not yet popped
|
|
|
|
from local_label_stack (stmt exprs) */
|
2009-05-05 18:17:26 +00:00
|
|
|
|
|
|
|
/* type_decl() types */
|
|
|
|
#define TYPE_ABSTRACT 1 /* type without variable */
|
|
|
|
#define TYPE_DIRECT 2 /* type with variable */
|
2022-03-01 21:00:42 +00:00
|
|
|
#define TYPE_PARAM 4 /* type declares function parameter */
|
2022-03-24 09:16:37 +00:00
|
|
|
#define TYPE_NEST 8 /* nested call to post_type */
|
2009-05-05 18:17:26 +00:00
|
|
|
|
2025-02-14 16:47:45 +00:00
|
|
|
#include <tcc/io.h>
|
2009-05-05 18:17:26 +00:00
|
|
|
|
2025-02-21 14:10:26 +00:00
|
|
|
#define WARN_ON 1
|
|
|
|
|
2009-05-05 18:17:26 +00:00
|
|
|
/* used to record tokens */
|
|
|
|
typedef struct TokenString {
|
|
|
|
int *str;
|
|
|
|
int len;
|
2024-02-09 15:07:43 +00:00
|
|
|
int need_spc;
|
2009-05-05 18:17:26 +00:00
|
|
|
int allocated_len;
|
|
|
|
int last_line_num;
|
2017-07-20 20:21:27 +00:00
|
|
|
int save_line_num;
|
tccpp: fix issues, add tests
* fix some macro expansion issues
* add some pp tests in tests/pp
* improved tcc -E output for better diff'ability
* remove -dD feature (quirky code, exotic feature,
didn't work well)
Based partially on ideas / researches from PipCet
Some issues remain with VA_ARGS macros (if used in a
rather tricky way).
Also, to keep it simple, the pp doesn't automtically
add any extra spaces to separate tokens which otherwise
would form wrong tokens if re-read from tcc -E output
(such as '+' '=') GCC does that, other compilers don't.
* cleanups
- #line 01 "file" / # 01 "file" processing
- #pragma comment(lib,"foo")
- tcc -E: forward some pragmas to output (pack, comment(lib))
- fix macro parameter list parsing mess from
a3fc54345949535524d01319e1ca6378b7c2c201
a715d7143d9d17da17e67fec6af1c01409a71a31
(some coffee might help, next time ;)
- introduce TOK_PPSTR - to have character constants as
written in the file (similar to TOK_PPNUM)
- allow '\' appear in macros
- new functions begin/end_macro to:
- fix switching macro levels during expansion
- allow unget_tok to unget more than one tok
- slight speedup by using bitflags in isidnum_table
Also:
- x86_64.c : fix decl after statements
- i386-gen,c : fix a vstack leak with VLA on windows
- configure/Makefile : build on windows (MSYS) was broken
- tcc_warning: fflush stderr to keep output order (win32)
2015-05-09 12:29:39 +00:00
|
|
|
/* used to chain token-strings with begin/end_macro() */
|
|
|
|
struct TokenString *prev;
|
|
|
|
const int *prev_ptr;
|
|
|
|
char alloc;
|
2009-05-05 18:17:26 +00:00
|
|
|
} TokenString;
|
|
|
|
|
2018-12-20 09:55:22 +00:00
|
|
|
/* GNUC attribute definition */
|
|
|
|
typedef struct AttributeDef {
|
|
|
|
struct SymAttr a;
|
|
|
|
struct FuncAttr f;
|
2025-02-21 14:10:26 +00:00
|
|
|
struct TCCSection *section;
|
2018-12-20 09:55:22 +00:00
|
|
|
Sym *cleanup_func;
|
Reinstate attribute alias handling
commit 2a0167a merged alias and asm symbol renaming, but broke
semantics of aliases, see testcase. Basically the difference between
the two is that an asm rename doesn't generate a new symbol, i.e. with
int foo __asm__("bar");
all source reference to 'foo' will be to 'bar', nothing of the name
'foo' will remain in the object file, and for instance reference to
'foo' from other compilation units won't be resolved to this one.
Aliases OTOH create an additional symbol. With:
void target (void) { return; }
void afunc (void) __attribute__((alias("target")));
reference to 'afunc' will remain 'afunc' in the object file. It will
generate two symbols, 'afunc' and 'target' referring to the same entity.
This difference matters if other compilation units make references to
'afunc'.
A side requirement of this is that for alias to work that the target
symbol needs to be defined in the same unit. For TCC we even require a
stricter variant: it must be defined before the alias is created.
Now, with this I merely re-instated the old flow of events before above
commit. It didn't seem useful anymore to place both names in the
asm_label member of attributes, and the asm_label member of Sym now
again only needs the hold the __asm__ rename.
It also follows that tcc_predefs.h can't make use of attribute alias to
e.g. map __builtin_memcpy to __bound_memcpy (simply because the latter
isn't defined in all units), but rather must use __asm__ renaming, which
in turn means that the underscore handling needs to be done by hand.
2020-09-30 15:46:01 +00:00
|
|
|
int alias_target; /* token */
|
2018-12-20 09:55:22 +00:00
|
|
|
int asm_label; /* associated asm label */
|
|
|
|
char attr_mode; /* __attribute__((__mode__(...))) */
|
|
|
|
} AttributeDef;
|
|
|
|
|
2009-06-29 19:14:53 +00:00
|
|
|
/* inline functions */
|
|
|
|
typedef struct InlineFunc {
|
2016-11-11 17:29:45 +00:00
|
|
|
TokenString *func_str;
|
2009-06-29 19:14:53 +00:00
|
|
|
Sym *sym;
|
|
|
|
char filename[1];
|
|
|
|
} InlineFunc;
|
|
|
|
|
2009-05-05 18:17:26 +00:00
|
|
|
/* include file cache, used to find files faster and also to eliminate
|
|
|
|
inclusion if the include file is protected by #ifndef ... #endif */
|
|
|
|
typedef struct CachedInclude {
|
|
|
|
int ifndef_macro;
|
2016-10-01 18:03:48 +00:00
|
|
|
int once;
|
2009-05-05 18:17:26 +00:00
|
|
|
int hash_next; /* -1 if none */
|
|
|
|
char filename[1]; /* path specified in #include */
|
|
|
|
} CachedInclude;
|
|
|
|
|
2016-10-01 18:03:48 +00:00
|
|
|
#define CACHED_INCLUDES_HASH_SIZE 32
|
2009-05-05 18:17:26 +00:00
|
|
|
|
2009-05-11 16:45:56 +00:00
|
|
|
typedef struct ExprValue {
|
2016-05-11 21:47:02 +00:00
|
|
|
uint64_t v;
|
2009-05-11 16:45:56 +00:00
|
|
|
Sym *sym;
|
2016-06-29 13:57:32 +00:00
|
|
|
int pcrel;
|
2009-05-11 16:45:56 +00:00
|
|
|
} ExprValue;
|
|
|
|
|
|
|
|
#define MAX_ASM_OPERANDS 30
|
|
|
|
typedef struct ASMOperand {
|
2022-07-07 14:45:16 +00:00
|
|
|
int id; /* GCC 3 optional identifier (0 if number only supported) */
|
2023-04-24 19:58:50 +00:00
|
|
|
char constraint[16];
|
2009-05-11 16:45:56 +00:00
|
|
|
char asm_str[16]; /* computed asm string for operand */
|
|
|
|
SValue *vt; /* C value of the expression */
|
|
|
|
int ref_index; /* if >= 0, gives reference to a output constraint */
|
|
|
|
int input_index; /* if >= 0, gives reference to an input constraint */
|
|
|
|
int priority; /* priority, used to assign registers */
|
|
|
|
int reg; /* if >= 0, register number used for this operand */
|
|
|
|
int is_llong; /* true if double register value */
|
|
|
|
int is_memory; /* true if memory operand */
|
|
|
|
int is_rw; /* for '+' modifier */
|
2022-07-07 14:45:16 +00:00
|
|
|
int is_label; /* for asm goto */
|
2009-05-11 16:45:56 +00:00
|
|
|
} ASMOperand;
|
|
|
|
|
2025-02-21 14:10:26 +00:00
|
|
|
#if 0
|
2009-05-05 18:17:26 +00:00
|
|
|
struct TCCState {
|
2019-12-01 20:22:57 +00:00
|
|
|
unsigned char verbose; /* if true, display some information during compilation */
|
|
|
|
unsigned char nostdinc; /* if true, no standard headers are added */
|
|
|
|
unsigned char nostdlib; /* if true, no standard libraries are added */
|
|
|
|
unsigned char symbolic; /* if true, resolve symbols in the current module first */
|
|
|
|
unsigned char filetype; /* file type for compilation (NONE,C,ASM) */
|
2020-06-01 16:10:58 +00:00
|
|
|
unsigned char optimize; /* only to #define __OPTIMIZE__ */
|
|
|
|
unsigned char option_pthread; /* -pthread option */
|
2019-12-01 20:22:57 +00:00
|
|
|
unsigned int cversion; /* supported C ISO version, 199901 (the default), 201112, ... */
|
2009-05-05 18:17:26 +00:00
|
|
|
|
|
|
|
/* C language options */
|
2019-12-01 20:22:57 +00:00
|
|
|
unsigned char char_is_unsigned;
|
|
|
|
unsigned char leading_underscore;
|
|
|
|
unsigned char ms_extensions; /* allow nested named struct w/o identifier behave like unnamed */
|
|
|
|
unsigned char dollars_in_identifiers; /* allows '$' char in identifiers */
|
|
|
|
unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */
|
2024-11-17 20:04:29 +00:00
|
|
|
unsigned char reverse_funcargs; /* if true, evaluate last function arg first */
|
2024-11-17 20:10:20 +00:00
|
|
|
unsigned char gnu89_inline; /* treat 'extern inline' like 'static inline' */
|
2016-04-03 08:42:15 +00:00
|
|
|
|
2021-07-31 18:44:51 +00:00
|
|
|
/* warning switches */
|
|
|
|
unsigned char warn_none;
|
|
|
|
unsigned char warn_all;
|
|
|
|
unsigned char warn_error;
|
|
|
|
unsigned char warn_write_strings;
|
|
|
|
unsigned char warn_unsupported;
|
|
|
|
unsigned char warn_implicit_function_declaration;
|
|
|
|
unsigned char warn_discarded_qualifiers;
|
|
|
|
#define WARN_ON 1 /* warning is on (-Woption) */
|
|
|
|
unsigned char warn_num; /* temp var for tcc_warning_c() */
|
2009-05-05 18:17:26 +00:00
|
|
|
|
2021-08-01 18:04:46 +00:00
|
|
|
unsigned char option_r; /* option -r */
|
|
|
|
unsigned char do_bench; /* option -bench */
|
|
|
|
unsigned char just_deps; /* option -M */
|
|
|
|
unsigned char gen_deps; /* option -MD */
|
|
|
|
unsigned char include_sys_deps; /* option -MD */
|
2023-10-29 14:20:16 +00:00
|
|
|
unsigned char gen_phony_deps; /* option -MP */
|
2021-08-01 18:04:46 +00:00
|
|
|
|
|
|
|
/* use GNU C extensions */
|
|
|
|
unsigned char gnu_ext;
|
|
|
|
/* use TinyCC extensions */
|
|
|
|
unsigned char tcc_ext;
|
|
|
|
|
|
|
|
unsigned char dflag; /* -dX value */
|
|
|
|
unsigned char Pflag; /* -P switch (LINE_MACRO_OUTPUT_FORMAT) */
|
|
|
|
|
2019-12-01 20:22:57 +00:00
|
|
|
unsigned char has_text_addr;
|
2021-08-01 18:04:46 +00:00
|
|
|
addr_t text_addr; /* address of text section */
|
2016-12-15 16:01:22 +00:00
|
|
|
unsigned section_align; /* section alignment */
|
2025-02-07 16:17:17 +00:00
|
|
|
|
2021-08-01 18:04:46 +00:00
|
|
|
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
|
2025-02-11 12:07:04 +00:00
|
|
|
char *entryname; /* "_start" unless set */
|
2017-09-26 05:16:23 +00:00
|
|
|
|
2021-08-01 18:04:46 +00:00
|
|
|
/* output type, see TCC_OUTPUT_XXX */
|
|
|
|
int output_type;
|
|
|
|
/* output format, see TCC_OUTPUT_FORMAT_xxx */
|
|
|
|
int output_format;
|
2013-02-12 18:13:28 +00:00
|
|
|
|
various stuff
win32/Makefile ("for cygwin") removed
- On cygwin, the normal ./configure && make can be used with either
cygwin's "GCC for Win32 Toolchain"
./configure --cross-prefix=i686-w64-mingw32-
or with an existing tcc:
./configure --cc=<old-tccdir>/tcc.exe
tcctest.c:
- exclude test_high_clobbers() on _WIN64 (does not work)
tests2/95_bitfield.c:
- use 'signed char' for ARM (where default 'char' is unsigned)
tests:
- remove -I "expr" diff option to allow tests with
busybox-diff.
libtcc.c, tcc.c:
- removed -iwithprefix option. It is supposed to be
combined with -iprefix which we don't have either.
tccgen.c:
- fix assignments and return of 'void', as in
void f() {
void *p, *q;
*p = *q:
return *p;
}
This appears to be allowed but should do nothing.
tcc.h, libtcc.c, tccpp.c:
- Revert "Introduce VIP sysinclude paths which are always searched first"
This reverts commit 1d5e386b0a78393ac6b670c209a185849ec798a1.
The patch was giving tcc's system includes priority over -I which
is not how it should be.
tccelf.c:
- add DT_TEXTREL tag only if text relocations are actually
used (which is likely not the case on x86_64)
- prepare_dynamic_rel(): avoid relocation of unresolved
(weak) symbols
tccrun.c:
- for HAVE_SELINUX, use two mappings to the same (real) file.
(it was so once except the RX mapping wasn't used at all).
tccpe.c:
- fix relocation constant used for x86_64 (by Andrei E. Warentin)
- #ifndef _WIN32 do "chmod 755 ..." to get runnable exes on cygwin.
tccasm.c:
- keep forward asm labels static, otherwise they will endup
in dynsym eventually.
configure, Makefile:
- mingw32: respect ./configure options --bindir --docdir --libdir
- allow overriding tcc when building libtcc1.a and libtcc.def with
make XTCC=<tcc program to use>
- use $(wildcard ...) for install to allow installing just
a cross compiler for example
make cross-arm
make install
- use name <target>-libtcc1.a
build-tcc.bat:
- add options: -clean, -b bindir
2017-10-11 16:13:43 +00:00
|
|
|
/* include paths */
|
2013-02-12 18:13:28 +00:00
|
|
|
char **include_paths;
|
|
|
|
int nb_include_paths;
|
|
|
|
|
|
|
|
char **sysinclude_paths;
|
|
|
|
int nb_sysinclude_paths;
|
|
|
|
|
|
|
|
/* library paths */
|
|
|
|
char **library_paths;
|
|
|
|
int nb_library_paths;
|
|
|
|
|
|
|
|
/* crt?.o object path */
|
|
|
|
char **crt_paths;
|
|
|
|
int nb_crt_paths;
|
2009-05-11 16:45:44 +00:00
|
|
|
|
2019-12-10 23:37:18 +00:00
|
|
|
/* -D / -U options */
|
|
|
|
CString cmdline_defs;
|
|
|
|
/* -include options */
|
|
|
|
CString cmdline_incl;
|
2016-06-27 14:40:00 +00:00
|
|
|
|
2009-05-05 18:17:26 +00:00
|
|
|
/* error handling */
|
|
|
|
void *error_opaque;
|
|
|
|
void (*error_func)(void *opaque, const char *msg);
|
|
|
|
int error_set_jmp_enabled;
|
|
|
|
jmp_buf error_jmp_buf;
|
|
|
|
int nb_errors;
|
|
|
|
|
2013-02-12 18:13:28 +00:00
|
|
|
/* output file for preprocessing (-E) */
|
|
|
|
FILE *ppfp;
|
2009-05-05 18:17:26 +00:00
|
|
|
|
2013-02-12 18:13:28 +00:00
|
|
|
/* for -MD/-MF: collected dependencies for this compilation */
|
|
|
|
char **target_deps;
|
|
|
|
int nb_target_deps;
|
|
|
|
|
|
|
|
/* compilation */
|
2009-05-05 18:17:26 +00:00
|
|
|
BufferedFile *include_stack[INCLUDE_STACK_SIZE];
|
2013-02-12 18:13:28 +00:00
|
|
|
BufferedFile **include_stack_ptr;
|
2009-05-05 18:17:26 +00:00
|
|
|
|
|
|
|
int ifdef_stack[IFDEF_STACK_SIZE];
|
2013-02-12 18:13:28 +00:00
|
|
|
int *ifdef_stack_ptr;
|
2009-05-05 18:17:26 +00:00
|
|
|
|
2013-02-12 18:13:28 +00:00
|
|
|
/* included files enclosed with #ifndef MACRO */
|
2009-05-05 18:17:26 +00:00
|
|
|
int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
|
2013-02-12 18:13:28 +00:00
|
|
|
CachedInclude **cached_includes;
|
|
|
|
int nb_cached_includes;
|
2009-05-05 18:17:26 +00:00
|
|
|
|
2013-02-12 18:13:28 +00:00
|
|
|
/* #pragma pack stack */
|
2009-05-05 18:17:26 +00:00
|
|
|
int pack_stack[PACK_STACK_SIZE];
|
|
|
|
int *pack_stack_ptr;
|
tccpp: fix issues, add tests
* fix some macro expansion issues
* add some pp tests in tests/pp
* improved tcc -E output for better diff'ability
* remove -dD feature (quirky code, exotic feature,
didn't work well)
Based partially on ideas / researches from PipCet
Some issues remain with VA_ARGS macros (if used in a
rather tricky way).
Also, to keep it simple, the pp doesn't automtically
add any extra spaces to separate tokens which otherwise
would form wrong tokens if re-read from tcc -E output
(such as '+' '=') GCC does that, other compilers don't.
* cleanups
- #line 01 "file" / # 01 "file" processing
- #pragma comment(lib,"foo")
- tcc -E: forward some pragmas to output (pack, comment(lib))
- fix macro parameter list parsing mess from
a3fc54345949535524d01319e1ca6378b7c2c201
a715d7143d9d17da17e67fec6af1c01409a71a31
(some coffee might help, next time ;)
- introduce TOK_PPSTR - to have character constants as
written in the file (similar to TOK_PPNUM)
- allow '\' appear in macros
- new functions begin/end_macro to:
- fix switching macro levels during expansion
- allow unget_tok to unget more than one tok
- slight speedup by using bitflags in isidnum_table
Also:
- x86_64.c : fix decl after statements
- i386-gen,c : fix a vstack leak with VLA on windows
- configure/Makefile : build on windows (MSYS) was broken
- tcc_warning: fflush stderr to keep output order (win32)
2015-05-09 12:29:39 +00:00
|
|
|
char **pragma_libs;
|
|
|
|
int nb_pragma_libs;
|
2009-05-05 18:17:26 +00:00
|
|
|
|
2013-02-12 18:13:28 +00:00
|
|
|
/* inline functions are stored as token lists and compiled last
|
|
|
|
only if referenced */
|
2009-06-29 19:14:53 +00:00
|
|
|
struct InlineFunc **inline_fns;
|
|
|
|
int nb_inline_fns;
|
|
|
|
|
2013-02-12 18:13:28 +00:00
|
|
|
/* sections */
|
|
|
|
Section **sections;
|
|
|
|
int nb_sections; /* number of sections, including first dummy section */
|
|
|
|
|
|
|
|
Section **priv_sections;
|
|
|
|
int nb_priv_sections; /* number of private sections */
|
|
|
|
|
2019-12-10 23:37:18 +00:00
|
|
|
/* predefined sections */
|
2021-02-01 14:10:58 +00:00
|
|
|
Section *text_section, *data_section, *rodata_section, *bss_section;
|
2019-12-10 23:37:18 +00:00
|
|
|
Section *cur_text_section; /* current section where function code is generated */
|
2022-05-09 15:02:09 +00:00
|
|
|
/* symbol section */
|
2025-02-14 16:47:45 +00:00
|
|
|
Section *symtab_section;
|
2022-05-09 15:02:09 +00:00
|
|
|
|
2019-12-10 23:37:18 +00:00
|
|
|
/* Is there a new undefined sym since last new_undef_sym() */
|
|
|
|
int new_undef_sym;
|
2025-02-14 16:47:45 +00:00
|
|
|
|
2019-12-09 19:32:13 +00:00
|
|
|
/* ptr to next reloc entry reused */
|
|
|
|
ElfW_Rel *qrel;
|
2021-10-22 05:39:54 +00:00
|
|
|
#define qrel s1->qrel
|
2017-11-30 14:15:22 +00:00
|
|
|
|
2019-12-14 11:31:03 +00:00
|
|
|
/* benchmark info */
|
|
|
|
int total_idents;
|
|
|
|
int total_lines;
|
2023-03-23 19:02:19 +00:00
|
|
|
unsigned int total_bytes;
|
2023-02-03 00:04:38 +00:00
|
|
|
unsigned int total_output[4];
|
2019-12-14 11:31:03 +00:00
|
|
|
|
2021-08-01 18:04:46 +00:00
|
|
|
/* for warnings/errors for object files */
|
2020-06-17 06:21:37 +00:00
|
|
|
const char *current_filename;
|
|
|
|
|
2013-02-12 18:13:28 +00:00
|
|
|
/* used by main and tcc_parse_args only */
|
2016-10-01 18:04:58 +00:00
|
|
|
struct filespec **files; /* files seen on command line */
|
2013-02-12 18:13:28 +00:00
|
|
|
int nb_files; /* number thereof */
|
|
|
|
int nb_libraries; /* number of libs thereof */
|
|
|
|
char *outfile; /* output filename */
|
|
|
|
char *deps_outfile; /* option -MF */
|
2017-02-18 08:55:34 +00:00
|
|
|
int argc;
|
|
|
|
char **argv;
|
2023-04-15 07:54:23 +00:00
|
|
|
CString linker_arg; /* collect -Wl options */
|
2009-05-05 18:17:26 +00:00
|
|
|
};
|
2025-02-21 14:10:26 +00:00
|
|
|
#else
|
|
|
|
# include <tcc/state.h>
|
|
|
|
#endif
|
2009-05-05 18:17:26 +00:00
|
|
|
|
2016-10-01 18:04:58 +00:00
|
|
|
struct filespec {
|
2017-02-18 08:55:34 +00:00
|
|
|
char type;
|
|
|
|
char name[1];
|
2016-10-01 18:04:58 +00:00
|
|
|
};
|
|
|
|
|
2009-05-05 18:17:26 +00:00
|
|
|
/* The current value can be: */
|
2013-02-12 18:13:28 +00:00
|
|
|
#define VT_VALMASK 0x003f /* mask for value location, register or: */
|
|
|
|
#define VT_CONST 0x0030 /* constant in vc (must be first non register value) */
|
2011-08-06 14:08:03 +00:00
|
|
|
#define VT_LLOCAL 0x0031 /* lvalue, offset on stack */
|
|
|
|
#define VT_LOCAL 0x0032 /* offset on stack */
|
|
|
|
#define VT_CMP 0x0033 /* the value is stored in processor flags (in vc) */
|
|
|
|
#define VT_JMP 0x0034 /* value is the consequence of jmp true (even) */
|
|
|
|
#define VT_JMPI 0x0035 /* value is the consequence of jmp false (odd) */
|
2009-05-05 18:17:26 +00:00
|
|
|
#define VT_LVAL 0x0100 /* var is an lvalue */
|
|
|
|
#define VT_SYM 0x0200 /* a symbol value is added */
|
2019-12-16 17:51:28 +00:00
|
|
|
#define VT_MUSTCAST 0x0C00 /* value must be casted to be correct (used for
|
2009-05-05 18:17:26 +00:00
|
|
|
char/short stored in integer registers) */
|
2022-08-16 14:58:00 +00:00
|
|
|
#define VT_NONCONST 0x1000 /* VT_CONST, but not an (C standard) integer
|
|
|
|
constant expression */
|
2019-12-16 17:51:28 +00:00
|
|
|
#define VT_MUSTBOUND 0x4000 /* bound checking must be done before
|
2009-05-05 18:17:26 +00:00
|
|
|
dereferencing value */
|
|
|
|
#define VT_BOUNDED 0x8000 /* value is bounded. The address of the
|
|
|
|
bounding function call point is in vc */
|
|
|
|
/* types */
|
2013-02-12 18:13:28 +00:00
|
|
|
#define VT_BTYPE 0x000f /* mask for basic type */
|
2017-07-09 10:34:11 +00:00
|
|
|
#define VT_VOID 0 /* void type */
|
2013-02-12 18:13:28 +00:00
|
|
|
#define VT_BYTE 1 /* signed byte type */
|
|
|
|
#define VT_SHORT 2 /* short type */
|
2017-07-09 10:34:11 +00:00
|
|
|
#define VT_INT 3 /* integer type */
|
|
|
|
#define VT_LLONG 4 /* 64 bit integer */
|
|
|
|
#define VT_PTR 5 /* pointer */
|
2013-02-12 18:13:28 +00:00
|
|
|
#define VT_FUNC 6 /* function type */
|
|
|
|
#define VT_STRUCT 7 /* struct/union definition */
|
2017-07-09 10:38:25 +00:00
|
|
|
#define VT_FLOAT 8 /* IEEE float */
|
|
|
|
#define VT_DOUBLE 9 /* IEEE double */
|
|
|
|
#define VT_LDOUBLE 10 /* IEEE long double */
|
|
|
|
#define VT_BOOL 11 /* ISOC99 boolean type */
|
|
|
|
#define VT_QLONG 13 /* 128-bit integer. Only used for x86-64 ABI */
|
|
|
|
#define VT_QFLOAT 14 /* 128-bit float. Only used for x86-64 ABI */
|
2017-07-09 10:34:11 +00:00
|
|
|
|
2013-02-12 18:13:28 +00:00
|
|
|
#define VT_UNSIGNED 0x0010 /* unsigned type */
|
2017-07-09 10:34:11 +00:00
|
|
|
#define VT_DEFSIGN 0x0020 /* explicitly signed or unsigned */
|
|
|
|
#define VT_ARRAY 0x0040 /* array type (also has VT_PTR) */
|
|
|
|
#define VT_BITFIELD 0x0080 /* bitfield modifier */
|
|
|
|
#define VT_CONSTANT 0x0100 /* const modifier */
|
|
|
|
#define VT_VOLATILE 0x0200 /* volatile modifier */
|
|
|
|
#define VT_VLA 0x0400 /* VLA type (also has VT_PTR and VT_ARRAY) */
|
2017-09-24 16:57:48 +00:00
|
|
|
#define VT_LONG 0x0800 /* long type (also has VT_INT rsp. VT_LLONG) */
|
2009-05-05 18:17:26 +00:00
|
|
|
|
|
|
|
/* storage */
|
2017-07-09 10:34:11 +00:00
|
|
|
#define VT_EXTERN 0x00001000 /* extern definition */
|
|
|
|
#define VT_STATIC 0x00002000 /* static variable */
|
|
|
|
#define VT_TYPEDEF 0x00004000 /* typedef definition */
|
|
|
|
#define VT_INLINE 0x00008000 /* inline definition */
|
2019-06-17 01:34:03 +00:00
|
|
|
/* currently unused: 0x000[1248]0000 */
|
2009-05-05 18:17:26 +00:00
|
|
|
|
2017-07-09 10:34:11 +00:00
|
|
|
#define VT_STRUCT_SHIFT 20 /* shift for bitfield shift values (32 - 2*6) */
|
2019-06-21 22:42:24 +00:00
|
|
|
#define VT_STRUCT_MASK (((1U << (6+6)) - 1) << VT_STRUCT_SHIFT | VT_BITFIELD)
|
2017-07-09 10:34:11 +00:00
|
|
|
#define BIT_POS(t) (((t) >> VT_STRUCT_SHIFT) & 0x3f)
|
|
|
|
#define BIT_SIZE(t) (((t) >> (VT_STRUCT_SHIFT + 6)) & 0x3f)
|
2014-04-14 00:53:11 +00:00
|
|
|
|
2017-07-09 10:38:25 +00:00
|
|
|
#define VT_UNION (1 << VT_STRUCT_SHIFT | VT_STRUCT)
|
|
|
|
#define VT_ENUM (2 << VT_STRUCT_SHIFT) /* integral type is an enum really */
|
|
|
|
#define VT_ENUM_VAL (3 << VT_STRUCT_SHIFT) /* integral type is an enum constant really */
|
|
|
|
|
|
|
|
#define IS_ENUM(t) ((t & VT_STRUCT_MASK) == VT_ENUM)
|
|
|
|
#define IS_ENUM_VAL(t) ((t & VT_STRUCT_MASK) == VT_ENUM_VAL)
|
|
|
|
#define IS_UNION(t) ((t & (VT_STRUCT_MASK|VT_BTYPE)) == VT_UNION)
|
|
|
|
|
2021-01-26 13:29:07 +00:00
|
|
|
#define VT_ATOMIC VT_VOLATILE
|
|
|
|
|
2009-05-05 18:17:26 +00:00
|
|
|
/* type mask (except storage) */
|
2019-06-17 01:34:03 +00:00
|
|
|
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
|
2017-07-09 10:38:25 +00:00
|
|
|
#define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK))
|
2017-07-09 10:34:11 +00:00
|
|
|
|
2017-11-30 14:15:22 +00:00
|
|
|
/* symbol was created by tccasm.c first */
|
2020-11-25 10:23:01 +00:00
|
|
|
#define VT_ASM (VT_VOID | 1 << VT_STRUCT_SHIFT)
|
|
|
|
#define VT_ASM_FUNC (VT_ASM | 2 << VT_STRUCT_SHIFT)
|
2017-11-30 14:15:22 +00:00
|
|
|
#define IS_ASM_SYM(sym) (((sym)->type.t & (VT_BTYPE | VT_ASM)) == VT_ASM)
|
|
|
|
|
2019-12-16 17:51:28 +00:00
|
|
|
/* general: set/get the pseudo-bitfield value for bit-mask M */
|
|
|
|
#define BFVAL(M,N) ((unsigned)((M) & ~((M) << 1)) * (N))
|
|
|
|
#define BFGET(X,M) (((X) & (M)) / BFVAL(M,1))
|
|
|
|
#define BFSET(X,M,N) ((X) = ((X) & ~(M)) | BFVAL(M,N))
|
|
|
|
|
2009-12-20 00:53:49 +00:00
|
|
|
/* ------------ libtcc.c ------------ */
|
|
|
|
|
2025-02-08 14:45:16 +00:00
|
|
|
extern struct TCCState *tcc_state;
|
|
|
|
extern void** stk_data;
|
|
|
|
extern int nb_stk_data;
|
2009-12-20 00:53:49 +00:00
|
|
|
|
2025-02-08 14:45:16 +00:00
|
|
|
PUB_FUNC int _tcc_error_noabort(const char *fmt, ...) __attribute__ ((format (printf, (1), (2))));
|
|
|
|
PUB_FUNC __attribute__((noreturn)) void _tcc_error(const char *fmt, ...) __attribute__ ((format (printf, (1), (2))));
|
|
|
|
PUB_FUNC void _tcc_warning(const char *fmt, ...) __attribute__ ((format (printf, (1), (2))));
|
2024-06-11 11:57:22 +00:00
|
|
|
#define tcc_internal_error(msg) \
|
|
|
|
tcc_error("internal compiler error in %s:%d: %s", __FUNCTION__,__LINE__,msg)
|
2009-12-20 00:53:49 +00:00
|
|
|
|
|
|
|
/* other utilities */
|
2025-02-08 14:45:16 +00:00
|
|
|
void dynarray_add(void *ptab, int *nb_ptr, void *data);
|
|
|
|
void dynarray_reset(void *pp, int *n);
|
|
|
|
void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
|
|
|
|
int tcc_open(TCCState *s1, const char *filename);
|
|
|
|
void tcc_close(void);
|
2010-11-25 12:29:15 +00:00
|
|
|
|
2023-04-24 19:58:50 +00:00
|
|
|
/* mark a memory pointer on stack for cleanup after errors */
|
|
|
|
#define stk_push(p) dynarray_add(&stk_data, &nb_stk_data, p)
|
|
|
|
#define stk_pop() (--nb_stk_data)
|
|
|
|
/* mark CString on stack for cleanup errors */
|
|
|
|
#define cstr_new_s(cstr) (cstr_new(cstr), stk_push(&(cstr)->data))
|
|
|
|
#define cstr_free_s(cstr) (cstr_free(cstr), stk_pop())
|
|
|
|
|
2025-02-08 14:45:16 +00:00
|
|
|
int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
|
2016-10-01 18:46:16 +00:00
|
|
|
/* flags: */
|
|
|
|
#define AFF_PRINT_ERROR 0x10 /* print error if file not found */
|
2017-07-20 20:21:27 +00:00
|
|
|
#define AFF_TYPE_BIN 0x40 /* file to add is binary */
|
2018-05-31 21:51:59 +00:00
|
|
|
#define AFF_WHOLE_ARCHIVE 0x80 /* load all objects from archive */
|
2017-07-20 20:21:27 +00:00
|
|
|
/* s->filetype: */
|
2016-10-01 18:54:45 +00:00
|
|
|
#define AFF_TYPE_NONE 0
|
|
|
|
#define AFF_TYPE_C 1
|
|
|
|
#define AFF_TYPE_ASM 2
|
2018-05-31 21:51:59 +00:00
|
|
|
#define AFF_TYPE_ASMPP 4
|
|
|
|
#define AFF_TYPE_LIB 8
|
|
|
|
#define AFF_TYPE_MASK (15 | AFF_TYPE_BIN)
|
2025-02-21 14:10:26 +00:00
|
|
|
|
2016-10-01 18:54:45 +00:00
|
|
|
|
2024-02-04 16:38:23 +00:00
|
|
|
/* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */
|
|
|
|
#define FILE_NOT_FOUND -2
|
|
|
|
|
2020-06-27 15:15:06 +00:00
|
|
|
#ifndef ELF_OBJ_ONLY
|
2025-02-08 14:45:16 +00:00
|
|
|
int tcc_add_crt(TCCState *s, const char *filename);
|
2018-06-08 13:31:40 +00:00
|
|
|
#endif
|
2025-02-08 14:45:16 +00:00
|
|
|
int tcc_add_support(TCCState *s1, const char *filename);
|
2025-02-07 16:17:17 +00:00
|
|
|
|
2025-02-08 14:45:16 +00:00
|
|
|
void tcc_add_pragma_libs(TCCState *s1);
|
2021-10-22 05:39:54 +00:00
|
|
|
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
|
|
|
|
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
|
2025-02-08 17:38:14 +00:00
|
|
|
char *tcc_load_text(int fd);
|
2023-06-26 00:05:27 +00:00
|
|
|
/* for #pragma once */
|
2025-02-08 14:45:16 +00:00
|
|
|
int normalized_PATHCMP(const char *f1, const char *f2);
|
2013-02-19 11:47:36 +00:00
|
|
|
|
2025-02-21 14:10:26 +00:00
|
|
|
/* ------------- coff.c ------------- */
|
|
|
|
void coff_delete(TCCState *s1);
|
|
|
|
void coff_new(TCCState *s1);
|
|
|
|
void coff_section_realloc(TCCSection *sec, size_t new_size);
|
|
|
|
TCCSection *coff_find_section(TCCState *s1, const char *name);
|
|
|
|
void *coff_section_ptr_add(TCCSection *sec, size_t size);
|
|
|
|
int coff_add_sym(TCCState *s1, uint32_t value, const char *name, size_t size,
|
|
|
|
int16_t scnum, uint16_t type, int8_t sclass);
|
|
|
|
void coff_add_reloca(TCCState *s1, TCCSection *s, uint32_t offset,
|
|
|
|
int type, int symbol, uint32_t addend);
|
|
|
|
size_t coff_section_add(TCCSection *sec, size_t size, int align);
|
|
|
|
void coff_begin_file(TCCState *s1);
|
|
|
|
void coff_end_file(TCCState *s1);
|
|
|
|
int coff_load_file(TCCState *s1, int fd, unsigned long file_offset);
|
|
|
|
void coff_add_crtbegin(TCCState *s1);
|
|
|
|
void coff_add_crtend(TCCState *s1);
|
|
|
|
/* ------------- archive.c ---------- */
|
|
|
|
int archive_load(TCCState *s1, int fd, int alacarte);
|
|
|
|
|
2009-12-20 00:53:49 +00:00
|
|
|
|
2013-02-12 18:13:28 +00:00
|
|
|
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
|
|
|
|
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
|
|
|
|
|
2020-05-17 02:18:26 +00:00
|
|
|
/* Browse each elem of type <type> in section <sec> starting at elem <startoff>
|
|
|
|
using variable <elem> */
|
|
|
|
#define for_each_elem(sec, startoff, elem, type) \
|
|
|
|
for (elem = (type *) sec->data + startoff; \
|
|
|
|
elem < (type *) (sec->data + sec->data_offset); elem++)
|
|
|
|
|
2025-02-08 14:45:16 +00:00
|
|
|
void tcc_add_runtime(TCCState *s1);
|
2025-02-07 16:17:17 +00:00
|
|
|
|
2022-05-09 15:02:09 +00:00
|
|
|
/* ------------ tccdbg.c ------------ */
|
2019-12-10 23:37:18 +00:00
|
|
|
#define tcc_error_noabort TCC_SET_STATE(_tcc_error_noabort)
|
|
|
|
#define tcc_error TCC_SET_STATE(_tcc_error)
|
|
|
|
#define tcc_warning TCC_SET_STATE(_tcc_warning)
|
|
|
|
|
2019-12-14 11:31:03 +00:00
|
|
|
#define total_idents TCC_STATE_VAR(total_idents)
|
|
|
|
#define total_lines TCC_STATE_VAR(total_lines)
|
|
|
|
#define total_bytes TCC_STATE_VAR(total_bytes)
|
|
|
|
|
2021-10-22 05:39:54 +00:00
|
|
|
PUB_FUNC void tcc_enter_state(TCCState *s1);
|
|
|
|
PUB_FUNC void tcc_exit_state(TCCState *s1);
|
2019-12-10 23:37:18 +00:00
|
|
|
|
2021-07-31 18:44:51 +00:00
|
|
|
/* conditional warning depending on switch */
|
|
|
|
#define tcc_warning_c(sw) TCC_SET_STATE((\
|
2021-10-22 05:39:54 +00:00
|
|
|
tcc_state->warn_num = offsetof(TCCState, sw) \
|
2021-07-31 18:44:51 +00:00
|
|
|
- offsetof(TCCState, warn_none), _tcc_warning))
|
|
|
|
|
2009-12-20 00:53:49 +00:00
|
|
|
/********************************************************/
|
|
|
|
#endif /* _TCC_H */
|
2019-12-10 23:37:18 +00:00
|
|
|
|
|
|
|
#undef TCC_STATE_VAR
|
|
|
|
#undef TCC_SET_STATE
|
|
|
|
|
|
|
|
#ifdef USING_GLOBALS
|
2021-10-22 05:39:54 +00:00
|
|
|
# define TCC_STATE_VAR(sym) tcc_state->sym
|
2019-12-10 23:37:18 +00:00
|
|
|
# define TCC_SET_STATE(fn) fn
|
|
|
|
# undef USING_GLOBALS
|
2023-04-15 07:54:23 +00:00
|
|
|
# undef _tcc_error
|
2019-12-10 23:37:18 +00:00
|
|
|
#else
|
2021-10-22 05:39:54 +00:00
|
|
|
# define TCC_STATE_VAR(sym) s1->sym
|
|
|
|
# define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn)
|
2023-04-15 07:54:23 +00:00
|
|
|
# define _tcc_error use_tcc_error_noabort
|
2019-12-10 23:37:18 +00:00
|
|
|
#endif
|