777 lines
26 KiB
C
777 lines
26 KiB
C
/*
|
|
* 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
|
|
|
|
#define _GNU_SOURCE
|
|
#define _DARWIN_C_SOURCE
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
/* gnu headers use to #define __attribute__ to empty for non-gcc compilers */
|
|
#ifdef __TINYC__
|
|
# undef __attribute__
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <setjmp.h>
|
|
#include <time.h>
|
|
|
|
#include <unistd.h>
|
|
#include <sys/time.h>
|
|
/* 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);
|
|
|
|
#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
|
|
|
|
/* ------------ path configuration ------------ */
|
|
|
|
#ifndef CONFIG_SYSROOT
|
|
# define CONFIG_SYSROOT ""
|
|
#endif
|
|
#if !defined CONFIG_TCCDIR
|
|
# 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 */
|
|
#ifndef CONFIG_TCC_SYSINCLUDEPATHS
|
|
|
|
# define CONFIG_TCC_SYSINCLUDEPATHS \
|
|
"{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
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
#include <libtcc.h>
|
|
/*#include <tcc/elf.h>*/
|
|
#include <tcc/object/coff.h>
|
|
#include <tcc/utils/cstring.h>
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
#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"
|
|
|
|
# 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 */
|
|
typedef uint32_t addr_t;
|
|
#define ElfSym ElfW(Sym)
|
|
|
|
#define LONG_SIZE 4
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
#define INCLUDE_STACK_SIZE 32
|
|
#define IFDEF_STACK_SIZE 64
|
|
#define VSTACK_SIZE 512
|
|
#define STRING_MAX_SIZE 1024
|
|
#define TOKSTR_MAX_SIZE 256
|
|
#define PACK_STACK_SIZE 8
|
|
|
|
#define TOK_HASH_SIZE 16384 /* must be a power of two */
|
|
#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;
|
|
uint64_t i;
|
|
struct {
|
|
char *data;
|
|
int size;
|
|
} str;
|
|
int tab[LDOUBLE_SIZE/4];
|
|
} 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. */
|
|
|
|
} 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)) */
|
|
func_ctor : 1, /* attribute((constructor)) */
|
|
func_dtor : 1, /* attribute((destructor)) */
|
|
func_args : 8, /* PE __stdcall args */
|
|
func_alwinl : 1, /* always_inline */
|
|
xxxx : 15;
|
|
};
|
|
|
|
/* 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 */
|
|
};
|
|
struct Sym *prev; /* prev symbol in stack */
|
|
struct Sym *prev_tok; /* previous symbol for this token */
|
|
} Sym;
|
|
|
|
#if 0
|
|
/* 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;
|
|
|
|
/**/
|
|
char name[8];
|
|
addr_t addr;
|
|
int32_t flags;
|
|
int32_t size;
|
|
|
|
COFFReloc *coff_reloc;
|
|
/**/
|
|
|
|
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 */
|
|
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 */
|
|
char old_name[1]; /* section name */
|
|
} Section;
|
|
|
|
#endif
|
|
|
|
/* -------------------------------------------------- */
|
|
|
|
#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 */
|
|
#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 */
|
|
#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 */
|
|
|
|
/* 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 ## */
|
|
|
|
/* 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) */
|
|
|
|
/* 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 */
|
|
|
|
#include <tcc/io.h>
|
|
|
|
#define WARN_ON 1
|
|
|
|
/* used to record tokens */
|
|
typedef struct TokenString {
|
|
int *str;
|
|
int len;
|
|
int need_spc;
|
|
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;
|
|
} TokenString;
|
|
|
|
/* GNUC attribute definition */
|
|
typedef struct AttributeDef {
|
|
struct SymAttr a;
|
|
struct FuncAttr f;
|
|
struct TCCSection *section;
|
|
Sym *cleanup_func;
|
|
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;
|
|
|
|
/* 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;
|
|
int hash_next; /* -1 if none */
|
|
char filename[1]; /* path specified in #include */
|
|
} CachedInclude;
|
|
|
|
#define CACHED_INCLUDES_HASH_SIZE 32
|
|
|
|
typedef struct ExprValue {
|
|
uint64_t v;
|
|
Sym *sym;
|
|
int pcrel;
|
|
} ExprValue;
|
|
|
|
#define MAX_ASM_OPERANDS 30
|
|
typedef struct ASMOperand {
|
|
int id; /* GCC 3 optional identifier (0 if number only supported) */
|
|
char constraint[16];
|
|
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 */
|
|
} ASMOperand;
|
|
|
|
#if 0
|
|
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 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 int cversion; /* supported C ISO version, 199901 (the default), 201112, ... */
|
|
|
|
/* 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' */
|
|
|
|
/* 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() */
|
|
|
|
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 */
|
|
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 */
|
|
|
|
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
|
|
char *entryname; /* "_start" unless set */
|
|
|
|
/* output type, see TCC_OUTPUT_XXX */
|
|
int output_type;
|
|
/* output format, see TCC_OUTPUT_FORMAT_xxx */
|
|
int output_format;
|
|
|
|
/* 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;
|
|
|
|
/* 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;
|
|
|
|
/* for -MD/-MF: collected dependencies for this compilation */
|
|
char **target_deps;
|
|
int nb_target_deps;
|
|
|
|
/* compilation */
|
|
BufferedFile *include_stack[INCLUDE_STACK_SIZE];
|
|
BufferedFile **include_stack_ptr;
|
|
|
|
int ifdef_stack[IFDEF_STACK_SIZE];
|
|
int *ifdef_stack_ptr;
|
|
|
|
/* included files enclosed with #ifndef MACRO */
|
|
int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
|
|
CachedInclude **cached_includes;
|
|
int nb_cached_includes;
|
|
|
|
/* #pragma pack stack */
|
|
int pack_stack[PACK_STACK_SIZE];
|
|
int *pack_stack_ptr;
|
|
char **pragma_libs;
|
|
int nb_pragma_libs;
|
|
|
|
/* 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 *cur_text_section; /* current section where function code is generated */
|
|
/* symbol section */
|
|
Section *symtab_section;
|
|
|
|
/* Is there a new undefined sym since last new_undef_sym() */
|
|
int new_undef_sym;
|
|
|
|
/* ptr to next reloc entry reused */
|
|
ElfW_Rel *qrel;
|
|
#define qrel s1->qrel
|
|
|
|
/* benchmark info */
|
|
int total_idents;
|
|
int total_lines;
|
|
unsigned int total_bytes;
|
|
unsigned int total_output[4];
|
|
|
|
/* 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 */
|
|
};
|
|
#else
|
|
# include <tcc/state.h>
|
|
#endif
|
|
|
|
struct filespec {
|
|
char type;
|
|
char name[1];
|
|
};
|
|
|
|
/* 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) */
|
|
#define VT_LVAL 0x0100 /* var is an lvalue */
|
|
#define VT_SYM 0x0200 /* a symbol value is added */
|
|
#define VT_MUSTCAST 0x0C00 /* value must be casted to be correct (used for
|
|
char/short stored in integer registers) */
|
|
#define VT_NONCONST 0x1000 /* VT_CONST, but not an (C standard) integer
|
|
constant expression */
|
|
#define VT_MUSTBOUND 0x4000 /* bound checking must be done before
|
|
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) */
|
|
|
|
/* 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 */
|
|
|
|
#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
|
|
|
|
/* 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)
|
|
|
|
/* 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;
|
|
|
|
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 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)
|
|
|
|
|
|
/* 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);
|
|
char *tcc_load_text(int fd);
|
|
/* for #pragma once */
|
|
int normalized_PATHCMP(const char *f1, const char *f2);
|
|
|
|
/* ------------- 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);
|
|
|
|
|
|
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
|
|
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
|
|
|
|
/* 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++)
|
|
|
|
void tcc_add_runtime(TCCState *s1);
|
|
|
|
/* ------------ tccdbg.c ------------ */
|
|
#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
|