tcc-stupidos/libtcc/include/tcc.h

1299 lines
44 KiB
C
Raw Normal View History

/*
* TCC - Tiny C Compiler
*
* 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
*/
#ifndef _TCC_H
#define _TCC_H
2009-05-05 18:17:26 +00:00
#define _GNU_SOURCE
#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>
/* gnu headers use to #define __attribute__ to empty for non-gcc compilers */
#ifdef __TINYC__
# undef __attribute__
#endif
2009-05-05 18:17:26 +00:00
#include <string.h>
#include <fcntl.h>
#include <setjmp.h>
#include <time.h>
#ifndef _WIN32
# include <unistd.h>
# include <sys/time.h>
# ifndef CONFIG_TCC_STATIC
# include <dlfcn.h>
# endif
/* XXX: need to define this to use them in non ISOC99 context */
extern float strtof (const char *__nptr, char **__endptr);
extern long double strtold (const char *__nptr, char **__endptr);
#endif
2016-10-17 21:24:01 +00:00
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN 1
# include <windows.h>
# include <io.h> /* open, close etc. */
# include <direct.h> /* getcwd */
# include <malloc.h> /* alloca */
# ifdef __GNUC__
# include <stdint.h>
# endif
# define inline __inline
# define snprintf _snprintf
# define vsnprintf _vsnprintf
# ifndef __GNUC__
# define strtold (long double)strtod
# define strtof (float)strtod
# define strtoll _strtoi64
# define strtoull _strtoui64
# endif
# ifndef va_copy
# define va_copy(a,b) a = b
# endif
2009-05-05 18:17:26 +00:00
#endif
#ifndef O_BINARY
# define O_BINARY 0
#endif
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
#ifndef countof
#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
#endif
#ifdef _WIN32
# define IS_DIRSEP(c) (c == '/' || c == '\\')
# define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2])))
# define PATHCMP stricmp
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
# define PATHSEP ";"
#else
# define IS_DIRSEP(c) (c == '/')
# define IS_ABSPATH(p) IS_DIRSEP(p[0])
# define PATHCMP strcmp
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
# define PATHSEP ":"
#endif
2016-10-17 21:24:01 +00:00
/* -------------------------------------------- */
2009-05-05 18:17:26 +00:00
/* parser debug */
/* #define PARSE_DEBUG */
2009-05-05 18:17:26 +00:00
/* preprocessor debug */
/* #define PP_DEBUG */
2009-05-05 18:17:26 +00:00
/* include file debug */
/* #define INC_DEBUG */
/* memory leak debug (only for single threaded usage) */
/* #define MEM_DEBUG 1,2,3 */
2009-05-05 18:17:26 +00:00
/* assembler debug */
/* #define ASM_DEBUG */
2009-05-05 18:17:26 +00:00
#ifdef CONFIG_TCC_PIE
# define CONFIG_TCC_PIC 1
#endif
/* support using libtcc from threads */
#ifndef CONFIG_TCC_SEMLOCK
# define CONFIG_TCC_SEMLOCK 1
#endif
/* ------------ path configuration ------------ */
2009-05-05 18:17:26 +00:00
#ifndef CONFIG_SYSROOT
# define CONFIG_SYSROOT ""
#endif
#if !defined CONFIG_TCCDIR && !defined _WIN32
# define CONFIG_TCCDIR "/usr/local/lib/tcc"
#endif
#ifndef CONFIG_LDDIR
# define CONFIG_LDDIR "lib"
#endif
#ifdef CONFIG_TRIPLET
# define USE_TRIPLET(s) s "/" CONFIG_TRIPLET
# define ALSO_TRIPLET(s) USE_TRIPLET(s) ":" s
#else
# define USE_TRIPLET(s) s
# define ALSO_TRIPLET(s) s
#endif
/* path to find crt1.o, crti.o and crtn.o */
#ifndef CONFIG_TCC_CRTPREFIX
# define CONFIG_TCC_CRTPREFIX USE_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR)
#endif
#ifndef CONFIG_USR_INCLUDE
# define CONFIG_USR_INCLUDE "/usr/include"
#endif
/* Below: {B} is substituted by CONFIG_TCCDIR (rsp. -B option) */
/* 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
# 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") \
":" ALSO_TRIPLET(CONFIG_SYSROOT CONFIG_USR_INCLUDE)
#endif
/* library search paths */
#ifndef CONFIG_TCC_LIBPATHS
# define CONFIG_TCC_LIBPATHS \
"{B}" \
":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \
":" ALSO_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) \
":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR)
#endif
/* (target specific) libtcc1.a */
#ifndef TCC_LIBTCC1
# define TCC_LIBTCC1 "libtcc1.a"
#endif
/* <cross-prefix-to->libtcc1.a */
#ifndef CONFIG_TCC_CROSSPREFIX
# define CONFIG_TCC_CROSSPREFIX ""
#endif
2016-10-17 21:24:01 +00:00
/* -------------------------------------------- */
#include <libtcc.h>
#include <tcc/elf.h>
#include <tcc/coff.h>
2016-10-17 21:24:01 +00:00
/* -------------------------------------------- */
#ifndef PUB_FUNC /* functions used by tcc.c but not in libtcc.h */
# define PUB_FUNC
#endif
/* -------------------------------------------- */
/* include the target specific definitions */
# include "tcc/i386/gen.h"
# include "tcc/i386/link.h"
# 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"
/* target address type */
#define addr_t ElfW(Addr)
#define ElfSym ElfW(Sym)
#define LONG_SIZE 4
/* -------------------------------------------- */
2009-05-05 18:17:26 +00:00
#define INCLUDE_STACK_SIZE 32
#define IFDEF_STACK_SIZE 64
#define VSTACK_SIZE 512
2009-05-05 18:17:26 +00:00
#define STRING_MAX_SIZE 1024
#define TOKSTR_MAX_SIZE 256
2009-05-05 18:17:26 +00:00
#define PACK_STACK_SIZE 8
#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;
typedef struct CString {
int size; /* size in bytes */
int size_allocated;
char *data; /* nwchar_t* in cases */
2009-05-05 18:17:26 +00:00
} CString;
/* type definition */
typedef struct CType {
int t;
struct Sym *ref;
} CType;
/* constant value */
typedef union CValue {
long double ld;
double d;
float f;
uint64_t i;
struct {
char *data;
int size;
} str;
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 */
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;
/* symbol attributes */
struct SymAttr {
unsigned short
aligned : 5, /* alignment as log2+1 (0 == unspecified) */
packed : 1,
weak : 1,
visibility : 2,
dllexport : 1,
nodecorate : 1,
dllimport : 1,
addrtaken : 1,
nodebug : 1,
xxxx : 2; /* not used */
};
/* function attributes or temporary attributes for parsing */
struct FuncAttr {
unsigned
func_call : 3, /* calling convention (0..5), see below */
func_type : 2, /* FUNC_OLD/NEW/ELLIPSIS */
func_noreturn : 1, /* attribute((noreturn)) */
2020-01-17 21:58:39 +00:00
func_ctor : 1, /* attribute((constructor)) */
func_dtor : 1, /* attribute((destructor)) */
func_args : 8, /* PE __stdcall args */
func_alwinl : 1, /* always_inline */
xxxx : 15;
};
2009-05-05 18:17:26 +00:00
/* symbol management */
typedef struct Sym {
int v; /* symbol token */
unsigned short r; /* associated register or VT_CONST/VT_LOCAL and LVAL type */
struct SymAttr a; /* symbol attributes */
union {
struct {
int c; /* associated number or Elf symbol index */
union {
int sym_scope; /* scope level for locals */
int jnext; /* next jump label */
int jind; /* label position */
struct FuncAttr f; /* function attributes */
int auxtype; /* bitfield access type */
};
};
long long enum_val; /* enum constant if IS_ENUM_VAL */
int *d; /* define token stream */
struct Sym *cleanup_func;
};
CType type; /* associated type */
union {
struct Sym *next; /* next related symbol (for fields and anoms) */
int *e; /* expanded token stream */
int asm_label; /* associated asm label */
struct Sym *cleanupstate; /* in defined labels */
int *vla_array_str; /* vla array code */
};
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;
/* 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 */
TCCState *s1;
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) */
addr_t sh_addr; /* address at which the section is relocated */
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 */
struct Section *hash; /* hash table for symbols */
struct Section *prev; /* previous section on section stack */
2009-05-05 18:17:26 +00:00
char name[1]; /* section name */
} Section;
/* -------------------------------------------------- */
#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 */
/* 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 ... */
/* 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 */
#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 */
#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 */
#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 */
#define TYPE_PARAM 4 /* type declares function parameter */
#define TYPE_NEST 8 /* nested call to post_type */
2009-05-05 18:17:26 +00:00
#define IO_BUF_SIZE 8192
typedef struct BufferedFile {
uint8_t *buf_ptr;
uint8_t *buf_end;
int fd;
struct BufferedFile *prev;
2009-05-05 18:17:26 +00:00
int line_num; /* current line number - here to simplify code */
int line_ref; /* tcc -E: last printed line */
2009-05-05 18:17:26 +00:00
int ifndef_macro; /* #ifndef macro / #endif search */
int ifndef_macro_saved; /* saved ifndef_macro */
int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
int include_next_index; /* next search path */
int prev_tok_flags; /* saved tok_flags */
char filename[1024]; /* filename */
char *true_filename; /* filename not modified by # line directive */
unsigned char unget[4];
unsigned char buffer[1]; /* extra size for CH_EOB char */
2009-05-05 18:17:26 +00:00
} BufferedFile;
#define CH_EOB '\\' /* end of buffer or '\0' char in file */
#define CH_EOF (-1) /* end of file */
/* used to record tokens */
typedef struct TokenString {
int *str;
int len;
int need_spc;
2009-05-05 18:17:26 +00:00
int allocated_len;
int last_line_num;
int save_line_num;
/* 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;
/* GNUC attribute definition */
typedef struct AttributeDef {
struct SymAttr a;
struct FuncAttr f;
struct Section *section;
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 */
int asm_label; /* associated asm label */
char attr_mode; /* __attribute__((__mode__(...))) */
} AttributeDef;
/* inline functions */
typedef struct InlineFunc {
TokenString *func_str;
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;
int once;
2009-05-05 18:17:26 +00:00
int hash_next; /* -1 if none */
char filename[1]; /* path specified in #include */
} CachedInclude;
#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 {
uint64_t v;
2009-05-11 16:45:56 +00:00
Sym *sym;
int pcrel;
2009-05-11 16:45:56 +00:00
} ExprValue;
#define MAX_ASM_OPERANDS 30
typedef struct ASMOperand {
int id; /* GCC 3 optional identifier (0 if number only supported) */
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 */
int is_label; /* for asm goto */
2009-05-11 16:45:56 +00:00
} ASMOperand;
/* extra symbol attributes (not in symbol table) */
struct sym_attr {
unsigned got_offset;
unsigned plt_offset;
int plt_sym;
int dyn_index;
};
2009-05-05 18:17:26 +00:00
struct TCCState {
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 nocommon; /* if true, do not use common symbols for .bss data */
unsigned char symbolic; /* if true, resolve symbols in the current module first */
unsigned char filetype; /* file type for compilation (NONE,C,ASM) */
unsigned char optimize; /* only to #define __OPTIMIZE__ */
unsigned char option_pthread; /* -pthread option */
unsigned char enable_new_dtags; /* -Wl,--enable-new-dtags */
unsigned int cversion; /* supported C ISO version, 199901 (the default), 201112, ... */
2009-05-05 18:17:26 +00:00
/* C language options */
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 */
unsigned char reverse_funcargs; /* if true, evaluate last function arg first */
unsigned char gnu89_inline; /* treat 'extern inline' like 'static inline' */
unsigned char unwind_tables; /* create eh_frame section */
/* 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
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 */
/* 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) */
unsigned char has_text_addr;
addr_t text_addr; /* address of text section */
unsigned section_align; /* section alignment */
int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
char *rpath; /* as specified on the command line (-Wl,-rpath=) */
char *elf_entryname; /* "_start" unless set */
char *init_symbol; /* symbols to call at load-time (not used currently) */
char *fini_symbol; /* symbols to call at unload-time (not used currently) */
char *mapfile; /* create a mapfile (not used currently) */
/* output type, see TCC_OUTPUT_XXX */
int output_type;
/* output format, see TCC_OUTPUT_FORMAT_xxx */
int output_format;
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 */
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;
/* -D / -U options */
CString cmdline_defs;
/* -include options */
CString cmdline_incl;
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;
/* output file for preprocessing (-E) */
FILE *ppfp;
2009-05-05 18:17:26 +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];
BufferedFile **include_stack_ptr;
2009-05-05 18:17:26 +00:00
int ifdef_stack[IFDEF_STACK_SIZE];
int *ifdef_stack_ptr;
2009-05-05 18:17:26 +00:00
/* included files enclosed with #ifndef MACRO */
2009-05-05 18:17:26 +00:00
int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
CachedInclude **cached_includes;
int nb_cached_includes;
2009-05-05 18:17:26 +00:00
/* #pragma pack stack */
2009-05-05 18:17:26 +00:00
int pack_stack[PACK_STACK_SIZE];
int *pack_stack_ptr;
char **pragma_libs;
int nb_pragma_libs;
2009-05-05 18:17:26 +00:00
/* inline functions are stored as token lists and compiled last
only if referenced */
struct InlineFunc **inline_fns;
int nb_inline_fns;
/* sections */
Section **sections;
int nb_sections; /* number of sections, including first dummy section */
Section **priv_sections;
int nb_priv_sections; /* number of private sections */
/* predefined sections */
Section *text_section, *data_section, *rodata_section, *bss_section;
Section *common_section;
Section *cur_text_section; /* current section where function code is generated */
/* symbol section */
union { Section *symtab_section, *symtab; }; /* historical alias */
/* exported dynamic symbol section */
Section *dynsym;
/* got & plt handling */
Section *got, *plt;
/* exception handling */
Section *eh_frame_section;
Section *eh_frame_hdr_section;
unsigned long eh_start;
/* Is there a new undefined sym since last new_undef_sym() */
int new_undef_sym;
/* extra attributes (eg. GOT/PLT value) for symtab symbols */
struct sym_attr *sym_attrs;
int nb_sym_attrs;
/* ptr to next reloc entry reused */
ElfW_Rel *qrel;
#define qrel s1->qrel
#ifndef ELF_OBJ_ONLY
int nb_sym_versions;
struct sym_version *sym_versions;
int nb_sym_to_version;
int *sym_to_version;
int dt_verneednum;
Section *versym_section;
Section *verneed_section;
#endif
/* benchmark info */
int total_idents;
int total_lines;
unsigned int total_bytes;
unsigned int total_output[4];
/* used by tcc_load_ldscript */
int fd, cc;
/* for warnings/errors for object files */
const char *current_filename;
/* used by main and tcc_parse_args only */
struct filespec **files; /* files seen on command line */
int nb_files; /* number thereof */
int nb_libraries; /* number of libs thereof */
char *outfile; /* output filename */
char *deps_outfile; /* option -MF */
int argc;
char **argv;
CString linker_arg; /* collect -Wl options */
2009-05-05 18:17:26 +00:00
};
struct filespec {
char type;
char name[1];
};
2009-05-05 18:17:26 +00:00
/* The current value can be: */
#define VT_VALMASK 0x003f /* mask for value location, register or: */
#define VT_CONST 0x0030 /* constant in vc (must be first non register value) */
#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) */
#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 */
#define VT_BTYPE 0x000f /* mask for basic type */
#define VT_VOID 0 /* void type */
#define VT_BYTE 1 /* signed byte type */
#define VT_SHORT 2 /* short type */
#define VT_INT 3 /* integer type */
#define VT_LLONG 4 /* 64 bit integer */
#define VT_PTR 5 /* pointer */
#define VT_FUNC 6 /* function type */
#define VT_STRUCT 7 /* struct/union definition */
#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 */
#define VT_UNSIGNED 0x0010 /* unsigned type */
#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) */
#define VT_LONG 0x0800 /* long type (also has VT_INT rsp. VT_LLONG) */
2009-05-05 18:17:26 +00:00
/* storage */
#define VT_EXTERN 0x00001000 /* extern definition */
#define VT_STATIC 0x00002000 /* static variable */
#define VT_TYPEDEF 0x00004000 /* typedef definition */
#define VT_INLINE 0x00008000 /* inline definition */
/* currently unused: 0x000[1248]0000 */
2009-05-05 18:17:26 +00:00
#define VT_STRUCT_SHIFT 20 /* shift for bitfield shift values (32 - 2*6) */
#define VT_STRUCT_MASK (((1U << (6+6)) - 1) << VT_STRUCT_SHIFT | VT_BITFIELD)
#define BIT_POS(t) (((t) >> VT_STRUCT_SHIFT) & 0x3f)
#define BIT_SIZE(t) (((t) >> (VT_STRUCT_SHIFT + 6)) & 0x3f)
#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)
#define VT_ATOMIC VT_VOLATILE
2009-05-05 18:17:26 +00:00
/* type mask (except storage) */
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
#define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK))
/* symbol was created by tccasm.c first */
#define VT_ASM (VT_VOID | 1 << VT_STRUCT_SHIFT)
#define VT_ASM_FUNC (VT_ASM | 2 << VT_STRUCT_SHIFT)
#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))
/* ------------ libtcc.c ------------ */
extern struct TCCState *tcc_state;
extern void** stk_data;
extern int nb_stk_data;
/* public functions currently used by the tcc main function */
PUB_FUNC char *tcc_basename(const char *name);
PUB_FUNC char *tcc_fileextension (const char *name);
2015-05-12 08:56:39 +00:00
/* all allocations - even MEM_DEBUG - use these */
PUB_FUNC void tcc_free(void *ptr);
PUB_FUNC void *tcc_malloc(unsigned long size);
PUB_FUNC void *tcc_mallocz(unsigned long size);
PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size);
PUB_FUNC char *tcc_strdup(const char *str);
#ifdef MEM_DEBUG
#define tcc_free(ptr) tcc_free_debug(ptr)
#define tcc_malloc(size) tcc_malloc_debug(size, __FILE__, __LINE__)
#define tcc_mallocz(size) tcc_mallocz_debug(size, __FILE__, __LINE__)
#define tcc_realloc(ptr,size) tcc_realloc_debug(ptr, size, __FILE__, __LINE__)
#define tcc_strdup(str) tcc_strdup_debug(str, __FILE__, __LINE__)
PUB_FUNC void tcc_free_debug(void *ptr);
PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line);
PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line);
PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line);
PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);
#endif
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))));
#define tcc_internal_error(msg) \
tcc_error("internal compiler error in %s:%d: %s", __FUNCTION__,__LINE__,msg)
/* other utilities */
void dynarray_add(void *ptab, int *nb_ptr, void *data);
void dynarray_reset(void *pp, int *n);
void cstr_ccat(CString *cstr, int ch);
void cstr_cat(CString *cstr, const char *str, int len);
void cstr_wccat(CString *cstr, int ch);
void cstr_new(CString *cstr);
void cstr_free(CString *cstr);
int cstr_printf(CString *cs, const char *fmt, ...) __attribute__ ((format (printf, (2), (3))));
int cstr_vprintf(CString *cstr, const char *fmt, va_list ap);
void cstr_reset(CString *cstr);
void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
int tcc_open(TCCState *s1, const char *filename);
void tcc_close(void);
/* 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())
int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
/* flags: */
#define AFF_PRINT_ERROR 0x10 /* print error if file not found */
#define AFF_TYPE_BIN 0x40 /* file to add is binary */
#define AFF_WHOLE_ARCHIVE 0x80 /* load all objects from archive */
/* s->filetype: */
#define AFF_TYPE_NONE 0
#define AFF_TYPE_C 1
#define AFF_TYPE_ASM 2
#define AFF_TYPE_ASMPP 4
#define AFF_TYPE_LIB 8
#define AFF_TYPE_MASK (15 | AFF_TYPE_BIN)
/* values from tcc_object_type(...) */
#define AFF_BINTYPE_REL 1
#define AFF_BINTYPE_DYN 2
#define AFF_BINTYPE_AR 3
#define AFF_BINTYPE_COFF 4
/* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */
#define FILE_NOT_FOUND -2
#ifndef ELF_OBJ_ONLY
int tcc_add_crt(TCCState *s, const char *filename);
#endif
int tcc_add_support(TCCState *s1, const char *filename);
void tcc_add_pragma_libs(TCCState *s1);
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);
2016-10-15 13:55:31 +00:00
#ifdef _WIN32
char *normalize_slashes(char *path);
2016-10-15 13:55:31 +00:00
#endif
/* for #pragma once */
int normalized_PATHCMP(const char *f1, const char *f2);
/* ------------ tccpp.c ------------ */
extern struct BufferedFile *file;
extern int tok;
extern CValue tokc;
extern const int *macro_ptr;
extern int parse_flags;
extern int tok_flags;
extern CString tokcstr; /* current parsed string, if any */
/* display benchmark infos */
extern int tok_ident;
extern TokenSym **table_ident;
extern int pp_expr;
#define TOK_FLAG_BOL 0x0001 /* beginning of line before */
#define TOK_FLAG_BOF 0x0002 /* beginning of file before */
#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
token. line feed is also
returned at eof */
#define PARSE_FLAG_ASM_FILE 0x0008 /* we processing an asm file: '#' can be used for line comment, etc. */
#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
#define PARSE_FLAG_ACCEPT_STRAYS 0x0020 /* next() returns '\\' token */
#define PARSE_FLAG_TOK_STR 0x0040 /* return parsed strings instead of TOK_PPSTR */
/* isidnum_table flags: */
#define IS_SPC 1
#define IS_ID 2
#define IS_NUM 4
enum line_macro_output_format {
LINE_MACRO_OUTPUT_FORMAT_GCC,
LINE_MACRO_OUTPUT_FORMAT_NONE,
LINE_MACRO_OUTPUT_FORMAT_STD,
LINE_MACRO_OUTPUT_FORMAT_P10 = 11
};
TokenSym *tok_alloc(const char *str, int len);
int tok_alloc_const(const char *str);
const char *get_tok_str(int v, CValue *cv);
void begin_macro(TokenString *str, int alloc);
void end_macro(void);
int set_idnum(int c, int val);
void tok_str_new(TokenString *s);
TokenString *tok_str_alloc(void);
void tok_str_free(TokenString *s);
void tok_str_free_str(int *str);
void tok_str_add(TokenString *s, int t);
void tok_str_add_tok(TokenString *s);
void define_push(int v, int macro_type, int *str, Sym *first_arg);
void define_undef(Sym *s);
Sym *define_find(int v);
void free_defines(Sym *b);
void parse_define(void);
void skip_to_eol(int warn);
void preprocess(int is_bof);
void next(void);
void unget_tok(int last_tok);
void preprocess_start(TCCState *s1, int filetype);
void preprocess_end(TCCState *s1);
void tccpp_new(TCCState *s);
void tccpp_delete(TCCState *s);
void tccpp_putfile(const char *filename);
int tcc_preprocess(TCCState *s1);
void skip(int c);
__attribute__((noreturn)) void expect(const char *msg);
void pp_error(CString *cs);
2017-05-08 04:38:09 +00:00
/* space excluding newline */
static inline int is_space(int ch) {
return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
}
static inline int isid(int c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}
static inline int isnum(int c) {
return c >= '0' && c <= '9';
}
static inline int isoct(int c) {
return c >= '0' && c <= '7';
}
static inline int toup(int c) {
return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
}
/* ------------ tccgen.c ------------ */
#define SYM_POOL_NB (8192 / sizeof(Sym))
extern Sym *global_stack;
extern Sym *local_stack;
extern Sym *local_label_stack;
extern Sym *global_label_stack;
extern Sym *define_stack;
extern CType int_type, func_old_type, char_pointer_type;
extern SValue *vtop;
extern int rsym, anon_sym, ind, loc;
extern char debug_modes;
extern int nocode_wanted; /* true if no code generation wanted for an expression */
extern int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
extern CType func_vt; /* current function return type (used by return instruction) */
extern int func_var; /* true if current function is variadic */
extern int func_vc;
extern int func_ind;
extern const char *funcname;
void tccgen_init(TCCState *s1);
int tccgen_compile(TCCState *s1);
void tccgen_finish(TCCState *s1);
void check_vstack(void);
int is_float(int t);
int ieee_finite(double d);
int exact_log2p1(int i);
void test_lvalue(void);
ElfSym *elfsym(Sym *);
void update_storage(Sym *sym);
void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);
#if PTR_SIZE == 4
void greloc(Section *s, Sym *sym, unsigned long offset, int type);
#endif
void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
void sym_free(Sym *sym);
Sym *sym_push(int v, CType *type, int r, int c);
void sym_pop(Sym **ptop, Sym *b, int keep);
Sym *sym_push2(Sym **ps, int v, int t, int c);
Sym *sym_find2(Sym *s, int v);
Sym *sym_find(int v);
Sym *label_find(int v);
Sym *label_push(Sym **ptop, int v, int flags);
void label_pop(Sym **ptop, Sym *slast, int keep);
Sym *struct_find(int v);
Sym *global_identifier_push(int v, int t, int c);
Sym *external_global_sym(int v, CType *type);
Sym *external_helper_sym(int v);
void vpush_helper_func(int v);
void vset(CType *type, int r, int v);
void vset_VT_CMP(int op);
void vpushi(int v);
void vpushv(SValue *v);
void vpushsym(CType *type, Sym *sym);
void vswap(void);
void vrott(int n);
void vrotb(int n);
void vrev(int n);
void vpop(void);
#if PTR_SIZE == 4
void lexpand(void);
#endif
void save_reg(int r);
void save_reg_upstack(int r, int n);
int get_reg(int rc);
void save_regs(int n);
void gaddrof(void);
int gv(int rc);
void gv2(int rc1, int rc2);
void gen_op(int op);
int type_size(CType *type, int *a);
void mk_pointer(CType *type);
void vstore(void);
void inc(int post, int c);
CString* parse_mult_str(const char *msg);
CString* parse_asm_str(void);
void indir(void);
void unary(void);
void gexpr(void);
int expr_const(void);
/* ------------ tccelf.c ------------ */
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
2022-12-28 02:07:53 +00:00
#define ARMAG "!<arch>\n" /* For COFF and a.out archives */
void tccelf_new(TCCState *s);
void tccelf_delete(TCCState *s);
void tccelf_begin_file(TCCState *s1);
void tccelf_end_file(TCCState *s1);
Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
void section_realloc(Section *sec, unsigned long new_size);
size_t section_add(Section *sec, addr_t size, int align);
void *section_ptr_add(Section *sec, addr_t size);
Section *find_section(TCCState *s1, const char *name);
void free_section(Section *s);
Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
void init_symtab(Section *s);
int put_elf_str(Section *s, const char *sym);
int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
int find_elf_sym(Section *s, const char *name);
void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol);
void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend);
void resolve_common_syms(TCCState *s1);
void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
void relocate_sections(TCCState *s1);
ssize_t full_read(int fd, void *buf, size_t count);
void *load_data(int fd, unsigned long file_offset, unsigned long size);
int tcc_object_type(int fd, ElfW(Ehdr) *h);
int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
int tcc_load_archive(TCCState *s1, int fd, int alacarte);
void add_array(TCCState *s1, const char *sec, int c);
struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc);
addr_t get_sym_addr(TCCState *s, const char *name, int err, int forc);
void list_elf_symbols(TCCState *s, void *ctx,
void (*symbol_cb)(void *ctx, const char *name, const void *val));
int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs);
2020-01-17 21:58:39 +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++)
#ifndef ELF_OBJ_ONLY
int tcc_load_ldscript(TCCState *s1, int fd);
void tccelf_add_crtbegin(TCCState *s1);
void tccelf_add_crtend(TCCState *s1);
#endif
#ifndef TCC_TARGET_PE
void tcc_add_runtime(TCCState *s1);
#endif
int coff_load_file(TCCState *s1, int fd, const char *fname);
/* ------------ xxx-link.c ------------ */
#if !defined ELF_OBJ_ONLY
int code_reloc (int reloc_type);
int gotplt_entry_type (int reloc_type);
/* Whether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so
that unknown relocation don't create a GOT or PLT entry */
enum gotplt_entry {
NO_GOTPLT_ENTRY, /* never generate (eg. GLOB_DAT & JMP_SLOT relocs) */
BUILD_GOT_ONLY, /* only build GOT (eg. TPOFF relocs) */
AUTO_GOTPLT_ENTRY, /* generate if sym is UNDEF */
ALWAYS_GOTPLT_ENTRY /* always generate (eg. PLTOFF relocs) */
};
#define NEED_RELOC_TYPE
unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
void relocate_plt(TCCState *s1);
void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */
#define NEED_BUILD_GOT
#endif
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
/* ------------ xxx-gen.c ------------ */
extern const char * const target_machine_defs;
extern const int reg_classes[NB_REGS];
void gsym_addr(int t, int a);
void gsym(int t);
void load(int r, SValue *sv);
void store(int r, SValue *v);
int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
void gfunc_call(int nb_args);
void gfunc_prolog(Sym *func_sym);
void gfunc_epilog(void);
void gen_fill_nops(int);
int gjmp(int t);
void gjmp_addr(int a);
int gjmp_cond(int op, int t);
int gjmp_append(int n, int t);
void gen_opi(int op);
void gen_opf(int op);
void gen_cvt_ftoi(int t);
void gen_cvt_itof(void);
void gen_cvt_ftof(void);
void ggoto(void);
void o(unsigned int c);
void gen_vla_sp_save(int addr);
void gen_vla_sp_restore(int addr);
void gen_vla_alloc(CType *type, int align);
static inline uint16_t read16le(unsigned char *p) {
return p[0] | (uint16_t)p[1] << 8;
}
static inline void write16le(unsigned char *p, uint16_t x) {
p[0] = x & 255; p[1] = x >> 8 & 255;
}
static inline uint32_t read32le(unsigned char *p) {
return read16le(p) | (uint32_t)read16le(p + 2) << 16;
}
static inline void write32le(unsigned char *p, uint32_t x) {
write16le(p, x); write16le(p + 2, x >> 16);
}
2016-11-20 13:52:56 +00:00
static inline void add32le(unsigned char *p, int32_t x) {
write32le(p, read32le(p) + x);
}
static inline uint64_t read64le(unsigned char *p) {
return read32le(p) | (uint64_t)read32le(p + 4) << 32;
}
static inline void write64le(unsigned char *p, uint64_t x) {
write32le(p, x); write32le(p + 4, x >> 32);
}
2016-11-20 13:52:56 +00:00
static inline void add64le(unsigned char *p, int64_t x) {
write64le(p, read64le(p) + x);
}
/* ------------ i386-gen.c ------------ */
void g(int c);
void gen_le16(int c);
void gen_le32(int c);
void gen_addr32(int r, Sym *sym, int c);
void gen_addrpc32(int r, Sym *sym, int c);
void gen_cvt_csti(int t);
/* ------------ tccasm.c ------------ */
void asm_instr(void);
void asm_global_instr(void);
int tcc_assemble(TCCState *s1, int do_preprocess);
int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
Sym* get_asm_sym(int name, Sym *csym);
void asm_expr(TCCState *s1, ExprValue *pe);
int asm_int_expr(TCCState *s1);
/* ------------ i386-asm.c ------------ */
void gen_expr32(ExprValue *pe);
void asm_opcode(TCCState *s1, int opcode);
int asm_parse_regvar(int t);
void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
void asm_clobber(uint8_t *clobber_regs, const char *str);
#define ST_ASM_SET 0x04
/* ------------ tccdbg.c ------------ */
#define eh_frame_hdr_section s1->eh_frame_hdr_section
/********************************************************/
#if CONFIG_TCC_SEMLOCK
#if defined _WIN32
typedef struct { int init; CRITICAL_SECTION cs; } TCCSem;
static inline void wait_sem(TCCSem *p) {
if (!p->init)
InitializeCriticalSection(&p->cs), p->init = 1;
EnterCriticalSection(&p->cs);
}
static inline void post_sem(TCCSem *p) {
LeaveCriticalSection(&p->cs);
}
#elif defined __APPLE__
#include <dispatch/dispatch.h>
typedef struct { int init; dispatch_semaphore_t sem; } TCCSem;
static inline void wait_sem(TCCSem *p) {
if (!p->init)
p->sem = dispatch_semaphore_create(1), p->init = 1;
dispatch_semaphore_wait(p->sem, DISPATCH_TIME_FOREVER);
}
static inline void post_sem(TCCSem *p) {
dispatch_semaphore_signal(p->sem);
}
#else
#include <semaphore.h>
#include <errno.h>
typedef struct { int init; sem_t sem; } TCCSem;
static inline void wait_sem(TCCSem *p) {
if (!p->init)
sem_init(&p->sem, 0, 1), p->init = 1;
while (sem_wait(&p->sem) < 0 && errno == EINTR);
}
static inline void post_sem(TCCSem *p) {
sem_post(&p->sem);
}
#endif
#define TCC_SEM(s) TCCSem s
#define WAIT_SEM wait_sem
#define POST_SEM post_sem
#else
#define TCC_SEM(s)
#define WAIT_SEM(p)
#define POST_SEM(p)
#endif
#define text_section TCC_STATE_VAR(text_section)
#define data_section TCC_STATE_VAR(data_section)
#define rodata_section TCC_STATE_VAR(rodata_section)
#define bss_section TCC_STATE_VAR(bss_section)
#define common_section TCC_STATE_VAR(common_section)
#define cur_text_section TCC_STATE_VAR(cur_text_section)
#define bounds_section TCC_STATE_VAR(bounds_section)
#define lbounds_section TCC_STATE_VAR(lbounds_section)
#define symtab_section TCC_STATE_VAR(symtab_section)
#define gnu_ext TCC_STATE_VAR(gnu_ext)
#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)
#define total_idents TCC_STATE_VAR(total_idents)
#define total_lines TCC_STATE_VAR(total_lines)
#define total_bytes TCC_STATE_VAR(total_bytes)
PUB_FUNC void tcc_enter_state(TCCState *s1);
PUB_FUNC void tcc_exit_state(TCCState *s1);
/* conditional warning depending on switch */
#define tcc_warning_c(sw) TCC_SET_STATE((\
tcc_state->warn_num = offsetof(TCCState, sw) \
- offsetof(TCCState, warn_none), _tcc_warning))
/********************************************************/
#endif /* _TCC_H */
#undef TCC_STATE_VAR
#undef TCC_SET_STATE
#ifdef USING_GLOBALS
# define TCC_STATE_VAR(sym) tcc_state->sym
# define TCC_SET_STATE(fn) fn
# undef USING_GLOBALS
# undef _tcc_error
#else
# define TCC_STATE_VAR(sym) s1->sym
# define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn)
# define _tcc_error use_tcc_error_noabort
#endif