Strip down further TCC (removing unused function, unused parameter...). Split source in multiple files (WIP)
This commit is contained in:
parent
f08ef63153
commit
6318a909ff
65 changed files with 892 additions and 10358 deletions
|
@ -1,3 +1 @@
|
||||||
AM_CFLAGS =
|
SUBDIRS = libtcc tcc libtcc1
|
||||||
|
|
||||||
SUBDIRS = libtcc tcc
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
-I.
|
-I.
|
||||||
-DHAVE_CONFIG_H
|
-DHAVE_CONFIG_H
|
||||||
|
-Ilibtcc/include
|
||||||
-Ilibtcc
|
-Ilibtcc
|
|
@ -10,7 +10,8 @@ AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
libtcc/Makefile
|
libtcc/Makefile
|
||||||
tcc/Makefile])
|
tcc/Makefile
|
||||||
|
libtcc1/Makefile])
|
||||||
|
|
||||||
AC_LANG([C])
|
AC_LANG([C])
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
@ -18,6 +19,7 @@ AC_PROG_CPP
|
||||||
AC_PROG_CC_C_O
|
AC_PROG_CC_C_O
|
||||||
AC_PROG_RANLIB
|
AC_PROG_RANLIB
|
||||||
AM_PROG_AR
|
AM_PROG_AR
|
||||||
|
AM_PROG_AS
|
||||||
|
|
||||||
AC_CHECK_INCLUDES_DEFAULT
|
AC_CHECK_INCLUDES_DEFAULT
|
||||||
AC_C_CONST
|
AC_C_CONST
|
||||||
|
|
|
@ -3,4 +3,4 @@ libtcc_a_SOURCES = libtcc.c tccpp.c tccgen.c \
|
||||||
tccasm.c tccelf.c \
|
tccasm.c tccelf.c \
|
||||||
i386/gen.c i386/link.c \
|
i386/gen.c i386/link.c \
|
||||||
i386/asm.c tcccoff.c
|
i386/asm.c tcccoff.c
|
||||||
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/libtcc
|
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) -I$(srcdir)/include
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
#include "token.h"
|
||||||
|
|
||||||
#define MAX_OPERANDS 3
|
#define MAX_OPERANDS 3
|
||||||
|
|
||||||
|
@ -201,7 +202,7 @@ static const ASMInstr asm_instrs[] = {
|
||||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 2, { op0, op1 }},
|
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 2, { op0, op1 }},
|
||||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 3, { op0, op1, op2 }},
|
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 3, { op0, op1, op2 }},
|
||||||
|
|
||||||
#include "asm.h"
|
#include "asm.inc"
|
||||||
/* last operation */
|
/* last operation */
|
||||||
{ 0, },
|
{ 0, },
|
||||||
};
|
};
|
||||||
|
@ -213,7 +214,7 @@ static const uint16_t op0_codes[] = {
|
||||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||||
#include "asm.h"
|
#include "asm.inc"
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int get_reg_shift(TCCState *s1)
|
static inline int get_reg_shift(TCCState *s1)
|
||||||
|
@ -382,7 +383,7 @@ static void parse_operand(TCCState *s1, Operand *op)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: unify with C code output ? */
|
/* XXX: unify with C code output ? */
|
||||||
ST_FUNC void gen_expr32(ExprValue *pe)
|
void gen_expr32(ExprValue *pe)
|
||||||
{
|
{
|
||||||
if (pe->pcrel)
|
if (pe->pcrel)
|
||||||
/* If PC-relative, always set VT_SYM, even without symbol,
|
/* If PC-relative, always set VT_SYM, even without symbol,
|
||||||
|
@ -501,7 +502,7 @@ static void maybe_print_stats (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_opcode(TCCState *s1, int opcode)
|
void asm_opcode(TCCState *s1, int opcode)
|
||||||
{
|
{
|
||||||
const ASMInstr *pa;
|
const ASMInstr *pa;
|
||||||
int i, modrm_index, modreg_index, reg, v, op1, seg_prefix, pc, p;
|
int i, modrm_index, modreg_index, reg, v, op1, seg_prefix, pc, p;
|
||||||
|
@ -962,7 +963,7 @@ static const char *skip_constraint_modifiers(const char *p)
|
||||||
|
|
||||||
/* If T (a token) is of the form "%reg" returns the register
|
/* If T (a token) is of the form "%reg" returns the register
|
||||||
number and type, otherwise return -1. */
|
number and type, otherwise return -1. */
|
||||||
ST_FUNC int asm_parse_regvar (int t)
|
int asm_parse_regvar (int t)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
Operand op;
|
Operand op;
|
||||||
|
@ -987,7 +988,7 @@ ST_FUNC int asm_parse_regvar (int t)
|
||||||
|
|
||||||
#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
|
#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
|
||||||
|
|
||||||
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
void asm_compute_constraints(ASMOperand *operands,
|
||||||
int nb_operands, int nb_outputs,
|
int nb_operands, int nb_outputs,
|
||||||
const uint8_t *clobber_regs,
|
const uint8_t *clobber_regs,
|
||||||
int *pout_reg)
|
int *pout_reg)
|
||||||
|
@ -1239,7 +1240,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void subst_asm_operand(CString *add_str,
|
void subst_asm_operand(CString *add_str,
|
||||||
SValue *sv, int modifier)
|
SValue *sv, int modifier)
|
||||||
{
|
{
|
||||||
int r, reg, size, val;
|
int r, reg, size, val;
|
||||||
|
@ -1328,7 +1329,7 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate prolog and epilog code for asm statement */
|
/* generate prolog and epilog code for asm statement */
|
||||||
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
void asm_gen_code(ASMOperand *operands, int nb_operands,
|
||||||
int nb_outputs, int is_output,
|
int nb_outputs, int is_output,
|
||||||
uint8_t *clobber_regs,
|
uint8_t *clobber_regs,
|
||||||
int out_reg)
|
int out_reg)
|
||||||
|
@ -1425,7 +1426,7 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
void asm_clobber(uint8_t *clobber_regs, const char *str)
|
||||||
{
|
{
|
||||||
int reg;
|
int reg;
|
||||||
|
|
||||||
|
|
|
@ -18,70 +18,11 @@
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef TARGET_DEFS_ONLY
|
|
||||||
|
|
||||||
/* number of available registers */
|
|
||||||
#define NB_REGS 5
|
|
||||||
#define NB_ASM_REGS 8
|
|
||||||
#define CONFIG_TCC_ASM
|
|
||||||
|
|
||||||
/* a register can belong to several classes. The classes must be
|
|
||||||
sorted from more general to more precise (see gv2() code which does
|
|
||||||
assumptions on it). */
|
|
||||||
#define RC_INT 0x0001 /* generic integer register */
|
|
||||||
#define RC_FLOAT 0x0002 /* generic float register */
|
|
||||||
#define RC_EAX 0x0004
|
|
||||||
#define RC_EDX 0x0008
|
|
||||||
#define RC_ECX 0x0010
|
|
||||||
#define RC_EBX 0x0020
|
|
||||||
#define RC_ST0 0x0040
|
|
||||||
|
|
||||||
#define RC_IRET RC_EAX /* function return: integer register */
|
|
||||||
#define RC_IRE2 RC_EDX /* function return: second integer register */
|
|
||||||
#define RC_FRET RC_ST0 /* function return: float register */
|
|
||||||
|
|
||||||
/* pretty names for the registers */
|
|
||||||
enum {
|
|
||||||
TREG_EAX = 0,
|
|
||||||
TREG_ECX,
|
|
||||||
TREG_EDX,
|
|
||||||
TREG_EBX,
|
|
||||||
TREG_ST0,
|
|
||||||
TREG_ESP = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
/* return registers for function */
|
|
||||||
#define REG_IRET TREG_EAX /* single word int return register */
|
|
||||||
#define REG_IRE2 TREG_EDX /* second word return register (for long long) */
|
|
||||||
#define REG_FRET TREG_ST0 /* float return register */
|
|
||||||
|
|
||||||
/* defined if function parameters must be evaluated in reverse order */
|
|
||||||
#define INVERT_FUNC_PARAMS
|
|
||||||
|
|
||||||
/* defined if structures are passed as pointers. Otherwise structures
|
|
||||||
are directly pushed on stack. */
|
|
||||||
/* #define FUNC_STRUCT_PARAM_AS_PTR */
|
|
||||||
|
|
||||||
/* pointer size, in bytes */
|
|
||||||
#define PTR_SIZE 4
|
|
||||||
|
|
||||||
/* long double size and alignment, in bytes */
|
|
||||||
#define LDOUBLE_SIZE 12
|
|
||||||
#define LDOUBLE_ALIGN 4
|
|
||||||
/* maximum alignment (for aligned attribute support) */
|
|
||||||
#define MAX_ALIGN 8
|
|
||||||
|
|
||||||
/* define if return values need to be extended explicitely
|
|
||||||
at caller side (for interfacing with non-TCC compilers) */
|
|
||||||
#define PROMOTE_RET
|
|
||||||
|
|
||||||
/******************************************************/
|
|
||||||
#else /* ! TARGET_DEFS_ONLY */
|
|
||||||
/******************************************************/
|
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include <tcc.h>
|
||||||
|
#include "token.h"
|
||||||
|
|
||||||
ST_DATA const char * const target_machine_defs =
|
const char * const target_machine_defs =
|
||||||
"__i386__\0"
|
"__i386__\0"
|
||||||
"__i386\0"
|
"__i386\0"
|
||||||
;
|
;
|
||||||
|
@ -89,7 +30,7 @@ ST_DATA const char * const target_machine_defs =
|
||||||
/* define to 1/0 to [not] have EBX as 4th register */
|
/* define to 1/0 to [not] have EBX as 4th register */
|
||||||
#define USE_EBX 0
|
#define USE_EBX 0
|
||||||
|
|
||||||
ST_DATA const int reg_classes[NB_REGS] = {
|
const int reg_classes[NB_REGS] = {
|
||||||
/* eax */ RC_INT | RC_EAX,
|
/* eax */ RC_INT | RC_EAX,
|
||||||
/* ecx */ RC_INT | RC_ECX,
|
/* ecx */ RC_INT | RC_ECX,
|
||||||
/* edx */ RC_INT | RC_EDX,
|
/* edx */ RC_INT | RC_EDX,
|
||||||
|
@ -101,7 +42,7 @@ static unsigned long func_sub_sp_offset;
|
||||||
static int func_ret_sub;
|
static int func_ret_sub;
|
||||||
|
|
||||||
/* XXX: make it faster ? */
|
/* XXX: make it faster ? */
|
||||||
ST_FUNC void g(int c)
|
void g(int c)
|
||||||
{
|
{
|
||||||
int ind1;
|
int ind1;
|
||||||
if (nocode_wanted)
|
if (nocode_wanted)
|
||||||
|
@ -113,7 +54,7 @@ ST_FUNC void g(int c)
|
||||||
ind = ind1;
|
ind = ind1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void o(unsigned int c)
|
void o(unsigned int c)
|
||||||
{
|
{
|
||||||
while (c) {
|
while (c) {
|
||||||
g(c);
|
g(c);
|
||||||
|
@ -121,13 +62,13 @@ ST_FUNC void o(unsigned int c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_le16(int v)
|
void gen_le16(int v)
|
||||||
{
|
{
|
||||||
g(v);
|
g(v);
|
||||||
g(v >> 8);
|
g(v >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_le32(int c)
|
void gen_le32(int c)
|
||||||
{
|
{
|
||||||
g(c);
|
g(c);
|
||||||
g(c >> 8);
|
g(c >> 8);
|
||||||
|
@ -136,7 +77,7 @@ ST_FUNC void gen_le32(int c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* output a symbol and patch all calls to it */
|
/* output a symbol and patch all calls to it */
|
||||||
ST_FUNC void gsym_addr(int t, int a)
|
void gsym_addr(int t, int a)
|
||||||
{
|
{
|
||||||
while (t) {
|
while (t) {
|
||||||
unsigned char *ptr = cur_text_section->data + t;
|
unsigned char *ptr = cur_text_section->data + t;
|
||||||
|
@ -158,7 +99,7 @@ static int oad(int c, int s)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_fill_nops(int bytes)
|
void gen_fill_nops(int bytes)
|
||||||
{
|
{
|
||||||
while (bytes--)
|
while (bytes--)
|
||||||
g(0x90);
|
g(0x90);
|
||||||
|
@ -168,14 +109,14 @@ ST_FUNC void gen_fill_nops(int bytes)
|
||||||
#define gjmp2(instr,lbl) oad(instr,lbl)
|
#define gjmp2(instr,lbl) oad(instr,lbl)
|
||||||
|
|
||||||
/* output constant with relocation if 'r & VT_SYM' is true */
|
/* output constant with relocation if 'r & VT_SYM' is true */
|
||||||
ST_FUNC void gen_addr32(int r, Sym *sym, int c)
|
void gen_addr32(int r, Sym *sym, int c)
|
||||||
{
|
{
|
||||||
if (r & VT_SYM)
|
if (r & VT_SYM)
|
||||||
greloc(cur_text_section, sym, ind, R_386_32);
|
greloc(cur_text_section, sym, ind, R_386_32);
|
||||||
gen_le32(c);
|
gen_le32(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
|
void gen_addrpc32(int r, Sym *sym, int c)
|
||||||
{
|
{
|
||||||
if (r & VT_SYM)
|
if (r & VT_SYM)
|
||||||
greloc(cur_text_section, sym, ind, R_386_PC32);
|
greloc(cur_text_section, sym, ind, R_386_PC32);
|
||||||
|
@ -206,7 +147,7 @@ static void gen_modrm(int op_reg, int r, Sym *sym, int c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load 'r' from value 'sv' */
|
/* load 'r' from value 'sv' */
|
||||||
ST_FUNC void load(int r, SValue *sv)
|
void load(int r, SValue *sv)
|
||||||
{
|
{
|
||||||
int v, t, ft, fc, fr;
|
int v, t, ft, fc, fr;
|
||||||
SValue v1;
|
SValue v1;
|
||||||
|
@ -281,7 +222,7 @@ ST_FUNC void load(int r, SValue *sv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store register 'r' in lvalue 'v' */
|
/* store register 'r' in lvalue 'v' */
|
||||||
ST_FUNC void store(int r, SValue *v)
|
void store(int r, SValue *v)
|
||||||
{
|
{
|
||||||
int fr, bt, ft, fc;
|
int fr, bt, ft, fc;
|
||||||
|
|
||||||
|
@ -349,7 +290,7 @@ static const uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX };
|
||||||
|
|
||||||
/* Return the number of registers needed to return the struct, or 0 if
|
/* Return the number of registers needed to return the struct, or 0 if
|
||||||
returning via struct pointer. */
|
returning via struct pointer. */
|
||||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
|
int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
|
||||||
{
|
{
|
||||||
#if defined(TCC_TARGET_PE) || TARGETOS_FreeBSD || TARGETOS_OpenBSD
|
#if defined(TCC_TARGET_PE) || TARGETOS_FreeBSD || TARGETOS_OpenBSD
|
||||||
int size, align, nregs;
|
int size, align, nregs;
|
||||||
|
@ -370,6 +311,10 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int
|
||||||
ret->ref = NULL;
|
ret->ref = NULL;
|
||||||
return nregs;
|
return nregs;
|
||||||
#else
|
#else
|
||||||
|
(void)vt;
|
||||||
|
(void)variadic;
|
||||||
|
(void)ret;
|
||||||
|
(void)regsize;
|
||||||
*ret_align = 1; // Never have to re-align return values for x86
|
*ret_align = 1; // Never have to re-align return values for x86
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -378,7 +323,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int
|
||||||
/* Generate function call. The function address is pushed first, then
|
/* Generate function call. The function address is pushed first, then
|
||||||
all the parameters in call order. This functions pops all the
|
all the parameters in call order. This functions pops all the
|
||||||
parameters and the function address. */
|
parameters and the function address. */
|
||||||
ST_FUNC void gfunc_call(int nb_args)
|
void gfunc_call(int nb_args)
|
||||||
{
|
{
|
||||||
int size, align, r, args_size, i, func_call;
|
int size, align, r, args_size, i, func_call;
|
||||||
Sym *func_sym;
|
Sym *func_sym;
|
||||||
|
@ -488,7 +433,7 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* generate function prolog of type 't' */
|
/* generate function prolog of type 't' */
|
||||||
ST_FUNC void gfunc_prolog(Sym *func_sym)
|
void gfunc_prolog(Sym *func_sym)
|
||||||
{
|
{
|
||||||
CType *func_type = &func_sym->type;
|
CType *func_type = &func_sym->type;
|
||||||
int addr, align, size, func_call, fastcall_nb_regs;
|
int addr, align, size, func_call, fastcall_nb_regs;
|
||||||
|
@ -571,7 +516,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate function epilog */
|
/* generate function epilog */
|
||||||
ST_FUNC void gfunc_epilog(void)
|
void gfunc_epilog(void)
|
||||||
{
|
{
|
||||||
addr_t v, saved_ind;
|
addr_t v, saved_ind;
|
||||||
|
|
||||||
|
@ -612,13 +557,13 @@ ST_FUNC void gfunc_epilog(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate a jump to a label */
|
/* generate a jump to a label */
|
||||||
ST_FUNC int gjmp(int t)
|
int gjmp(int t)
|
||||||
{
|
{
|
||||||
return gjmp2(0xe9, t);
|
return gjmp2(0xe9, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate a jump to a fixed address */
|
/* generate a jump to a fixed address */
|
||||||
ST_FUNC void gjmp_addr(int a)
|
void gjmp_addr(int a)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
r = a - ind - 2;
|
r = a - ind - 2;
|
||||||
|
@ -632,7 +577,7 @@ ST_FUNC void gjmp_addr(int a)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* generate a jump to a fixed address */
|
/* generate a jump to a fixed address */
|
||||||
ST_FUNC void gjmp_cond_addr(int a, int op)
|
void gjmp_cond_addr(int a, int op)
|
||||||
{
|
{
|
||||||
int r = a - ind - 2;
|
int r = a - ind - 2;
|
||||||
if (r == (char)r)
|
if (r == (char)r)
|
||||||
|
@ -642,7 +587,7 @@ ST_FUNC void gjmp_cond_addr(int a, int op)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ST_FUNC int gjmp_append(int n, int t)
|
int gjmp_append(int n, int t)
|
||||||
{
|
{
|
||||||
void *p;
|
void *p;
|
||||||
/* insert vtop->c jump list in t */
|
/* insert vtop->c jump list in t */
|
||||||
|
@ -656,14 +601,14 @@ ST_FUNC int gjmp_append(int n, int t)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int gjmp_cond(int op, int t)
|
int gjmp_cond(int op, int t)
|
||||||
{
|
{
|
||||||
g(0x0f);
|
g(0x0f);
|
||||||
t = gjmp2(op - 16, t);
|
t = gjmp2(op - 16, t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_opi(int op)
|
void gen_opi(int op)
|
||||||
{
|
{
|
||||||
int r, fr, opc, c;
|
int r, fr, opc, c;
|
||||||
|
|
||||||
|
@ -802,7 +747,7 @@ ST_FUNC void gen_opi(int op)
|
||||||
/* generate a floating point operation 'v = t1 op t2' instruction. The
|
/* generate a floating point operation 'v = t1 op t2' instruction. The
|
||||||
two operands are guaranteed to have the same floating point type */
|
two operands are guaranteed to have the same floating point type */
|
||||||
/* XXX: need to use ST1 too */
|
/* XXX: need to use ST1 too */
|
||||||
ST_FUNC void gen_opf(int op)
|
void gen_opf(int op)
|
||||||
{
|
{
|
||||||
int a, ft, fc, swapped, r;
|
int a, ft, fc, swapped, r;
|
||||||
|
|
||||||
|
@ -923,7 +868,7 @@ ST_FUNC void gen_opf(int op)
|
||||||
|
|
||||||
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
|
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
|
||||||
and 'long long' cases. */
|
and 'long long' cases. */
|
||||||
ST_FUNC void gen_cvt_itof(int t)
|
void gen_cvt_itof(void)
|
||||||
{
|
{
|
||||||
save_reg(TREG_ST0);
|
save_reg(TREG_ST0);
|
||||||
gv(RC_INT);
|
gv(RC_INT);
|
||||||
|
@ -954,7 +899,7 @@ ST_FUNC void gen_cvt_itof(int t)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert fp to int 't' type */
|
/* convert fp to int 't' type */
|
||||||
ST_FUNC void gen_cvt_ftoi(int t)
|
void gen_cvt_ftoi(int t)
|
||||||
{
|
{
|
||||||
int bt = vtop->type.t & VT_BTYPE;
|
int bt = vtop->type.t & VT_BTYPE;
|
||||||
if (bt == VT_FLOAT)
|
if (bt == VT_FLOAT)
|
||||||
|
@ -972,14 +917,14 @@ ST_FUNC void gen_cvt_ftoi(int t)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert from one floating point type to another */
|
/* convert from one floating point type to another */
|
||||||
ST_FUNC void gen_cvt_ftof(int t)
|
void gen_cvt_ftof(void)
|
||||||
{
|
{
|
||||||
/* all we have to do on i386 is to put the float in a register */
|
/* all we have to do on i386 is to put the float in a register */
|
||||||
gv(RC_FLOAT);
|
gv(RC_FLOAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* char/short to int conversion */
|
/* char/short to int conversion */
|
||||||
ST_FUNC void gen_cvt_csti(int t)
|
void gen_cvt_csti(int t)
|
||||||
{
|
{
|
||||||
int r, sz, xl;
|
int r, sz, xl;
|
||||||
r = gv(RC_INT);
|
r = gv(RC_INT);
|
||||||
|
@ -992,7 +937,7 @@ ST_FUNC void gen_cvt_csti(int t)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* increment tcov counter */
|
/* increment tcov counter */
|
||||||
ST_FUNC void gen_increment_tcov (SValue *sv)
|
void gen_increment_tcov (SValue *sv)
|
||||||
{
|
{
|
||||||
o(0x0583); /* addl $1, xxx */
|
o(0x0583); /* addl $1, xxx */
|
||||||
greloc(cur_text_section, sv->sym, ind, R_386_32);
|
greloc(cur_text_section, sv->sym, ind, R_386_32);
|
||||||
|
@ -1005,27 +950,27 @@ ST_FUNC void gen_increment_tcov (SValue *sv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* computed goto support */
|
/* computed goto support */
|
||||||
ST_FUNC void ggoto(void)
|
void ggoto(void)
|
||||||
{
|
{
|
||||||
gcall_or_jmp(1);
|
gcall_or_jmp(1);
|
||||||
vtop--;
|
vtop--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the stack pointer onto the stack */
|
/* Save the stack pointer onto the stack */
|
||||||
ST_FUNC void gen_vla_sp_save(int addr) {
|
void gen_vla_sp_save(int addr) {
|
||||||
/* mov %esp,addr(%ebp)*/
|
/* mov %esp,addr(%ebp)*/
|
||||||
o(0x89);
|
o(0x89);
|
||||||
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
|
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore the SP from a location on the stack */
|
/* Restore the SP from a location on the stack */
|
||||||
ST_FUNC void gen_vla_sp_restore(int addr) {
|
void gen_vla_sp_restore(int addr) {
|
||||||
o(0x8b);
|
o(0x8b);
|
||||||
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
|
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Subtract from the stack pointer, and push the resulting value onto the stack */
|
/* Subtract from the stack pointer, and push the resulting value onto the stack */
|
||||||
ST_FUNC void gen_vla_alloc(CType *type, int align) {
|
void gen_vla_alloc(CType *type, int align) {
|
||||||
int use_call = 0;
|
int use_call = 0;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */
|
#ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */
|
||||||
|
@ -1051,6 +996,3 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end of X86 code generator */
|
/* end of X86 code generator */
|
||||||
/*************************************************************/
|
|
||||||
#endif
|
|
||||||
/*************************************************************/
|
|
||||||
|
|
|
@ -1,31 +1,9 @@
|
||||||
#ifdef TARGET_DEFS_ONLY
|
#include <tcc.h>
|
||||||
|
|
||||||
#define EM_TCC_TARGET EM_386
|
|
||||||
|
|
||||||
/* relocation type for 32 bit data relocation */
|
|
||||||
#define R_DATA_32 R_386_32
|
|
||||||
#define R_DATA_PTR R_386_32
|
|
||||||
#define R_JMP_SLOT R_386_JMP_SLOT
|
|
||||||
#define R_GLOB_DAT R_386_GLOB_DAT
|
|
||||||
#define R_COPY R_386_COPY
|
|
||||||
#define R_RELATIVE R_386_RELATIVE
|
|
||||||
|
|
||||||
#define R_NUM R_386_NUM
|
|
||||||
|
|
||||||
#define ELF_START_ADDR 0x08048000
|
|
||||||
#define ELF_PAGE_SIZE 0x1000
|
|
||||||
|
|
||||||
#define PCRELATIVE_DLLPLT 0
|
|
||||||
#define RELOCATE_DLLPLT 1
|
|
||||||
|
|
||||||
#else /* !TARGET_DEFS_ONLY */
|
|
||||||
|
|
||||||
#include "tcc.h"
|
|
||||||
|
|
||||||
#ifdef NEED_RELOC_TYPE
|
#ifdef NEED_RELOC_TYPE
|
||||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||||
relocations, returns -1. */
|
relocations, returns -1. */
|
||||||
ST_FUNC int code_reloc (int reloc_type)
|
int code_reloc (int reloc_type)
|
||||||
{
|
{
|
||||||
switch (reloc_type) {
|
switch (reloc_type) {
|
||||||
case R_386_RELATIVE:
|
case R_386_RELATIVE:
|
||||||
|
@ -55,7 +33,7 @@ ST_FUNC int code_reloc (int reloc_type)
|
||||||
/* Returns an enumerator to describe whether and when the relocation needs a
|
/* Returns an enumerator to describe whether and when the relocation needs a
|
||||||
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||||
different values. */
|
different values. */
|
||||||
ST_FUNC int gotplt_entry_type (int reloc_type)
|
int gotplt_entry_type (int reloc_type)
|
||||||
{
|
{
|
||||||
switch (reloc_type) {
|
switch (reloc_type) {
|
||||||
case R_386_RELATIVE:
|
case R_386_RELATIVE:
|
||||||
|
@ -92,7 +70,7 @@ ST_FUNC int gotplt_entry_type (int reloc_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NEED_BUILD_GOT
|
#ifdef NEED_BUILD_GOT
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
||||||
{
|
{
|
||||||
Section *plt = s1->plt;
|
Section *plt = s1->plt;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
|
@ -134,7 +112,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
||||||
|
|
||||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||||
address for PLT and GOT are known (see fill_program_header) */
|
address for PLT and GOT are known (see fill_program_header) */
|
||||||
ST_FUNC void relocate_plt(TCCState *s1)
|
void relocate_plt(TCCState *s1)
|
||||||
{
|
{
|
||||||
uint8_t *p, *p_end;
|
uint8_t *p, *p_end;
|
||||||
|
|
||||||
|
@ -167,9 +145,9 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
{
|
{
|
||||||
int sym_index, esym_index;
|
int sym_index;
|
||||||
|
|
||||||
sym_index = ELFW(R_SYM)(rel->r_info);
|
sym_index = ELFW(R_SYM)(rel->r_info);
|
||||||
|
|
||||||
|
@ -295,5 +273,3 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !TARGET_DEFS_ONLY */
|
|
||||||
|
|
|
@ -266,7 +266,7 @@
|
||||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||||
#include "asm.h"
|
#include "asm.inc"
|
||||||
|
|
||||||
#define ALT(x)
|
#define ALT(x)
|
||||||
#define DEF_ASM_OP0(name, opcode)
|
#define DEF_ASM_OP0(name, opcode)
|
||||||
|
@ -274,4 +274,4 @@
|
||||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
|
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
|
||||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
|
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
|
||||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
|
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
|
||||||
#include "asm.h"
|
#include "asm.inc"
|
File diff suppressed because it is too large
Load diff
60
libtcc/include/tcc/i386/gen.h
Normal file
60
libtcc/include/tcc/i386/gen.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#ifndef TCC_I386_GEN_H
|
||||||
|
# define TCC_I386_GEN_H 1
|
||||||
|
|
||||||
|
/* number of available registers */
|
||||||
|
# define NB_REGS 5
|
||||||
|
# define NB_ASM_REGS 8
|
||||||
|
|
||||||
|
/* a register can belong to several classes. The classes must be
|
||||||
|
sorted from more general to more precise (see gv2() code which does
|
||||||
|
assumptions on it). */
|
||||||
|
# define RC_INT 0x0001 /* generic integer register */
|
||||||
|
# define RC_FLOAT 0x0002 /* generic float register */
|
||||||
|
# define RC_EAX 0x0004
|
||||||
|
# define RC_EDX 0x0008
|
||||||
|
# define RC_ECX 0x0010
|
||||||
|
# define RC_EBX 0x0020
|
||||||
|
# define RC_ST0 0x0040
|
||||||
|
|
||||||
|
# define RC_IRET RC_EAX /* function return: integer register */
|
||||||
|
# define RC_IRE2 RC_EDX /* function return: second integer register */
|
||||||
|
# define RC_FRET RC_ST0 /* function return: float register */
|
||||||
|
|
||||||
|
/* pretty names for the registers */
|
||||||
|
enum {
|
||||||
|
TREG_EAX = 0,
|
||||||
|
TREG_ECX,
|
||||||
|
TREG_EDX,
|
||||||
|
TREG_EBX,
|
||||||
|
TREG_ST0,
|
||||||
|
TREG_ESP = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
/* return registers for function */
|
||||||
|
# define REG_IRET TREG_EAX /* single word int return register */
|
||||||
|
# define REG_IRE2 TREG_EDX /* second word return register (for long long) */
|
||||||
|
# define REG_FRET TREG_ST0 /* float return register */
|
||||||
|
|
||||||
|
/* defined if function parameters must be evaluated in reverse order */
|
||||||
|
# define INVERT_FUNC_PARAMS
|
||||||
|
|
||||||
|
/* defined if structures are passed as pointers. Otherwise structures
|
||||||
|
are directly pushed on stack. */
|
||||||
|
/* #define FUNC_STRUCT_PARAM_AS_PTR */
|
||||||
|
|
||||||
|
/* pointer size, in bytes */
|
||||||
|
# define PTR_SIZE 4
|
||||||
|
|
||||||
|
/* long double size and alignment, in bytes */
|
||||||
|
# define LDOUBLE_SIZE 12
|
||||||
|
# define LDOUBLE_ALIGN 4
|
||||||
|
/* maximum alignment (for aligned attribute support) */
|
||||||
|
# define MAX_ALIGN 8
|
||||||
|
|
||||||
|
/* define if return values need to be extended explicitely
|
||||||
|
at caller side (for interfacing with non-TCC compilers) */
|
||||||
|
# define PROMOTE_RET
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !TCC_I386_GEN_H */
|
20
libtcc/include/tcc/i386/link.h
Normal file
20
libtcc/include/tcc/i386/link.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef TCC_I386_LINK_H
|
||||||
|
# define TCC_I386_LINK_H 1
|
||||||
|
|
||||||
|
/* relocation type for 32 bit data relocation */
|
||||||
|
# define R_DATA_32 R_386_32
|
||||||
|
# define R_DATA_PTR R_386_32
|
||||||
|
# define R_JMP_SLOT R_386_JMP_SLOT
|
||||||
|
# define R_GLOB_DAT R_386_GLOB_DAT
|
||||||
|
# define R_COPY R_386_COPY
|
||||||
|
# define R_RELATIVE R_386_RELATIVE
|
||||||
|
|
||||||
|
# define R_NUM R_386_NUM
|
||||||
|
|
||||||
|
# define ELF_START_ADDR 0x08048000
|
||||||
|
# define ELF_PAGE_SIZE 0x1000
|
||||||
|
|
||||||
|
# define PCRELATIVE_DLLPLT 0
|
||||||
|
# define RELOCATE_DLLPLT 1
|
||||||
|
|
||||||
|
#endif /* !TCC_I386_LINK_H */
|
25
libtcc/include/tcc/option.h
Normal file
25
libtcc/include/tcc/option.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef LIBTCC_OPTION_H
|
||||||
|
# define LIBTCC_OPTION_H 1
|
||||||
|
|
||||||
|
# include <stdint.h>
|
||||||
|
|
||||||
|
# define TCC_OPTION_HAS_ARG 0x0001
|
||||||
|
# define TCC_OPTION_NOSEP 0x0002 /** cannot have space before option and arg */
|
||||||
|
|
||||||
|
# define TCC_OPT_HELP 'h'
|
||||||
|
# define TCC_OPT_HELP_MORE 'm'
|
||||||
|
# define TCC_OPT_ARCHIVE 'a'
|
||||||
|
# define TCC_OPT_VERSION 'V'
|
||||||
|
|
||||||
|
typedef struct TCCOption {
|
||||||
|
const char *name;
|
||||||
|
uint16_t index;
|
||||||
|
uint16_t flags;
|
||||||
|
} TCCOption;
|
||||||
|
|
||||||
|
typedef struct TCCState TCCState;
|
||||||
|
|
||||||
|
int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
|
||||||
|
void tcc_add_options(TCCOption *opts);
|
||||||
|
|
||||||
|
#endif /* LIBTCC_OPTION_H */
|
120
libtcc/libtcc.c
120
libtcc/libtcc.c
|
@ -25,15 +25,15 @@
|
||||||
/* global variables */
|
/* global variables */
|
||||||
|
|
||||||
/* XXX: get rid of this ASAP (or maybe not) */
|
/* XXX: get rid of this ASAP (or maybe not) */
|
||||||
ST_DATA struct TCCState *tcc_state;
|
struct TCCState *tcc_state;
|
||||||
TCC_SEM(static tcc_compile_sem);
|
TCC_SEM(static tcc_compile_sem);
|
||||||
/* an array of pointers to memory to be free'd after errors */
|
/* an array of pointers to memory to be free'd after errors */
|
||||||
ST_DATA void** stk_data;
|
void** stk_data;
|
||||||
ST_DATA int nb_stk_data;
|
int nb_stk_data;
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
ST_FUNC char *normalize_slashes(char *path)
|
char *normalize_slashes(char *path)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
for (p = path; *p; ++p)
|
for (p = path; *p; ++p)
|
||||||
|
@ -99,7 +99,7 @@ PUB_FUNC char *tcc_fileextension (const char *name)
|
||||||
return e ? e : strchr(b, 0);
|
return e ? e : strchr(b, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC char *tcc_load_text(int fd)
|
char *tcc_load_text(int fd)
|
||||||
{
|
{
|
||||||
int len = lseek(fd, 0, SEEK_END);
|
int len = lseek(fd, 0, SEEK_END);
|
||||||
char *buf = load_data(fd, 0, len + 1);
|
char *buf = load_data(fd, 0, len + 1);
|
||||||
|
@ -111,10 +111,6 @@ ST_FUNC char *tcc_load_text(int fd)
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
/* memory management */
|
/* memory management */
|
||||||
|
|
||||||
/* we'll need the actual versions for a minute */
|
|
||||||
#undef free
|
|
||||||
#undef realloc
|
|
||||||
|
|
||||||
static void *default_reallocator(void *ptr, unsigned long size)
|
static void *default_reallocator(void *ptr, unsigned long size)
|
||||||
{
|
{
|
||||||
void *ptr1;
|
void *ptr1;
|
||||||
|
@ -132,14 +128,6 @@ static void *default_reallocator(void *ptr, unsigned long size)
|
||||||
return ptr1;
|
return ptr1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void libc_free(void *ptr)
|
|
||||||
{
|
|
||||||
free(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define free(p) use_tcc_free(p)
|
|
||||||
#define realloc(p, s) use_tcc_realloc(p, s)
|
|
||||||
|
|
||||||
/* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */
|
/* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */
|
||||||
static void *(*reallocator)(void*, unsigned long) = default_reallocator;
|
static void *(*reallocator)(void*, unsigned long) = default_reallocator;
|
||||||
|
|
||||||
|
@ -208,7 +196,7 @@ struct mem_debug_header {
|
||||||
int line_num;
|
int line_num;
|
||||||
char file_name[MEM_DEBUG_FILE_LEN + 1];
|
char file_name[MEM_DEBUG_FILE_LEN + 1];
|
||||||
unsigned magic2;
|
unsigned magic2;
|
||||||
ALIGNED(16) unsigned char magic3[4];
|
__attribute__((aligned(16))) unsigned char magic3[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct mem_debug_header mem_debug_header_t;
|
typedef struct mem_debug_header mem_debug_header_t;
|
||||||
|
@ -369,16 +357,16 @@ PUB_FUNC void tcc_memcheck(int d)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* for #pragma once */
|
/* for #pragma once */
|
||||||
ST_FUNC int normalized_PATHCMP(const char *f1, const char *f2)
|
int normalized_PATHCMP(const char *f1, const char *f2)
|
||||||
{
|
{
|
||||||
char *p1, *p2;
|
char *p1, *p2;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
if (!!(p1 = realpath(f1, NULL))) {
|
if (!!(p1 = realpath(f1, NULL))) {
|
||||||
if (!!(p2 = realpath(f2, NULL))) {
|
if (!!(p2 = realpath(f2, NULL))) {
|
||||||
ret = PATHCMP(p1, p2);
|
ret = PATHCMP(p1, p2);
|
||||||
libc_free(p2); /* realpath() requirement */
|
free(p2); /* realpath() requirement */
|
||||||
}
|
}
|
||||||
libc_free(p1);
|
free(p1);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -386,7 +374,7 @@ ST_FUNC int normalized_PATHCMP(const char *f1, const char *f2)
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
/* dynarrays */
|
/* dynarrays */
|
||||||
|
|
||||||
ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data)
|
void dynarray_add(void *ptab, int *nb_ptr, void *data)
|
||||||
{
|
{
|
||||||
int nb, nb_alloc;
|
int nb, nb_alloc;
|
||||||
void **pp;
|
void **pp;
|
||||||
|
@ -406,7 +394,7 @@ ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data)
|
||||||
*nb_ptr = nb;
|
*nb_ptr = nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void dynarray_reset(void *pp, int *n)
|
void dynarray_reset(void *pp, int *n)
|
||||||
{
|
{
|
||||||
void **p;
|
void **p;
|
||||||
for (p = *(void***)pp; *n; ++p, --*n)
|
for (p = *(void***)pp; *n; ++p, --*n)
|
||||||
|
@ -575,7 +563,7 @@ PUB_FUNC void _tcc_warning(const char *fmt, ...)
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
/* I/O layer */
|
/* I/O layer */
|
||||||
|
|
||||||
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
|
void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
|
||||||
{
|
{
|
||||||
BufferedFile *bf;
|
BufferedFile *bf;
|
||||||
int buflen = initlen ? initlen : IO_BUF_SIZE;
|
int buflen = initlen ? initlen : IO_BUF_SIZE;
|
||||||
|
@ -598,7 +586,7 @@ ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
|
||||||
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tcc_close(void)
|
void tcc_close(void)
|
||||||
{
|
{
|
||||||
TCCState *s1 = tcc_state;
|
TCCState *s1 = tcc_state;
|
||||||
BufferedFile *bf = file;
|
BufferedFile *bf = file;
|
||||||
|
@ -626,7 +614,7 @@ static int _tcc_open(TCCState *s1, const char *filename)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int tcc_open(TCCState *s1, const char *filename)
|
int tcc_open(TCCState *s1, const char *filename)
|
||||||
{
|
{
|
||||||
int fd = _tcc_open(s1, filename);
|
int fd = _tcc_open(s1, filename);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
|
@ -755,8 +743,7 @@ void tcc_delete(TCCState *s1)
|
||||||
dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
|
dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
|
||||||
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
|
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
|
||||||
|
|
||||||
tcc_free(s1->tcc_lib_path);
|
tcc_free(s1->tcc_lib_path);;
|
||||||
tcc_free(s1->soname);
|
|
||||||
tcc_free(s1->rpath);
|
tcc_free(s1->rpath);
|
||||||
tcc_free(s1->elf_entryname);
|
tcc_free(s1->elf_entryname);
|
||||||
tcc_free(s1->init_symbol);
|
tcc_free(s1->init_symbol);
|
||||||
|
@ -771,8 +758,6 @@ void tcc_delete(TCCState *s1)
|
||||||
cstr_free(&s1->cmdline_defs);
|
cstr_free(&s1->cmdline_defs);
|
||||||
cstr_free(&s1->cmdline_incl);
|
cstr_free(&s1->cmdline_incl);
|
||||||
cstr_free(&s1->linker_arg);
|
cstr_free(&s1->linker_arg);
|
||||||
/* free loaded dlls array */
|
|
||||||
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
|
|
||||||
tcc_free(s1);
|
tcc_free(s1);
|
||||||
#ifdef MEM_DEBUG
|
#ifdef MEM_DEBUG
|
||||||
tcc_memcheck(-1);
|
tcc_memcheck(-1);
|
||||||
|
@ -823,35 +808,9 @@ int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add/update a 'DLLReference', Just find if level == -1 */
|
|
||||||
ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level)
|
|
||||||
{
|
|
||||||
DLLReference *ref = NULL;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < s1->nb_loaded_dlls; i++)
|
|
||||||
if (0 == strcmp(s1->loaded_dlls[i]->name, dllname)) {
|
|
||||||
ref = s1->loaded_dlls[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (level == -1)
|
|
||||||
return ref;
|
|
||||||
if (ref) {
|
|
||||||
if (level < ref->level)
|
|
||||||
ref->level = level;
|
|
||||||
ref->found = 1;
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
ref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
|
|
||||||
strcpy(ref->name, dllname);
|
|
||||||
dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, ref);
|
|
||||||
ref->level = level;
|
|
||||||
ref->index = s1->nb_loaded_dlls;
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int guess_filetype(const char *filename);
|
static int guess_filetype(const char *filename);
|
||||||
|
|
||||||
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
{
|
{
|
||||||
int fd, ret = -1;
|
int fd, ret = -1;
|
||||||
|
|
||||||
|
@ -893,12 +852,6 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
ret = coff_load_file(s1, fd, filename);
|
ret = coff_load_file(s1, fd, filename);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AFF_BINTYPE_DYN:
|
|
||||||
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
|
||||||
} else
|
|
||||||
ret = tcc_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* as GNU ld, consider it is an ld script if not recognized */
|
/* as GNU ld, consider it is an ld script if not recognized */
|
||||||
ret = tcc_load_ldscript(s1, fd);
|
ret = tcc_load_ldscript(s1, fd);
|
||||||
|
@ -970,14 +923,14 @@ static int tcc_add_library_internal(TCCState *s1, const char *fmt,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find and load a dll. Return non zero if not found */
|
/* find and load a dll. Return non zero if not found */
|
||||||
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
|
int tcc_add_dll(TCCState *s, const char *filename, int flags)
|
||||||
{
|
{
|
||||||
return tcc_add_library_internal(s, "%s/%s", filename, flags,
|
return tcc_add_library_internal(s, "%s/%s", filename, flags,
|
||||||
s->library_paths, s->nb_library_paths);
|
s->library_paths, s->nb_library_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find [cross-]libtcc1.a and tcc helper objects in library path */
|
/* find [cross-]libtcc1.a and tcc helper objects in library path */
|
||||||
ST_FUNC int tcc_add_support(TCCState *s1, const char *filename)
|
int tcc_add_support(TCCState *s1, const char *filename)
|
||||||
{
|
{
|
||||||
char buf[100];
|
char buf[100];
|
||||||
if (CONFIG_TCC_CROSSPREFIX[0])
|
if (CONFIG_TCC_CROSSPREFIX[0])
|
||||||
|
@ -985,13 +938,11 @@ ST_FUNC int tcc_add_support(TCCState *s1, const char *filename)
|
||||||
return tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
|
return tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined TCC_TARGET_PE
|
int tcc_add_crt(TCCState *s1, const char *filename)
|
||||||
ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
|
|
||||||
{
|
{
|
||||||
return tcc_add_library_internal(s1, "%s/%s",
|
return tcc_add_library_internal(s1, "%s/%s",
|
||||||
filename, AFF_PRINT_ERROR, s1->crt_paths, s1->nb_crt_paths);
|
filename, AFF_PRINT_ERROR, s1->crt_paths, s1->nb_crt_paths);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* the library name is the same as the argument of the '-l' option */
|
/* the library name is the same as the argument of the '-l' option */
|
||||||
int tcc_add_library(TCCState *s, const char *libraryname)
|
int tcc_add_library(TCCState *s, const char *libraryname)
|
||||||
|
@ -1010,7 +961,7 @@ int tcc_add_library(TCCState *s, const char *libraryname)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle #pragma comment(lib,) */
|
/* handle #pragma comment(lib,) */
|
||||||
ST_FUNC void tcc_add_pragma_libs(TCCState *s1)
|
void tcc_add_pragma_libs(TCCState *s1)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < s1->nb_pragma_libs; i++)
|
for (i = 0; i < s1->nb_pragma_libs; i++)
|
||||||
|
@ -1184,20 +1135,12 @@ static int tcc_set_linker(TCCState *s, const char *option)
|
||||||
ignoring = 1;
|
ignoring = 1;
|
||||||
} else if (link_option(option, "O", &p)) {
|
} else if (link_option(option, "O", &p)) {
|
||||||
ignoring = 1;
|
ignoring = 1;
|
||||||
} else if (link_option(option, "export-all-symbols", &p)) {
|
|
||||||
s->rdynamic = 1;
|
|
||||||
} else if (link_option(option, "export-dynamic", &p)) {
|
|
||||||
s->rdynamic = 1;
|
|
||||||
} else if (link_option(option, "rpath=", &p)) {
|
} else if (link_option(option, "rpath=", &p)) {
|
||||||
copy_linker_arg(&s->rpath, p, ':');
|
copy_linker_arg(&s->rpath, p, ':');
|
||||||
} else if (link_option(option, "enable-new-dtags", &p)) {
|
} else if (link_option(option, "enable-new-dtags", &p)) {
|
||||||
s->enable_new_dtags = 1;
|
s->enable_new_dtags = 1;
|
||||||
} else if (link_option(option, "section-alignment=", &p)) {
|
} else if (link_option(option, "section-alignment=", &p)) {
|
||||||
s->section_align = strtoul(p, &end, 16);
|
s->section_align = strtoul(p, &end, 16);
|
||||||
} else if (link_option(option, "soname=", &p)) {
|
|
||||||
copy_linker_arg(&s->soname, p, 0);
|
|
||||||
} else if (link_option(option, "install_name=", &p)) {
|
|
||||||
copy_linker_arg(&s->soname, p, 0);
|
|
||||||
} else if (ret = link_option(option, "?whole-archive", &p), ret) {
|
} else if (ret = link_option(option, "?whole-archive", &p), ret) {
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
s->filetype |= AFF_WHOLE_ARCHIVE;
|
s->filetype |= AFF_WHOLE_ARCHIVE;
|
||||||
|
@ -1308,10 +1251,7 @@ static const TCCOption tcc_options[] = {
|
||||||
{ "dumpmachine", TCC_OPTION_dumpmachine, 0},
|
{ "dumpmachine", TCC_OPTION_dumpmachine, 0},
|
||||||
{ "dumpversion", TCC_OPTION_dumpversion, 0},
|
{ "dumpversion", TCC_OPTION_dumpversion, 0},
|
||||||
{ "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
{ "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||||
{ "static", TCC_OPTION_static, 0 },
|
|
||||||
{ "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
{ "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||||
{ "shared", TCC_OPTION_shared, 0 },
|
|
||||||
{ "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
|
{ "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
|
||||||
{ "pthread", TCC_OPTION_pthread, 0},
|
{ "pthread", TCC_OPTION_pthread, 0},
|
||||||
{ "rdynamic", TCC_OPTION_rdynamic, 0 },
|
{ "rdynamic", TCC_OPTION_rdynamic, 0 },
|
||||||
|
@ -1346,6 +1286,9 @@ static const TCCOption tcc_options[] = {
|
||||||
{ "pipe", 0, 0 },
|
{ "pipe", 0, 0 },
|
||||||
{ "s", 0, 0 },
|
{ "s", 0, 0 },
|
||||||
{ "traditional", 0, 0 },
|
{ "traditional", 0, 0 },
|
||||||
|
{ "static", 0, 0},
|
||||||
|
{ "shared", 0, 0},
|
||||||
|
{ "soname", 0, 0},
|
||||||
{ NULL, 0, 0 },
|
{ NULL, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1591,21 +1534,13 @@ dorun:
|
||||||
s->dflag = 3;
|
s->dflag = 3;
|
||||||
else if (*optarg == 'M')
|
else if (*optarg == 'M')
|
||||||
s->dflag = 7;
|
s->dflag = 7;
|
||||||
else if (isnum(*optarg))
|
|
||||||
s->g_debug |= atoi(optarg);
|
|
||||||
else
|
else
|
||||||
goto unsupported_option;
|
goto unsupported_option;
|
||||||
break;
|
break;
|
||||||
case TCC_OPTION_static:
|
|
||||||
s->static_link = 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_std:
|
case TCC_OPTION_std:
|
||||||
if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0)
|
if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0)
|
||||||
s->cversion = 201112;
|
s->cversion = 201112;
|
||||||
break;
|
break;
|
||||||
case TCC_OPTION_soname:
|
|
||||||
s->soname = tcc_strdup(optarg);
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_o:
|
case TCC_OPTION_o:
|
||||||
if (s->outfile) {
|
if (s->outfile) {
|
||||||
tcc_warning("multiple -o option");
|
tcc_warning("multiple -o option");
|
||||||
|
@ -1655,9 +1590,6 @@ dorun:
|
||||||
case TCC_OPTION_w:
|
case TCC_OPTION_w:
|
||||||
s->warn_none = 1;
|
s->warn_none = 1;
|
||||||
break;
|
break;
|
||||||
case TCC_OPTION_rdynamic:
|
|
||||||
s->rdynamic = 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_Wl:
|
case TCC_OPTION_Wl:
|
||||||
if (s->linker_arg.size)
|
if (s->linker_arg.size)
|
||||||
((char*)s->linker_arg.data)[s->linker_arg.size - 1] = ',';
|
((char*)s->linker_arg.data)[s->linker_arg.size - 1] = ',';
|
||||||
|
@ -1789,9 +1721,3 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)
|
||||||
fprintf(stderr, " %d max (bytes)\n", mem_max_size);
|
fprintf(stderr, " %d max (bytes)\n", mem_max_size);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ONE_SOURCE
|
|
||||||
# undef malloc
|
|
||||||
# undef realloc
|
|
||||||
# undef free
|
|
||||||
#endif
|
|
||||||
|
|
113
libtcc/option.c
113
libtcc/option.c
|
@ -1,2 +1,113 @@
|
||||||
#include "tcc.h"
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <tcc/option.h>
|
||||||
|
#include "utils/cstr.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
OPTION_ignored = 0,
|
||||||
|
OPTION_I,
|
||||||
|
OPTION_D,
|
||||||
|
OPTION_U,
|
||||||
|
OPTION_P,
|
||||||
|
OPTION_L,
|
||||||
|
OPTION_B,
|
||||||
|
OPTION_l,
|
||||||
|
OPTION_bench,
|
||||||
|
OPTION_c,
|
||||||
|
OPTION_dumpmachine,
|
||||||
|
OPTION_dumpversion,
|
||||||
|
OPTION_d,
|
||||||
|
OPTION_std,
|
||||||
|
OPTION_o,
|
||||||
|
OPTION_pthread,
|
||||||
|
OPTION_r,
|
||||||
|
OPTION_Wl,
|
||||||
|
OPTION_Wp,
|
||||||
|
OPTION_W,
|
||||||
|
OPTION_O,
|
||||||
|
OPTION_m,
|
||||||
|
OPTION_f,
|
||||||
|
OPTION_isystem,
|
||||||
|
OPTION_include,
|
||||||
|
OPTION_nostdinc,
|
||||||
|
OPTION_nostdlib,
|
||||||
|
OPTION_print_search_dirs,
|
||||||
|
OPTION_w,
|
||||||
|
OPTION_E,
|
||||||
|
OPTION_M,
|
||||||
|
OPTION_MF,
|
||||||
|
OPTION_MD,
|
||||||
|
OPTION_MM,
|
||||||
|
OPTION_MMD,
|
||||||
|
OPTION_MP,
|
||||||
|
OPTION_x,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const TCCOption options[] = {
|
||||||
|
{"I", OPTION_I, TCC_OPTION_HAS_ARG},
|
||||||
|
{"D", OPTION_D, TCC_OPTION_HAS_ARG},
|
||||||
|
{"U", OPTION_U, TCC_OPTION_HAS_ARG},
|
||||||
|
{"P", OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
|
{"L", OPTION_L, TCC_OPTION_HAS_ARG},
|
||||||
|
{"B", OPTION_B, TCC_OPTION_HAS_ARG},
|
||||||
|
{"l", OPTION_l, TCC_OPTION_HAS_ARG},
|
||||||
|
{"bench", OPTION_bench, 0},
|
||||||
|
{"c", OPTION_c, 0},
|
||||||
|
{"dumpmachine", OPTION_dumpmachine, 0},
|
||||||
|
{"dumpversion", OPTION_dumpversion, 0},
|
||||||
|
{"d", OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
|
{"std", OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
|
{"o", OPTION_o, TCC_OPTION_HAS_ARG},
|
||||||
|
{"pthread", OPTION_pthread, 0},
|
||||||
|
{"r", OPTION_r, 0},
|
||||||
|
{"Wl", OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
|
{"Wp", OPTION_Wp, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
|
{"W", OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
|
{"O", OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
|
{"m", OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
|
{"f", OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
|
{"isystem", OPTION_isystem, TCC_OPTION_HAS_ARG},
|
||||||
|
{"include", OPTION_include, TCC_OPTION_HAS_ARG},
|
||||||
|
{"nostdinc", OPTION_nostdinc, 0},
|
||||||
|
{"nostdlib", OPTION_nostdlib, 0},
|
||||||
|
{"print-search-dirs", OPTION_print_search_dirs, 0},
|
||||||
|
{"w", OPTION_w, 0},
|
||||||
|
{"E", OPTION_E, 0},
|
||||||
|
{"M", OPTION_M, 0},
|
||||||
|
{"MD", OPTION_MD, 0},
|
||||||
|
{"MF", OPTION_MF, TCC_OPTION_HAS_ARG},
|
||||||
|
{"MM", OPTION_MM, 0},
|
||||||
|
{"MMD", OPTION_MMD, 0},
|
||||||
|
{"MP", OPTION_MP, 0},
|
||||||
|
{"x", OPTION_x, 0},
|
||||||
|
|
||||||
|
/* ignored (silently, except after -Wunsupported) */
|
||||||
|
{"arch", 0, TCC_OPTION_HAS_ARG},
|
||||||
|
{"g", 0, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
|
{"C", 0, 0},
|
||||||
|
{"-param", 0, 0},
|
||||||
|
{"pedantic", 0, 0},
|
||||||
|
{"pipe", 0, 0},
|
||||||
|
{"s", 0, 0},
|
||||||
|
{"traditional", 0, 0},
|
||||||
|
{"shared", 0, 0},
|
||||||
|
|
||||||
|
{NULL, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static TCCOption *options_ext = NULL;
|
||||||
|
|
||||||
|
static const char dumpmachine_str[] = "i386-pc-stupidos";
|
||||||
|
|
||||||
|
void
|
||||||
|
tcc_add_options(TCCOption *opt)
|
||||||
|
{
|
||||||
|
options_ext = opt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
#ifndef LIBTCC_OPTION_H
|
|
||||||
# define LIBTCC_OPTION_H 1
|
|
||||||
|
|
||||||
int tcc_parse_args(void *s, int *argc, char ***argv, int optind);
|
|
||||||
|
|
||||||
#endif /* LIBTCC_OPTION_H */
|
|
4
libtcc/tcc_internal.h
Normal file
4
libtcc/tcc_internal.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#ifndef TCC_INTERNAL_H
|
||||||
|
# define TCC_INTERNAL_H 1
|
||||||
|
|
||||||
|
#endif /* !TCC_INTERNAL_H */
|
|
@ -21,7 +21,7 @@
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
#ifdef CONFIG_TCC_ASM
|
#include "token.h"
|
||||||
|
|
||||||
static Section *last_text_section; /* to handle .previous asm directive */
|
static Section *last_text_section; /* to handle .previous asm directive */
|
||||||
static int asmgoto_n;
|
static int asmgoto_n;
|
||||||
|
@ -33,7 +33,7 @@ static int asm_get_prefix_name(TCCState *s1, const char *prefix, unsigned int n)
|
||||||
return tok_alloc_const(buf);
|
return tok_alloc_const(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
|
int asm_get_local_label_name(TCCState *s1, unsigned int n)
|
||||||
{
|
{
|
||||||
return asm_get_prefix_name(s1, "L..", n);
|
return asm_get_prefix_name(s1, "L..", n);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ static Sym *asm_label_push(int v)
|
||||||
are anonymous in C, in this case CSYM can be used to transfer
|
are anonymous in C, in this case CSYM can be used to transfer
|
||||||
all information from that symbol to the (possibly newly created)
|
all information from that symbol to the (possibly newly created)
|
||||||
asm symbol. */
|
asm symbol. */
|
||||||
ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
|
Sym* get_asm_sym(int name, Sym *csym)
|
||||||
{
|
{
|
||||||
Sym *sym = asm_label_find(name);
|
Sym *sym = asm_label_find(name);
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
|
@ -388,12 +388,12 @@ static inline void asm_expr_cmp(TCCState *s1, ExprValue *pe)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe)
|
void asm_expr(TCCState *s1, ExprValue *pe)
|
||||||
{
|
{
|
||||||
asm_expr_cmp(s1, pe);
|
asm_expr_cmp(s1, pe);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int asm_int_expr(TCCState *s1)
|
int asm_int_expr(TCCState *s1)
|
||||||
{
|
{
|
||||||
ExprValue e;
|
ExprValue e;
|
||||||
asm_expr(s1, &e);
|
asm_expr(s1, &e);
|
||||||
|
@ -1006,7 +1006,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assemble the current file */
|
/* Assemble the current file */
|
||||||
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
|
int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
/* default section is text */
|
/* default section is text */
|
||||||
|
@ -1043,7 +1043,7 @@ static void tcc_assemble_inline(TCCState *s1, const char *str, int len, int glob
|
||||||
/* find a constraint by its number or id (gcc 3 extended
|
/* find a constraint by its number or id (gcc 3 extended
|
||||||
syntax). return -1 if not found. Return in *pp in char after the
|
syntax). return -1 if not found. Return in *pp in char after the
|
||||||
constraint */
|
constraint */
|
||||||
ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands,
|
int find_constraint(ASMOperand *operands, int nb_operands,
|
||||||
const char *name, const char **pp)
|
const char *name, const char **pp)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
@ -1182,7 +1182,7 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse the GCC asm() instruction */
|
/* parse the GCC asm() instruction */
|
||||||
ST_FUNC void asm_instr(void)
|
void asm_instr(void)
|
||||||
{
|
{
|
||||||
CString astr, *astr1;
|
CString astr, *astr1;
|
||||||
|
|
||||||
|
@ -1330,7 +1330,7 @@ ST_FUNC void asm_instr(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_global_instr(void)
|
void asm_global_instr(void)
|
||||||
{
|
{
|
||||||
CString *astr;
|
CString *astr;
|
||||||
int saved_nocode_wanted = nocode_wanted;
|
int saved_nocode_wanted = nocode_wanted;
|
||||||
|
@ -1361,21 +1361,3 @@ ST_FUNC void asm_global_instr(void)
|
||||||
|
|
||||||
nocode_wanted = saved_nocode_wanted;
|
nocode_wanted = saved_nocode_wanted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************/
|
|
||||||
#else
|
|
||||||
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
|
|
||||||
{
|
|
||||||
tcc_error("asm not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
ST_FUNC void asm_instr(void)
|
|
||||||
{
|
|
||||||
tcc_error("inline asm() not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
ST_FUNC void asm_global_instr(void)
|
|
||||||
{
|
|
||||||
tcc_error("inline asm() not supported");
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_TCC_ASM */
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "coff.h"
|
#include "tcc/coff.h"
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,951 +0,0 @@
|
||||||
/*
|
|
||||||
* COFF file handling for TCC
|
|
||||||
*
|
|
||||||
* Copyright (c) 2003, 2004 TK
|
|
||||||
* Copyright (c) 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tcc.h"
|
|
||||||
|
|
||||||
/* XXX: this file uses tcc_error() to the effect of exit(1) */
|
|
||||||
#undef _tcc_error
|
|
||||||
|
|
||||||
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
|
|
||||||
#define MAX_STR_TABLE 1000000
|
|
||||||
AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */
|
|
||||||
|
|
||||||
SCNHDR section_header[MAXNSCNS];
|
|
||||||
|
|
||||||
#define MAX_FUNCS 1000
|
|
||||||
#define MAX_FUNC_NAME_LENGTH 128
|
|
||||||
|
|
||||||
int nFuncs;
|
|
||||||
char Func[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
|
|
||||||
char AssociatedFile[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
|
|
||||||
int LineNoFilePtr[MAX_FUNCS];
|
|
||||||
int EndAddress[MAX_FUNCS];
|
|
||||||
int LastLineNo[MAX_FUNCS];
|
|
||||||
int FuncEntries[MAX_FUNCS];
|
|
||||||
|
|
||||||
int OutputTheSection(Section * sect);
|
|
||||||
short int GetCoffFlags(const char *s);
|
|
||||||
void SortSymbolTable(TCCState *s1);
|
|
||||||
Section *FindSection(TCCState * s1, const char *sname);
|
|
||||||
|
|
||||||
int C67_main_entry_point;
|
|
||||||
|
|
||||||
int FindCoffSymbolIndex(TCCState * s1, const char *func_name);
|
|
||||||
int nb_syms;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long tag;
|
|
||||||
long size;
|
|
||||||
long fileptr;
|
|
||||||
long nextsym;
|
|
||||||
short int dummy;
|
|
||||||
} AUXFUNC;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long regmask;
|
|
||||||
unsigned short lineno;
|
|
||||||
unsigned short nentries;
|
|
||||||
int localframe;
|
|
||||||
int nextentry;
|
|
||||||
short int dummy;
|
|
||||||
} AUXBF;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long dummy;
|
|
||||||
unsigned short lineno;
|
|
||||||
unsigned short dummy1;
|
|
||||||
int dummy2;
|
|
||||||
int dummy3;
|
|
||||||
unsigned short dummy4;
|
|
||||||
} AUXEF;
|
|
||||||
|
|
||||||
ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|
||||||
{
|
|
||||||
Section *tcc_sect;
|
|
||||||
SCNHDR *coff_sec;
|
|
||||||
int file_pointer;
|
|
||||||
char *Coff_str_table, *pCoff_str_table;
|
|
||||||
int CoffTextSectionNo, coff_nb_syms;
|
|
||||||
FILHDR file_hdr; /* FILE HEADER STRUCTURE */
|
|
||||||
Section *stext, *sdata, *sbss;
|
|
||||||
int i, NSectionsToOutput = 0;
|
|
||||||
|
|
||||||
Coff_str_table = pCoff_str_table = NULL;
|
|
||||||
|
|
||||||
stext = FindSection(s1, ".text");
|
|
||||||
sdata = FindSection(s1, ".data");
|
|
||||||
sbss = FindSection(s1, ".bss");
|
|
||||||
|
|
||||||
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
|
|
||||||
coff_nb_syms = FindCoffSymbolIndex(s1, "XXXXXXXXXX1");
|
|
||||||
|
|
||||||
file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
|
|
||||||
file_hdr.f_timdat = 0; /* time & date stamp */
|
|
||||||
file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */
|
|
||||||
file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */
|
|
||||||
file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */
|
|
||||||
|
|
||||||
o_filehdr.magic = 0x0108; /* see magic.h */
|
|
||||||
o_filehdr.vstamp = 0x0190; /* version stamp */
|
|
||||||
o_filehdr.tsize = stext->data_offset; /* text size in bytes, padded to FW bdry */
|
|
||||||
o_filehdr.dsize = sdata->data_offset; /* initialized data " " */
|
|
||||||
o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */
|
|
||||||
o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */
|
|
||||||
o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */
|
|
||||||
o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */
|
|
||||||
|
|
||||||
|
|
||||||
// create all the section headers
|
|
||||||
|
|
||||||
file_pointer = FILHSZ + sizeof(AOUTHDR);
|
|
||||||
|
|
||||||
CoffTextSectionNo = -1;
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
coff_sec = §ion_header[i];
|
|
||||||
tcc_sect = s1->sections[i];
|
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
|
||||||
NSectionsToOutput++;
|
|
||||||
|
|
||||||
if (CoffTextSectionNo == -1 && tcc_sect == stext)
|
|
||||||
CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is
|
|
||||||
|
|
||||||
strcpy(coff_sec->s_name, tcc_sect->name); /* section name */
|
|
||||||
|
|
||||||
coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */
|
|
||||||
coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */
|
|
||||||
coff_sec->s_size = tcc_sect->data_offset; /* section size */
|
|
||||||
coff_sec->s_scnptr = 0; /* file ptr to raw data for section */
|
|
||||||
coff_sec->s_relptr = 0; /* file ptr to relocation */
|
|
||||||
coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */
|
|
||||||
coff_sec->s_nreloc = 0; /* number of relocation entries */
|
|
||||||
coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */
|
|
||||||
coff_sec->s_reserved = 0; /* reserved byte */
|
|
||||||
coff_sec->s_page = 0; /* memory page id */
|
|
||||||
|
|
||||||
file_pointer += sizeof(SCNHDR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file_hdr.f_nscns = NSectionsToOutput; /* number of sections */
|
|
||||||
|
|
||||||
// now loop through and determine file pointer locations
|
|
||||||
// for the raw data
|
|
||||||
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
coff_sec = §ion_header[i];
|
|
||||||
tcc_sect = s1->sections[i];
|
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
|
||||||
// put raw data
|
|
||||||
coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */
|
|
||||||
file_pointer += coff_sec->s_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now loop through and determine file pointer locations
|
|
||||||
// for the relocation data
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
coff_sec = §ion_header[i];
|
|
||||||
tcc_sect = s1->sections[i];
|
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
|
||||||
// put relocations data
|
|
||||||
if (coff_sec->s_nreloc > 0) {
|
|
||||||
coff_sec->s_relptr = file_pointer; /* file ptr to relocation */
|
|
||||||
file_pointer += coff_sec->s_nreloc * sizeof(struct reloc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now loop through and determine file pointer locations
|
|
||||||
// for the line number data
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
coff_sec = §ion_header[i];
|
|
||||||
tcc_sect = s1->sections[i];
|
|
||||||
|
|
||||||
coff_sec->s_nlnno = 0;
|
|
||||||
coff_sec->s_lnnoptr = 0;
|
|
||||||
|
|
||||||
if (s1->do_debug && tcc_sect == stext) {
|
|
||||||
// count how many line nos data
|
|
||||||
|
|
||||||
// also find association between source file name and function
|
|
||||||
// so we can sort the symbol table
|
|
||||||
|
|
||||||
|
|
||||||
Stab_Sym *sym, *sym_end;
|
|
||||||
char func_name[MAX_FUNC_NAME_LENGTH],
|
|
||||||
last_func_name[MAX_FUNC_NAME_LENGTH];
|
|
||||||
unsigned long func_addr, last_pc, pc;
|
|
||||||
const char *incl_files[INCLUDE_STACK_SIZE];
|
|
||||||
int incl_index, len, last_line_num;
|
|
||||||
const char *str, *p;
|
|
||||||
|
|
||||||
coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */
|
|
||||||
|
|
||||||
|
|
||||||
func_name[0] = '\0';
|
|
||||||
func_addr = 0;
|
|
||||||
incl_index = 0;
|
|
||||||
last_func_name[0] = '\0';
|
|
||||||
last_pc = 0xffffffff;
|
|
||||||
last_line_num = 1;
|
|
||||||
sym = (Stab_Sym *) stab_section->data + 1;
|
|
||||||
sym_end =
|
|
||||||
(Stab_Sym *) (stab_section->data +
|
|
||||||
stab_section->data_offset);
|
|
||||||
|
|
||||||
nFuncs = 0;
|
|
||||||
while (sym < sym_end) {
|
|
||||||
switch (sym->n_type) {
|
|
||||||
/* function start or end */
|
|
||||||
case N_FUN:
|
|
||||||
if (sym->n_strx == 0) {
|
|
||||||
// end of function
|
|
||||||
|
|
||||||
coff_sec->s_nlnno++;
|
|
||||||
file_pointer += LINESZ;
|
|
||||||
|
|
||||||
pc = sym->n_value + func_addr;
|
|
||||||
func_name[0] = '\0';
|
|
||||||
func_addr = 0;
|
|
||||||
EndAddress[nFuncs] = pc;
|
|
||||||
FuncEntries[nFuncs] =
|
|
||||||
(file_pointer -
|
|
||||||
LineNoFilePtr[nFuncs]) / LINESZ - 1;
|
|
||||||
LastLineNo[nFuncs++] = last_line_num + 1;
|
|
||||||
} else {
|
|
||||||
// beginning of function
|
|
||||||
|
|
||||||
LineNoFilePtr[nFuncs] = file_pointer;
|
|
||||||
coff_sec->s_nlnno++;
|
|
||||||
file_pointer += LINESZ;
|
|
||||||
|
|
||||||
str =
|
|
||||||
(const char *) stabstr_section->data +
|
|
||||||
sym->n_strx;
|
|
||||||
|
|
||||||
p = strchr(str, ':');
|
|
||||||
if (!p) {
|
|
||||||
pstrcpy(func_name, sizeof(func_name), str);
|
|
||||||
pstrcpy(Func[nFuncs], sizeof(func_name), str);
|
|
||||||
} else {
|
|
||||||
len = p - str;
|
|
||||||
if (len > sizeof(func_name) - 1)
|
|
||||||
len = sizeof(func_name) - 1;
|
|
||||||
memcpy(func_name, str, len);
|
|
||||||
memcpy(Func[nFuncs], str, len);
|
|
||||||
func_name[len] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the file that it came in so we can sort later
|
|
||||||
pstrcpy(AssociatedFile[nFuncs], sizeof(func_name),
|
|
||||||
incl_files[incl_index - 1]);
|
|
||||||
|
|
||||||
func_addr = sym->n_value;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* line number info */
|
|
||||||
case N_SLINE:
|
|
||||||
pc = sym->n_value + func_addr;
|
|
||||||
|
|
||||||
last_pc = pc;
|
|
||||||
last_line_num = sym->n_desc;
|
|
||||||
|
|
||||||
/* XXX: slow! */
|
|
||||||
strcpy(last_func_name, func_name);
|
|
||||||
|
|
||||||
coff_sec->s_nlnno++;
|
|
||||||
file_pointer += LINESZ;
|
|
||||||
break;
|
|
||||||
/* include files */
|
|
||||||
case N_BINCL:
|
|
||||||
str =
|
|
||||||
(const char *) stabstr_section->data + sym->n_strx;
|
|
||||||
add_incl:
|
|
||||||
if (incl_index < INCLUDE_STACK_SIZE) {
|
|
||||||
incl_files[incl_index++] = str;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case N_EINCL:
|
|
||||||
if (incl_index > 1)
|
|
||||||
incl_index--;
|
|
||||||
break;
|
|
||||||
case N_SO:
|
|
||||||
if (sym->n_strx == 0) {
|
|
||||||
incl_index = 0; /* end of translation unit */
|
|
||||||
} else {
|
|
||||||
str =
|
|
||||||
(const char *) stabstr_section->data +
|
|
||||||
sym->n_strx;
|
|
||||||
/* do not add path */
|
|
||||||
len = strlen(str);
|
|
||||||
if (len > 0 && str[len - 1] != '/')
|
|
||||||
goto add_incl;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sym++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
file_hdr.f_symptr = file_pointer; /* file pointer to symtab */
|
|
||||||
|
|
||||||
if (s1->do_debug)
|
|
||||||
file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */
|
|
||||||
else
|
|
||||||
file_hdr.f_nsyms = 0;
|
|
||||||
|
|
||||||
file_pointer += file_hdr.f_nsyms * SYMNMLEN;
|
|
||||||
|
|
||||||
// OK now we are all set to write the file
|
|
||||||
|
|
||||||
|
|
||||||
fwrite(&file_hdr, FILHSZ, 1, f);
|
|
||||||
fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);
|
|
||||||
|
|
||||||
// write section headers
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
coff_sec = §ion_header[i];
|
|
||||||
tcc_sect = s1->sections[i];
|
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
|
||||||
fwrite(coff_sec, sizeof(SCNHDR), 1, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// write raw data
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
coff_sec = §ion_header[i];
|
|
||||||
tcc_sect = s1->sections[i];
|
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
|
||||||
fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// write relocation data
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
coff_sec = §ion_header[i];
|
|
||||||
tcc_sect = s1->sections[i];
|
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
|
||||||
// put relocations data
|
|
||||||
if (coff_sec->s_nreloc > 0) {
|
|
||||||
fwrite(tcc_sect->reloc,
|
|
||||||
coff_sec->s_nreloc * sizeof(struct reloc), 1, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// group the symbols in order of filename, func1, func2, etc
|
|
||||||
// finally global symbols
|
|
||||||
|
|
||||||
if (s1->do_debug)
|
|
||||||
SortSymbolTable(s1);
|
|
||||||
|
|
||||||
// write line no data
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
coff_sec = §ion_header[i];
|
|
||||||
tcc_sect = s1->sections[i];
|
|
||||||
|
|
||||||
if (s1->do_debug && tcc_sect == stext) {
|
|
||||||
// count how many line nos data
|
|
||||||
|
|
||||||
|
|
||||||
Stab_Sym *sym, *sym_end;
|
|
||||||
char func_name[128], last_func_name[128];
|
|
||||||
unsigned long func_addr, last_pc, pc;
|
|
||||||
const char *incl_files[INCLUDE_STACK_SIZE];
|
|
||||||
int incl_index, len, last_line_num;
|
|
||||||
const char *str, *p;
|
|
||||||
|
|
||||||
LINENO CoffLineNo;
|
|
||||||
|
|
||||||
func_name[0] = '\0';
|
|
||||||
func_addr = 0;
|
|
||||||
incl_index = 0;
|
|
||||||
last_func_name[0] = '\0';
|
|
||||||
last_pc = 0;
|
|
||||||
last_line_num = 1;
|
|
||||||
sym = (Stab_Sym *) stab_section->data + 1;
|
|
||||||
sym_end =
|
|
||||||
(Stab_Sym *) (stab_section->data +
|
|
||||||
stab_section->data_offset);
|
|
||||||
|
|
||||||
while (sym < sym_end) {
|
|
||||||
switch (sym->n_type) {
|
|
||||||
/* function start or end */
|
|
||||||
case N_FUN:
|
|
||||||
if (sym->n_strx == 0) {
|
|
||||||
// end of function
|
|
||||||
|
|
||||||
CoffLineNo.l_addr.l_paddr = last_pc;
|
|
||||||
CoffLineNo.l_lnno = last_line_num + 1;
|
|
||||||
fwrite(&CoffLineNo, 6, 1, f);
|
|
||||||
|
|
||||||
pc = sym->n_value + func_addr;
|
|
||||||
func_name[0] = '\0';
|
|
||||||
func_addr = 0;
|
|
||||||
} else {
|
|
||||||
// beginning of function
|
|
||||||
|
|
||||||
str =
|
|
||||||
(const char *) stabstr_section->data +
|
|
||||||
sym->n_strx;
|
|
||||||
|
|
||||||
|
|
||||||
p = strchr(str, ':');
|
|
||||||
if (!p) {
|
|
||||||
pstrcpy(func_name, sizeof(func_name), str);
|
|
||||||
} else {
|
|
||||||
len = p - str;
|
|
||||||
if (len > sizeof(func_name) - 1)
|
|
||||||
len = sizeof(func_name) - 1;
|
|
||||||
memcpy(func_name, str, len);
|
|
||||||
func_name[len] = '\0';
|
|
||||||
}
|
|
||||||
func_addr = sym->n_value;
|
|
||||||
last_pc = func_addr;
|
|
||||||
last_line_num = -1;
|
|
||||||
|
|
||||||
// output a function begin
|
|
||||||
|
|
||||||
CoffLineNo.l_addr.l_symndx =
|
|
||||||
FindCoffSymbolIndex(s1, func_name);
|
|
||||||
CoffLineNo.l_lnno = 0;
|
|
||||||
|
|
||||||
fwrite(&CoffLineNo, 6, 1, f);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* line number info */
|
|
||||||
case N_SLINE:
|
|
||||||
pc = sym->n_value + func_addr;
|
|
||||||
|
|
||||||
|
|
||||||
/* XXX: slow! */
|
|
||||||
strcpy(last_func_name, func_name);
|
|
||||||
|
|
||||||
// output a line reference
|
|
||||||
|
|
||||||
CoffLineNo.l_addr.l_paddr = last_pc;
|
|
||||||
|
|
||||||
if (last_line_num == -1) {
|
|
||||||
CoffLineNo.l_lnno = sym->n_desc;
|
|
||||||
} else {
|
|
||||||
CoffLineNo.l_lnno = last_line_num + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fwrite(&CoffLineNo, 6, 1, f);
|
|
||||||
|
|
||||||
last_pc = pc;
|
|
||||||
last_line_num = sym->n_desc;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* include files */
|
|
||||||
case N_BINCL:
|
|
||||||
str =
|
|
||||||
(const char *) stabstr_section->data + sym->n_strx;
|
|
||||||
add_incl2:
|
|
||||||
if (incl_index < INCLUDE_STACK_SIZE) {
|
|
||||||
incl_files[incl_index++] = str;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case N_EINCL:
|
|
||||||
if (incl_index > 1)
|
|
||||||
incl_index--;
|
|
||||||
break;
|
|
||||||
case N_SO:
|
|
||||||
if (sym->n_strx == 0) {
|
|
||||||
incl_index = 0; /* end of translation unit */
|
|
||||||
} else {
|
|
||||||
str =
|
|
||||||
(const char *) stabstr_section->data +
|
|
||||||
sym->n_strx;
|
|
||||||
/* do not add path */
|
|
||||||
len = strlen(str);
|
|
||||||
if (len > 0 && str[len - 1] != '/')
|
|
||||||
goto add_incl2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sym++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// write symbol table
|
|
||||||
if (s1->do_debug) {
|
|
||||||
int k;
|
|
||||||
struct syment csym;
|
|
||||||
AUXFUNC auxfunc;
|
|
||||||
AUXBF auxbf;
|
|
||||||
AUXEF auxef;
|
|
||||||
int i;
|
|
||||||
Elf32_Sym *p;
|
|
||||||
const char *name;
|
|
||||||
int nstr;
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE);
|
|
||||||
pCoff_str_table = Coff_str_table;
|
|
||||||
nstr = 0;
|
|
||||||
|
|
||||||
p = (Elf32_Sym *) symtab_section->data;
|
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < nb_syms; i++) {
|
|
||||||
|
|
||||||
name = symtab_section->link->data + p->st_name;
|
|
||||||
|
|
||||||
for (k = 0; k < 8; k++)
|
|
||||||
csym._n._n_name[k] = 0;
|
|
||||||
|
|
||||||
if (strlen(name) <= 8) {
|
|
||||||
strcpy(csym._n._n_name, name);
|
|
||||||
} else {
|
|
||||||
if (pCoff_str_table - Coff_str_table + strlen(name) >
|
|
||||||
MAX_STR_TABLE - 1)
|
|
||||||
tcc_error("String table too large");
|
|
||||||
|
|
||||||
csym._n._n_n._n_zeroes = 0;
|
|
||||||
csym._n._n_n._n_offset =
|
|
||||||
pCoff_str_table - Coff_str_table + 4;
|
|
||||||
|
|
||||||
strcpy(pCoff_str_table, name);
|
|
||||||
pCoff_str_table += strlen(name) + 1; // skip over null
|
|
||||||
nstr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p->st_info == 4) {
|
|
||||||
// put a filename symbol
|
|
||||||
csym.n_value = 33; // ?????
|
|
||||||
csym.n_scnum = N_DEBUG;
|
|
||||||
csym.n_type = 0;
|
|
||||||
csym.n_sclass = C_FILE;
|
|
||||||
csym.n_numaux = 0;
|
|
||||||
fwrite(&csym, 18, 1, f);
|
|
||||||
n++;
|
|
||||||
|
|
||||||
} else if (p->st_info == 0x12) {
|
|
||||||
// find the function data
|
|
||||||
|
|
||||||
for (k = 0; k < nFuncs; k++) {
|
|
||||||
if (strcmp(name, Func[k]) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (k >= nFuncs) {
|
|
||||||
tcc_error("debug info can't find function: %s", name);
|
|
||||||
}
|
|
||||||
// put a Function Name
|
|
||||||
|
|
||||||
csym.n_value = p->st_value; // physical address
|
|
||||||
csym.n_scnum = CoffTextSectionNo;
|
|
||||||
csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0);
|
|
||||||
csym.n_sclass = C_EXT;
|
|
||||||
csym.n_numaux = 1;
|
|
||||||
fwrite(&csym, 18, 1, f);
|
|
||||||
|
|
||||||
// now put aux info
|
|
||||||
|
|
||||||
auxfunc.tag = 0;
|
|
||||||
auxfunc.size = EndAddress[k] - p->st_value;
|
|
||||||
auxfunc.fileptr = LineNoFilePtr[k];
|
|
||||||
auxfunc.nextsym = n + 6; // tktk
|
|
||||||
auxfunc.dummy = 0;
|
|
||||||
fwrite(&auxfunc, 18, 1, f);
|
|
||||||
|
|
||||||
// put a .bf
|
|
||||||
|
|
||||||
strcpy(csym._n._n_name, ".bf");
|
|
||||||
csym.n_value = p->st_value; // physical address
|
|
||||||
csym.n_scnum = CoffTextSectionNo;
|
|
||||||
csym.n_type = 0;
|
|
||||||
csym.n_sclass = C_FCN;
|
|
||||||
csym.n_numaux = 1;
|
|
||||||
fwrite(&csym, 18, 1, f);
|
|
||||||
|
|
||||||
// now put aux info
|
|
||||||
|
|
||||||
auxbf.regmask = 0;
|
|
||||||
auxbf.lineno = 0;
|
|
||||||
auxbf.nentries = FuncEntries[k];
|
|
||||||
auxbf.localframe = 0;
|
|
||||||
auxbf.nextentry = n + 6;
|
|
||||||
auxbf.dummy = 0;
|
|
||||||
fwrite(&auxbf, 18, 1, f);
|
|
||||||
|
|
||||||
// put a .ef
|
|
||||||
|
|
||||||
strcpy(csym._n._n_name, ".ef");
|
|
||||||
csym.n_value = EndAddress[k]; // physical address
|
|
||||||
csym.n_scnum = CoffTextSectionNo;
|
|
||||||
csym.n_type = 0;
|
|
||||||
csym.n_sclass = C_FCN;
|
|
||||||
csym.n_numaux = 1;
|
|
||||||
fwrite(&csym, 18, 1, f);
|
|
||||||
|
|
||||||
// now put aux info
|
|
||||||
|
|
||||||
auxef.dummy = 0;
|
|
||||||
auxef.lineno = LastLineNo[k];
|
|
||||||
auxef.dummy1 = 0;
|
|
||||||
auxef.dummy2 = 0;
|
|
||||||
auxef.dummy3 = 0;
|
|
||||||
auxef.dummy4 = 0;
|
|
||||||
fwrite(&auxef, 18, 1, f);
|
|
||||||
|
|
||||||
n += 6;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// try an put some type info
|
|
||||||
|
|
||||||
if ((p->st_other & VT_BTYPE) == VT_DOUBLE) {
|
|
||||||
csym.n_type = T_DOUBLE; // int
|
|
||||||
csym.n_sclass = C_EXT;
|
|
||||||
} else if ((p->st_other & VT_BTYPE) == VT_FLOAT) {
|
|
||||||
csym.n_type = T_FLOAT;
|
|
||||||
csym.n_sclass = C_EXT;
|
|
||||||
} else if ((p->st_other & VT_BTYPE) == VT_INT) {
|
|
||||||
csym.n_type = T_INT; // int
|
|
||||||
csym.n_sclass = C_EXT;
|
|
||||||
} else if ((p->st_other & VT_BTYPE) == VT_SHORT) {
|
|
||||||
csym.n_type = T_SHORT;
|
|
||||||
csym.n_sclass = C_EXT;
|
|
||||||
} else if ((p->st_other & VT_BTYPE) == VT_BYTE) {
|
|
||||||
csym.n_type = T_CHAR;
|
|
||||||
csym.n_sclass = C_EXT;
|
|
||||||
} else {
|
|
||||||
csym.n_type = T_INT; // just mark as a label
|
|
||||||
csym.n_sclass = C_LABEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
csym.n_value = p->st_value;
|
|
||||||
csym.n_scnum = 2;
|
|
||||||
csym.n_numaux = 1;
|
|
||||||
fwrite(&csym, 18, 1, f);
|
|
||||||
|
|
||||||
auxfunc.tag = 0;
|
|
||||||
auxfunc.size = 0x20;
|
|
||||||
auxfunc.fileptr = 0;
|
|
||||||
auxfunc.nextsym = 0;
|
|
||||||
auxfunc.dummy = 0;
|
|
||||||
fwrite(&auxfunc, 18, 1, f);
|
|
||||||
n++;
|
|
||||||
n++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s1->do_debug) {
|
|
||||||
// write string table
|
|
||||||
|
|
||||||
// first write the size
|
|
||||||
i = pCoff_str_table - Coff_str_table;
|
|
||||||
fwrite(&i, 4, 1, f);
|
|
||||||
|
|
||||||
// then write the strings
|
|
||||||
fwrite(Coff_str_table, i, 1, f);
|
|
||||||
|
|
||||||
tcc_free(Coff_str_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// group the symbols in order of filename, func1, func2, etc
|
|
||||||
// finally global symbols
|
|
||||||
|
|
||||||
void SortSymbolTable(TCCState *s1)
|
|
||||||
{
|
|
||||||
int i, j, k, n = 0;
|
|
||||||
Elf32_Sym *p, *p2, *NewTable;
|
|
||||||
char *name, *name2;
|
|
||||||
|
|
||||||
NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));
|
|
||||||
|
|
||||||
p = (Elf32_Sym *) symtab_section->data;
|
|
||||||
|
|
||||||
|
|
||||||
// find a file symbol, copy it over
|
|
||||||
// then scan the whole symbol list and copy any function
|
|
||||||
// symbols that match the file association
|
|
||||||
|
|
||||||
for (i = 0; i < nb_syms; i++) {
|
|
||||||
if (p->st_info == 4) {
|
|
||||||
name = (char *) symtab_section->link->data + p->st_name;
|
|
||||||
|
|
||||||
// this is a file symbol, copy it over
|
|
||||||
|
|
||||||
NewTable[n++] = *p;
|
|
||||||
|
|
||||||
p2 = (Elf32_Sym *) symtab_section->data;
|
|
||||||
|
|
||||||
for (j = 0; j < nb_syms; j++) {
|
|
||||||
if (p2->st_info == 0x12) {
|
|
||||||
// this is a func symbol
|
|
||||||
|
|
||||||
name2 =
|
|
||||||
(char *) symtab_section->link->data + p2->st_name;
|
|
||||||
|
|
||||||
// find the function data index
|
|
||||||
|
|
||||||
for (k = 0; k < nFuncs; k++) {
|
|
||||||
if (strcmp(name2, Func[k]) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (k >= nFuncs) {
|
|
||||||
tcc_error("debug (sort) info can't find function: %s", name2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(AssociatedFile[k], name) == 0) {
|
|
||||||
// yes they match copy it over
|
|
||||||
|
|
||||||
NewTable[n++] = *p2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p2++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now all the filename and func symbols should have been copied over
|
|
||||||
// copy all the rest over (all except file and funcs)
|
|
||||||
|
|
||||||
p = (Elf32_Sym *) symtab_section->data;
|
|
||||||
for (i = 0; i < nb_syms; i++) {
|
|
||||||
if (p->st_info != 4 && p->st_info != 0x12) {
|
|
||||||
NewTable[n++] = *p;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n != nb_syms)
|
|
||||||
tcc_error("Internal Compiler error, debug info");
|
|
||||||
|
|
||||||
// copy it all back
|
|
||||||
|
|
||||||
p = (Elf32_Sym *) symtab_section->data;
|
|
||||||
for (i = 0; i < nb_syms; i++) {
|
|
||||||
*p++ = NewTable[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
tcc_free(NewTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int FindCoffSymbolIndex(TCCState *s1, const char *func_name)
|
|
||||||
{
|
|
||||||
int i, n = 0;
|
|
||||||
Elf32_Sym *p;
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
p = (Elf32_Sym *) symtab_section->data;
|
|
||||||
|
|
||||||
for (i = 0; i < nb_syms; i++) {
|
|
||||||
|
|
||||||
name = (char *) symtab_section->link->data + p->st_name;
|
|
||||||
|
|
||||||
if (p->st_info == 4) {
|
|
||||||
// put a filename symbol
|
|
||||||
n++;
|
|
||||||
} else if (p->st_info == 0x12) {
|
|
||||||
|
|
||||||
if (strcmp(func_name, name) == 0)
|
|
||||||
return n;
|
|
||||||
|
|
||||||
n += 6;
|
|
||||||
|
|
||||||
// put a Function Name
|
|
||||||
|
|
||||||
// now put aux info
|
|
||||||
|
|
||||||
// put a .bf
|
|
||||||
|
|
||||||
// now put aux info
|
|
||||||
|
|
||||||
// put a .ef
|
|
||||||
|
|
||||||
// now put aux info
|
|
||||||
|
|
||||||
} else {
|
|
||||||
n += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n; // total number of symbols
|
|
||||||
}
|
|
||||||
|
|
||||||
int OutputTheSection(Section * sect)
|
|
||||||
{
|
|
||||||
const char *s = sect->name;
|
|
||||||
|
|
||||||
if (!strcmp(s, ".text"))
|
|
||||||
return 1;
|
|
||||||
else if (!strcmp(s, ".data"))
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
short int GetCoffFlags(const char *s)
|
|
||||||
{
|
|
||||||
if (!strcmp(s, ".text"))
|
|
||||||
return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400;
|
|
||||||
else if (!strcmp(s, ".data"))
|
|
||||||
return STYP_DATA;
|
|
||||||
else if (!strcmp(s, ".bss"))
|
|
||||||
return STYP_BSS;
|
|
||||||
else if (!strcmp(s, ".stack"))
|
|
||||||
return STYP_BSS | STYP_ALIGN | 0x200;
|
|
||||||
else if (!strcmp(s, ".cinit"))
|
|
||||||
return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Section *FindSection(TCCState * s1, const char *sname)
|
|
||||||
{
|
|
||||||
Section *s;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
s = s1->sections[i];
|
|
||||||
|
|
||||||
if (!strcmp(sname, s->name))
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
tcc_error("could not find section %s", sname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
|
|
||||||
{
|
|
||||||
// tktk TokenSym *ts;
|
|
||||||
|
|
||||||
FILE *f;
|
|
||||||
unsigned int str_size;
|
|
||||||
char *Coff_str_table, *name;
|
|
||||||
int i, k;
|
|
||||||
struct syment csym;
|
|
||||||
char name2[9];
|
|
||||||
FILHDR file_hdr; /* FILE HEADER STRUCTURE */
|
|
||||||
|
|
||||||
f = fdopen(fd, "rb");
|
|
||||||
if (!f) {
|
|
||||||
tcc_error("Unable to open .out file for input");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fread(&file_hdr, FILHSZ, 1, f) != 1)
|
|
||||||
tcc_error("error reading .out file for input");
|
|
||||||
|
|
||||||
if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
|
|
||||||
tcc_error("error reading .out file for input");
|
|
||||||
|
|
||||||
// first read the string table
|
|
||||||
|
|
||||||
if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))
|
|
||||||
tcc_error("error reading .out file for input");
|
|
||||||
|
|
||||||
if (fread(&str_size, sizeof(int), 1, f) != 1)
|
|
||||||
tcc_error("error reading .out file for input");
|
|
||||||
|
|
||||||
|
|
||||||
Coff_str_table = (char *) tcc_malloc(str_size);
|
|
||||||
|
|
||||||
if (fread(Coff_str_table, str_size - 4, 1, f) != 1)
|
|
||||||
tcc_error("error reading .out file for input");
|
|
||||||
|
|
||||||
// read/process all the symbols
|
|
||||||
|
|
||||||
// seek back to symbols
|
|
||||||
|
|
||||||
if (fseek(f, file_hdr.f_symptr, SEEK_SET))
|
|
||||||
tcc_error("error reading .out file for input");
|
|
||||||
|
|
||||||
for (i = 0; i < file_hdr.f_nsyms; i++) {
|
|
||||||
if (fread(&csym, SYMESZ, 1, f) != 1)
|
|
||||||
tcc_error("error reading .out file for input");
|
|
||||||
|
|
||||||
if (csym._n._n_n._n_zeroes == 0) {
|
|
||||||
name = Coff_str_table + csym._n._n_n._n_offset - 4;
|
|
||||||
} else {
|
|
||||||
name = csym._n._n_name;
|
|
||||||
|
|
||||||
if (name[7] != 0) {
|
|
||||||
for (k = 0; k < 8; k++)
|
|
||||||
name2[k] = name[k];
|
|
||||||
|
|
||||||
name2[8] = 0;
|
|
||||||
|
|
||||||
name = name2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if (strcmp("_DAC_Buffer",name)==0) // tktk
|
|
||||||
// name[0]=0;
|
|
||||||
|
|
||||||
if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures
|
|
||||||
(csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure
|
|
||||||
(csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles
|
|
||||||
(csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats
|
|
||||||
{
|
|
||||||
// strip off any leading underscore (except for other main routine)
|
|
||||||
|
|
||||||
if (name[0] == '_' && strcmp(name, "_main") != 0)
|
|
||||||
name++;
|
|
||||||
|
|
||||||
tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);
|
|
||||||
}
|
|
||||||
// skip any aux records
|
|
||||||
|
|
||||||
if (csym.n_numaux == 1) {
|
|
||||||
if (fread(&csym, SYMESZ, 1, f) != 1)
|
|
||||||
tcc_error("error reading .out file for input");
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
775
libtcc/tccelf.c
775
libtcc/tccelf.c
File diff suppressed because it is too large
Load diff
182
libtcc/tccgen.c
182
libtcc/tccgen.c
|
@ -21,6 +21,7 @@
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
|
#include "token.h"
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
/* global variables */
|
/* global variables */
|
||||||
|
@ -30,13 +31,13 @@
|
||||||
rsym: return symbol
|
rsym: return symbol
|
||||||
anon_sym: anonymous symbol index
|
anon_sym: anonymous symbol index
|
||||||
*/
|
*/
|
||||||
ST_DATA int rsym, anon_sym, ind, loc;
|
int rsym, anon_sym, ind, loc;
|
||||||
|
|
||||||
ST_DATA Sym *global_stack;
|
Sym *global_stack;
|
||||||
ST_DATA Sym *local_stack;
|
Sym *local_stack;
|
||||||
ST_DATA Sym *define_stack;
|
Sym *define_stack;
|
||||||
ST_DATA Sym *global_label_stack;
|
Sym *global_label_stack;
|
||||||
ST_DATA Sym *local_label_stack;
|
Sym *local_label_stack;
|
||||||
|
|
||||||
static Sym *sym_free_first;
|
static Sym *sym_free_first;
|
||||||
static void **sym_pools;
|
static void **sym_pools;
|
||||||
|
@ -45,11 +46,11 @@ static int nb_sym_pools;
|
||||||
static Sym *all_cleanups, *pending_gotos;
|
static Sym *all_cleanups, *pending_gotos;
|
||||||
static int local_scope;
|
static int local_scope;
|
||||||
|
|
||||||
ST_DATA SValue *vtop;
|
SValue *vtop;
|
||||||
static SValue _vstack[1 + VSTACK_SIZE];
|
static SValue _vstack[1 + VSTACK_SIZE];
|
||||||
#define vstack (_vstack + 1)
|
#define vstack (_vstack + 1)
|
||||||
|
|
||||||
ST_DATA int nocode_wanted; /* no code generation wanted */
|
int nocode_wanted; /* no code generation wanted */
|
||||||
#define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */
|
#define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */
|
||||||
#define DATA_ONLY_WANTED 0x80000000 /* ON outside of functions and for static initializers */
|
#define DATA_ONLY_WANTED 0x80000000 /* ON outside of functions and for static initializers */
|
||||||
|
|
||||||
|
@ -67,13 +68,13 @@ ST_DATA int nocode_wanted; /* no code generation wanted */
|
||||||
#define CONST_WANTED_MASK 0x0FFF0000
|
#define CONST_WANTED_MASK 0x0FFF0000
|
||||||
#define CONST_WANTED (nocode_wanted & CONST_WANTED_MASK)
|
#define CONST_WANTED (nocode_wanted & CONST_WANTED_MASK)
|
||||||
|
|
||||||
ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
||||||
ST_DATA CType func_vt; /* current function return type (used by return instruction) */
|
CType func_vt; /* current function return type (used by return instruction) */
|
||||||
ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */
|
int func_var; /* true if current function is variadic (used by return instruction) */
|
||||||
ST_DATA int func_vc;
|
int func_vc;
|
||||||
ST_DATA int func_ind;
|
int func_ind;
|
||||||
ST_DATA const char *funcname;
|
const char *funcname;
|
||||||
ST_DATA CType int_type, func_old_type, char_type, char_pointer_type;
|
CType int_type, func_old_type, char_type, char_pointer_type;
|
||||||
static CString initstr;
|
static CString initstr;
|
||||||
|
|
||||||
#if PTR_SIZE == 4
|
#if PTR_SIZE == 4
|
||||||
|
@ -163,7 +164,7 @@ static void do_Static_assert(void);
|
||||||
/* Automagical code suppression */
|
/* Automagical code suppression */
|
||||||
|
|
||||||
/* Clear 'nocode_wanted' at forward label if it was used */
|
/* Clear 'nocode_wanted' at forward label if it was used */
|
||||||
ST_FUNC void gsym(int t)
|
void gsym(int t)
|
||||||
{
|
{
|
||||||
if (t) {
|
if (t) {
|
||||||
gsym_addr(t, ind);
|
gsym_addr(t, ind);
|
||||||
|
@ -199,7 +200,7 @@ static int gjmp_acs(int t)
|
||||||
#define gjmp gjmp_acs
|
#define gjmp gjmp_acs
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
ST_INLN int is_float(int t)
|
int is_float(int t)
|
||||||
{
|
{
|
||||||
int bt = t & VT_BTYPE;
|
int bt = t & VT_BTYPE;
|
||||||
return bt == VT_LDOUBLE
|
return bt == VT_LDOUBLE
|
||||||
|
@ -289,7 +290,7 @@ static int RC2_TYPE(int t, int rc)
|
||||||
/* we use our own 'finite' function to avoid potential problems with
|
/* we use our own 'finite' function to avoid potential problems with
|
||||||
non standard math libs */
|
non standard math libs */
|
||||||
/* XXX: endianness dependent */
|
/* XXX: endianness dependent */
|
||||||
ST_FUNC int ieee_finite(double d)
|
int ieee_finite(double d)
|
||||||
{
|
{
|
||||||
int p[4];
|
int p[4];
|
||||||
memcpy(p, &d, sizeof(double));
|
memcpy(p, &d, sizeof(double));
|
||||||
|
@ -299,13 +300,13 @@ ST_FUNC int ieee_finite(double d)
|
||||||
/* compiling intel long double natively */
|
/* compiling intel long double natively */
|
||||||
# define TCC_IS_NATIVE_387
|
# define TCC_IS_NATIVE_387
|
||||||
|
|
||||||
ST_FUNC void test_lvalue(void)
|
void test_lvalue(void)
|
||||||
{
|
{
|
||||||
if (!(vtop->r & VT_LVAL))
|
if (!(vtop->r & VT_LVAL))
|
||||||
expect("lvalue");
|
expect("lvalue");
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void check_vstack(void)
|
void check_vstack(void)
|
||||||
{
|
{
|
||||||
if (vtop != vstack - 1)
|
if (vtop != vstack - 1)
|
||||||
tcc_error("internal compiler error: vstack leak (%d)",
|
tcc_error("internal compiler error: vstack leak (%d)",
|
||||||
|
@ -327,7 +328,7 @@ void pv (const char *lbl, int a, int b)
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
/* initialize vstack and types. This must be done also for tcc -E */
|
/* initialize vstack and types. This must be done also for tcc -E */
|
||||||
ST_FUNC void tccgen_init(TCCState *s1)
|
void tccgen_init(TCCState *s1)
|
||||||
{
|
{
|
||||||
vtop = vstack - 1;
|
vtop = vstack - 1;
|
||||||
memset(vtop, 0, sizeof *vtop);
|
memset(vtop, 0, sizeof *vtop);
|
||||||
|
@ -351,7 +352,7 @@ ST_FUNC void tccgen_init(TCCState *s1)
|
||||||
cstr_new(&initstr);
|
cstr_new(&initstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int tccgen_compile(TCCState *s1)
|
int tccgen_compile(TCCState *s1)
|
||||||
{
|
{
|
||||||
funcname = "";
|
funcname = "";
|
||||||
func_ind = -1;
|
func_ind = -1;
|
||||||
|
@ -371,7 +372,7 @@ ST_FUNC int tccgen_compile(TCCState *s1)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tccgen_finish(TCCState *s1)
|
void tccgen_finish(TCCState *s1)
|
||||||
{
|
{
|
||||||
free_inline_functions(s1);
|
free_inline_functions(s1);
|
||||||
sym_pop(&global_stack, NULL, 0);
|
sym_pop(&global_stack, NULL, 0);
|
||||||
|
@ -396,7 +397,7 @@ ST_FUNC void tccgen_finish(TCCState *s1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
ST_FUNC ElfSym *elfsym(Sym *s)
|
ElfSym *elfsym(Sym *s)
|
||||||
{
|
{
|
||||||
if (!s || !s->c)
|
if (!s || !s->c)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -404,7 +405,7 @@ ST_FUNC ElfSym *elfsym(Sym *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply storage attributes to Elf symbol */
|
/* apply storage attributes to Elf symbol */
|
||||||
ST_FUNC void update_storage(Sym *sym)
|
void update_storage(Sym *sym)
|
||||||
{
|
{
|
||||||
ElfSym *esym;
|
ElfSym *esym;
|
||||||
int sym_bind, old_sym_bind;
|
int sym_bind, old_sym_bind;
|
||||||
|
@ -450,7 +451,7 @@ ST_FUNC void update_storage(Sym *sym)
|
||||||
/* update sym->c so that it points to an external symbol in section
|
/* update sym->c so that it points to an external symbol in section
|
||||||
'section' with value 'value' */
|
'section' with value 'value' */
|
||||||
|
|
||||||
ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
|
void put_extern_sym2(Sym *sym, int sh_num,
|
||||||
addr_t value, unsigned long size,
|
addr_t value, unsigned long size,
|
||||||
int can_add_underscore)
|
int can_add_underscore)
|
||||||
{
|
{
|
||||||
|
@ -515,7 +516,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
|
||||||
update_storage(sym);
|
update_storage(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void put_extern_sym(Sym *sym, Section *s, addr_t value, unsigned long size)
|
void put_extern_sym(Sym *sym, Section *s, addr_t value, unsigned long size)
|
||||||
{
|
{
|
||||||
if (nocode_wanted && (NODATA_WANTED || (s && s == cur_text_section)))
|
if (nocode_wanted && (NODATA_WANTED || (s && s == cur_text_section)))
|
||||||
return;
|
return;
|
||||||
|
@ -523,7 +524,7 @@ ST_FUNC void put_extern_sym(Sym *sym, Section *s, addr_t value, unsigned long si
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a new relocation entry to symbol 'sym' in section 's' */
|
/* add a new relocation entry to symbol 'sym' in section 's' */
|
||||||
ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type,
|
void greloca(Section *s, Sym *sym, unsigned long offset, int type,
|
||||||
addr_t addend)
|
addr_t addend)
|
||||||
{
|
{
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
@ -542,7 +543,7 @@ ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PTR_SIZE == 4
|
#if PTR_SIZE == 4
|
||||||
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)
|
void greloc(Section *s, Sym *sym, unsigned long offset, int type)
|
||||||
{
|
{
|
||||||
greloca(s, sym, offset, type, 0);
|
greloca(s, sym, offset, type, 0);
|
||||||
}
|
}
|
||||||
|
@ -584,7 +585,7 @@ static inline Sym *sym_malloc(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_INLN void sym_free(Sym *sym)
|
void sym_free(Sym *sym)
|
||||||
{
|
{
|
||||||
#ifndef SYM_DEBUG
|
#ifndef SYM_DEBUG
|
||||||
sym->next = sym_free_first;
|
sym->next = sym_free_first;
|
||||||
|
@ -595,7 +596,7 @@ ST_INLN void sym_free(Sym *sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push, without hashing */
|
/* push, without hashing */
|
||||||
ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c)
|
Sym *sym_push2(Sym **ps, int v, int t, int c)
|
||||||
{
|
{
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
|
||||||
|
@ -612,7 +613,7 @@ ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c)
|
||||||
|
|
||||||
/* find a symbol and return its associated structure. 's' is the top
|
/* find a symbol and return its associated structure. 's' is the top
|
||||||
of the symbol stack */
|
of the symbol stack */
|
||||||
ST_FUNC Sym *sym_find2(Sym *s, int v)
|
Sym *sym_find2(Sym *s, int v)
|
||||||
{
|
{
|
||||||
while (s) {
|
while (s) {
|
||||||
if (s->v == v)
|
if (s->v == v)
|
||||||
|
@ -623,7 +624,7 @@ ST_FUNC Sym *sym_find2(Sym *s, int v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* structure lookup */
|
/* structure lookup */
|
||||||
ST_INLN Sym *struct_find(int v)
|
Sym *struct_find(int v)
|
||||||
{
|
{
|
||||||
v -= TOK_IDENT;
|
v -= TOK_IDENT;
|
||||||
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
||||||
|
@ -632,7 +633,7 @@ ST_INLN Sym *struct_find(int v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find an identifier */
|
/* find an identifier */
|
||||||
ST_INLN Sym *sym_find(int v)
|
Sym *sym_find(int v)
|
||||||
{
|
{
|
||||||
v -= TOK_IDENT;
|
v -= TOK_IDENT;
|
||||||
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
||||||
|
@ -649,7 +650,7 @@ static int sym_scope(Sym *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push a given symbol on the symbol stack */
|
/* push a given symbol on the symbol stack */
|
||||||
ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
|
Sym *sym_push(int v, CType *type, int r, int c)
|
||||||
{
|
{
|
||||||
Sym *s, **ps;
|
Sym *s, **ps;
|
||||||
TokenSym *ts;
|
TokenSym *ts;
|
||||||
|
@ -681,7 +682,7 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push a global identifier */
|
/* push a global identifier */
|
||||||
ST_FUNC Sym *global_identifier_push(int v, int t, int c)
|
Sym *global_identifier_push(int v, int t, int c)
|
||||||
{
|
{
|
||||||
Sym *s, **ps;
|
Sym *s, **ps;
|
||||||
s = sym_push2(&global_stack, v, t, c);
|
s = sym_push2(&global_stack, v, t, c);
|
||||||
|
@ -701,7 +702,7 @@ ST_FUNC Sym *global_identifier_push(int v, int t, int c)
|
||||||
|
|
||||||
/* pop symbols until top reaches 'b'. If KEEP is non-zero don't really
|
/* pop symbols until top reaches 'b'. If KEEP is non-zero don't really
|
||||||
pop them yet from the list, but do remove them from the token array. */
|
pop them yet from the list, but do remove them from the token array. */
|
||||||
ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep)
|
void sym_pop(Sym **ptop, Sym *b, int keep)
|
||||||
{
|
{
|
||||||
Sym *s, *ss, **ps;
|
Sym *s, *ss, **ps;
|
||||||
TokenSym *ts;
|
TokenSym *ts;
|
||||||
|
@ -730,7 +731,7 @@ ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* label lookup */
|
/* label lookup */
|
||||||
ST_FUNC Sym *label_find(int v)
|
Sym *label_find(int v)
|
||||||
{
|
{
|
||||||
v -= TOK_IDENT;
|
v -= TOK_IDENT;
|
||||||
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
||||||
|
@ -738,7 +739,7 @@ ST_FUNC Sym *label_find(int v)
|
||||||
return table_ident[v]->sym_label;
|
return table_ident[v]->sym_label;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
|
Sym *label_push(Sym **ptop, int v, int flags)
|
||||||
{
|
{
|
||||||
Sym *s, **ps;
|
Sym *s, **ps;
|
||||||
s = sym_push2(ptop, v, VT_STATIC, 0);
|
s = sym_push2(ptop, v, VT_STATIC, 0);
|
||||||
|
@ -757,7 +758,7 @@ ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
|
||||||
|
|
||||||
/* pop labels until element last is reached. Look if any labels are
|
/* pop labels until element last is reached. Look if any labels are
|
||||||
undefined. Define symbols if '&&label' was used. */
|
undefined. Define symbols if '&&label' was used. */
|
||||||
ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep)
|
void label_pop(Sym **ptop, Sym *slast, int keep)
|
||||||
{
|
{
|
||||||
Sym *s, *s1;
|
Sym *s, *s1;
|
||||||
for(s = *ptop; s != slast; s = s1) {
|
for(s = *ptop; s != slast; s = s1) {
|
||||||
|
@ -824,7 +825,7 @@ static void vsetc(CType *type, int r, CValue *vc)
|
||||||
vtop->sym = NULL;
|
vtop->sym = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void vswap(void)
|
void vswap(void)
|
||||||
{
|
{
|
||||||
SValue tmp;
|
SValue tmp;
|
||||||
|
|
||||||
|
@ -835,7 +836,7 @@ ST_FUNC void vswap(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pop stack value */
|
/* pop stack value */
|
||||||
ST_FUNC void vpop(void)
|
void vpop(void)
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
v = vtop->r & VT_VALMASK;
|
v = vtop->r & VT_VALMASK;
|
||||||
|
@ -868,7 +869,7 @@ static void vpush64(int ty, unsigned long long v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push integer constant */
|
/* push integer constant */
|
||||||
ST_FUNC void vpushi(int v)
|
void vpushi(int v)
|
||||||
{
|
{
|
||||||
vpush64(VT_INT, v);
|
vpush64(VT_INT, v);
|
||||||
}
|
}
|
||||||
|
@ -885,7 +886,7 @@ static inline void vpushll(long long v)
|
||||||
vpush64(VT_LLONG, v);
|
vpush64(VT_LLONG, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void vset(CType *type, int r, int v)
|
void vset(CType *type, int r, int v)
|
||||||
{
|
{
|
||||||
CValue cval;
|
CValue cval;
|
||||||
cval.i = v;
|
cval.i = v;
|
||||||
|
@ -900,7 +901,7 @@ static void vseti(int r, int v)
|
||||||
vset(&type, r, v);
|
vset(&type, r, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void vpushv(SValue *v)
|
void vpushv(SValue *v)
|
||||||
{
|
{
|
||||||
if (vtop >= vstack + (VSTACK_SIZE - 1))
|
if (vtop >= vstack + (VSTACK_SIZE - 1))
|
||||||
tcc_error("memory full (vstack)");
|
tcc_error("memory full (vstack)");
|
||||||
|
@ -914,7 +915,7 @@ static void vdup(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rotate the stack element at position n-1 to the top */
|
/* rotate the stack element at position n-1 to the top */
|
||||||
ST_FUNC void vrotb(int n)
|
void vrotb(int n)
|
||||||
{
|
{
|
||||||
SValue tmp;
|
SValue tmp;
|
||||||
if (--n < 1)
|
if (--n < 1)
|
||||||
|
@ -926,7 +927,7 @@ ST_FUNC void vrotb(int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rotate the top stack element into position n-1 */
|
/* rotate the top stack element into position n-1 */
|
||||||
ST_FUNC void vrott(int n)
|
void vrott(int n)
|
||||||
{
|
{
|
||||||
SValue tmp;
|
SValue tmp;
|
||||||
if (--n < 1)
|
if (--n < 1)
|
||||||
|
@ -938,7 +939,7 @@ ST_FUNC void vrott(int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reverse order of the the first n stack elements */
|
/* reverse order of the the first n stack elements */
|
||||||
ST_FUNC void vrev(int n)
|
void vrev(int n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
SValue tmp;
|
SValue tmp;
|
||||||
|
@ -951,7 +952,7 @@ ST_FUNC void vrev(int n)
|
||||||
/* vtop->r = VT_CMP means CPU-flags have been set from comparison or test. */
|
/* vtop->r = VT_CMP means CPU-flags have been set from comparison or test. */
|
||||||
|
|
||||||
/* called from generators to set the result from relational ops */
|
/* called from generators to set the result from relational ops */
|
||||||
ST_FUNC void vset_VT_CMP(int op)
|
void vset_VT_CMP(int op)
|
||||||
{
|
{
|
||||||
vtop->r = VT_CMP;
|
vtop->r = VT_CMP;
|
||||||
vtop->cmp_op = op;
|
vtop->cmp_op = op;
|
||||||
|
@ -1038,7 +1039,7 @@ static void gen_test_zero(int op)
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
/* push a symbol value of TYPE */
|
/* push a symbol value of TYPE */
|
||||||
ST_FUNC void vpushsym(CType *type, Sym *sym)
|
void vpushsym(CType *type, Sym *sym)
|
||||||
{
|
{
|
||||||
CValue cval;
|
CValue cval;
|
||||||
cval.i = 0;
|
cval.i = 0;
|
||||||
|
@ -1047,7 +1048,7 @@ ST_FUNC void vpushsym(CType *type, Sym *sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a static symbol pointing to a section */
|
/* Return a static symbol pointing to a section */
|
||||||
ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
|
Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
|
@ -1066,7 +1067,7 @@ static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
/* define a new external reference to a symbol 'v' of type 'u' */
|
/* define a new external reference to a symbol 'v' of type 'u' */
|
||||||
ST_FUNC Sym *external_global_sym(int v, CType *type)
|
Sym *external_global_sym(int v, CType *type)
|
||||||
{
|
{
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
|
||||||
|
@ -1085,14 +1086,14 @@ ST_FUNC Sym *external_global_sym(int v, CType *type)
|
||||||
|
|
||||||
/* create an external reference with no specific type similar to asm labels.
|
/* create an external reference with no specific type similar to asm labels.
|
||||||
This avoids type conflicts if the symbol is used from C too */
|
This avoids type conflicts if the symbol is used from C too */
|
||||||
ST_FUNC Sym *external_helper_sym(int v)
|
Sym *external_helper_sym(int v)
|
||||||
{
|
{
|
||||||
CType ct = { VT_ASM_FUNC, NULL };
|
CType ct = { VT_ASM_FUNC, NULL };
|
||||||
return external_global_sym(v, &ct);
|
return external_global_sym(v, &ct);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push a reference to an helper function (such as memmove) */
|
/* push a reference to an helper function (such as memmove) */
|
||||||
ST_FUNC void vpush_helper_func(int v)
|
void vpush_helper_func(int v)
|
||||||
{
|
{
|
||||||
vpushsym(&func_old_type, external_helper_sym(v));
|
vpushsym(&func_old_type, external_helper_sym(v));
|
||||||
}
|
}
|
||||||
|
@ -1289,7 +1290,7 @@ static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save registers up to (vtop - n) stack entry */
|
/* save registers up to (vtop - n) stack entry */
|
||||||
ST_FUNC void save_regs(int n)
|
void save_regs(int n)
|
||||||
{
|
{
|
||||||
SValue *p, *p1;
|
SValue *p, *p1;
|
||||||
for(p = vstack, p1 = vtop - n; p <= p1; p++)
|
for(p = vstack, p1 = vtop - n; p <= p1; p++)
|
||||||
|
@ -1297,14 +1298,14 @@ ST_FUNC void save_regs(int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save r to the memory stack, and mark it as being free */
|
/* save r to the memory stack, and mark it as being free */
|
||||||
ST_FUNC void save_reg(int r)
|
void save_reg(int r)
|
||||||
{
|
{
|
||||||
save_reg_upstack(r, 0);
|
save_reg_upstack(r, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save r to the memory stack, and mark it as being free,
|
/* save r to the memory stack, and mark it as being free,
|
||||||
if seen up to (vtop - n) stack entry */
|
if seen up to (vtop - n) stack entry */
|
||||||
ST_FUNC void save_reg_upstack(int r, int n)
|
void save_reg_upstack(int r, int n)
|
||||||
{
|
{
|
||||||
int l, size, align, bt, r2;
|
int l, size, align, bt, r2;
|
||||||
SValue *p, *p1, sv;
|
SValue *p, *p1, sv;
|
||||||
|
@ -1357,7 +1358,7 @@ ST_FUNC void save_reg_upstack(int r, int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find a free register of class 'rc'. If none, save one register */
|
/* find a free register of class 'rc'. If none, save one register */
|
||||||
ST_FUNC int get_reg(int rc)
|
int get_reg(int rc)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
SValue *p;
|
SValue *p;
|
||||||
|
@ -1455,7 +1456,7 @@ static void move_reg(int r, int s, int t)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get address of vtop (vtop MUST BE an lvalue) */
|
/* get address of vtop (vtop MUST BE an lvalue) */
|
||||||
ST_FUNC void gaddrof(void)
|
void gaddrof(void)
|
||||||
{
|
{
|
||||||
vtop->r &= ~VT_LVAL;
|
vtop->r &= ~VT_LVAL;
|
||||||
/* tricky: if saved lvalue, then we can go back to lvalue */
|
/* tricky: if saved lvalue, then we can go back to lvalue */
|
||||||
|
@ -1555,7 +1556,7 @@ static void store_packed_bf(int bit_pos, int bit_size)
|
||||||
vpop(), vpop();
|
vpop(), vpop();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int adjust_bf(SValue *sv, int bit_pos, int bit_size)
|
static int adjust_bf(SValue *sv)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
if (0 == sv->type.ref)
|
if (0 == sv->type.ref)
|
||||||
|
@ -1571,7 +1572,7 @@ static int adjust_bf(SValue *sv, int bit_pos, int bit_size)
|
||||||
/* store vtop a register belonging to class 'rc'. lvalues are
|
/* store vtop a register belonging to class 'rc'. lvalues are
|
||||||
converted to values. Cannot be used if cannot be converted to
|
converted to values. Cannot be used if cannot be converted to
|
||||||
register value (such as structures). */
|
register value (such as structures). */
|
||||||
ST_FUNC int gv(int rc)
|
int gv(int rc)
|
||||||
{
|
{
|
||||||
int r, r2, r_ok, r2_ok, rc2, bt;
|
int r, r2, r_ok, r2_ok, rc2, bt;
|
||||||
int bit_pos, bit_size, size, align;
|
int bit_pos, bit_size, size, align;
|
||||||
|
@ -1590,7 +1591,7 @@ ST_FUNC int gv(int rc)
|
||||||
if ((vtop->type.t & VT_BTYPE) == VT_BOOL)
|
if ((vtop->type.t & VT_BTYPE) == VT_BOOL)
|
||||||
type.t |= VT_UNSIGNED;
|
type.t |= VT_UNSIGNED;
|
||||||
|
|
||||||
r = adjust_bf(vtop, bit_pos, bit_size);
|
r = adjust_bf(vtop);
|
||||||
|
|
||||||
if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
|
if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
|
||||||
type.t |= VT_LLONG;
|
type.t |= VT_LLONG;
|
||||||
|
@ -1616,7 +1617,7 @@ ST_FUNC int gv(int rc)
|
||||||
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
||||||
/* CPUs usually cannot use float constants, so we store them
|
/* CPUs usually cannot use float constants, so we store them
|
||||||
generically in data segment */
|
generically in data segment */
|
||||||
init_params p = { rodata_section };
|
init_params p = { rodata_section, 0, NULL };
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
size = type_size(&vtop->type, &align);
|
size = type_size(&vtop->type, &align);
|
||||||
if (NODATA_WANTED)
|
if (NODATA_WANTED)
|
||||||
|
@ -1709,7 +1710,7 @@ ST_FUNC int gv(int rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
|
/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
|
||||||
ST_FUNC void gv2(int rc1, int rc2)
|
void gv2(int rc1, int rc2)
|
||||||
{
|
{
|
||||||
/* generate more generic register first. But VT_JMP or VT_CMP
|
/* generate more generic register first. But VT_JMP or VT_CMP
|
||||||
values must be generated first in all cases to avoid possible
|
values must be generated first in all cases to avoid possible
|
||||||
|
@ -1739,7 +1740,7 @@ ST_FUNC void gv2(int rc1, int rc2)
|
||||||
|
|
||||||
#if PTR_SIZE == 4
|
#if PTR_SIZE == 4
|
||||||
/* expand 64bit on stack in two ints */
|
/* expand 64bit on stack in two ints */
|
||||||
ST_FUNC void lexpand(void)
|
void lexpand(void)
|
||||||
{
|
{
|
||||||
int u, v;
|
int u, v;
|
||||||
u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED);
|
u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED);
|
||||||
|
@ -2031,10 +2032,6 @@ static void gen_opl(int op)
|
||||||
else if (op1 == TOK_GE)
|
else if (op1 == TOK_GE)
|
||||||
op1 = TOK_UGE;
|
op1 = TOK_UGE;
|
||||||
gen_op(op1);
|
gen_op(op1);
|
||||||
#if 0//def TCC_TARGET_I386
|
|
||||||
if (op == TOK_NE) { gsym(b); break; }
|
|
||||||
if (op == TOK_EQ) { gsym(a); break; }
|
|
||||||
#endif
|
|
||||||
gvtst_set(1, a);
|
gvtst_set(1, a);
|
||||||
gvtst_set(0, b);
|
gvtst_set(0, b);
|
||||||
break;
|
break;
|
||||||
|
@ -2216,10 +2213,6 @@ static void gen_opif(int op)
|
||||||
{
|
{
|
||||||
int c1, c2, i, bt;
|
int c1, c2, i, bt;
|
||||||
SValue *v1, *v2;
|
SValue *v1, *v2;
|
||||||
#if defined _MSC_VER && defined __x86_64__
|
|
||||||
/* avoid bad optimization with f1 -= f2 for f1:-0.0, f2:0.0 */
|
|
||||||
volatile
|
|
||||||
#endif
|
|
||||||
long double f1, f2;
|
long double f1, f2;
|
||||||
|
|
||||||
v1 = vtop - 1;
|
v1 = vtop - 1;
|
||||||
|
@ -2389,6 +2382,7 @@ static void type_to_str(char *buf, int buf_size,
|
||||||
tstr = "double";
|
tstr = "double";
|
||||||
if (!(t & VT_LONG))
|
if (!(t & VT_LONG))
|
||||||
goto add_tstr;
|
goto add_tstr;
|
||||||
|
// fall through
|
||||||
case VT_LDOUBLE:
|
case VT_LDOUBLE:
|
||||||
tstr = "long double";
|
tstr = "long double";
|
||||||
add_tstr:
|
add_tstr:
|
||||||
|
@ -2703,7 +2697,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generic gen_op: handles types problems */
|
/* generic gen_op: handles types problems */
|
||||||
ST_FUNC void gen_op(int op)
|
void gen_op(int op)
|
||||||
{
|
{
|
||||||
int t1, t2, bt1, bt2, t;
|
int t1, t2, bt1, bt2, t;
|
||||||
CType type1, combtype;
|
CType type1, combtype;
|
||||||
|
@ -2845,7 +2839,7 @@ static void gen_cvt_itof1(int t)
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
PUT_R_RET(vtop, t);
|
PUT_R_RET(vtop, t);
|
||||||
} else {
|
} else {
|
||||||
gen_cvt_itof(t);
|
gen_cvt_itof();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3012,7 +3006,7 @@ error:
|
||||||
if (sf || df) {
|
if (sf || df) {
|
||||||
if (sf && df) {
|
if (sf && df) {
|
||||||
/* convert from fp to fp */
|
/* convert from fp to fp */
|
||||||
gen_cvt_ftof(dbt);
|
gen_cvt_ftof();
|
||||||
} else if (df) {
|
} else if (df) {
|
||||||
/* convert int to fp */
|
/* convert int to fp */
|
||||||
gen_cvt_itof1(dbt);
|
gen_cvt_itof1(dbt);
|
||||||
|
@ -3122,7 +3116,7 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return type size as known at compile time. Put alignment at 'a' */
|
/* return type size as known at compile time. Put alignment at 'a' */
|
||||||
ST_FUNC int type_size(CType *type, int *a)
|
int type_size(CType *type, int *a)
|
||||||
{
|
{
|
||||||
Sym *s;
|
Sym *s;
|
||||||
int bt;
|
int bt;
|
||||||
|
@ -3152,11 +3146,7 @@ ST_FUNC int type_size(CType *type, int *a)
|
||||||
*a = LDOUBLE_ALIGN;
|
*a = LDOUBLE_ALIGN;
|
||||||
return LDOUBLE_SIZE;
|
return LDOUBLE_SIZE;
|
||||||
} else if (bt == VT_DOUBLE || bt == VT_LLONG) {
|
} else if (bt == VT_DOUBLE || bt == VT_LLONG) {
|
||||||
#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE)
|
|
||||||
*a = 4;
|
*a = 4;
|
||||||
#else
|
|
||||||
*a = 8;
|
|
||||||
#endif
|
|
||||||
return 8;
|
return 8;
|
||||||
} else if (bt == VT_INT || bt == VT_FLOAT) {
|
} else if (bt == VT_INT || bt == VT_FLOAT) {
|
||||||
*a = 4;
|
*a = 4;
|
||||||
|
@ -3196,7 +3186,7 @@ static inline CType *pointed_type(CType *type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* modify type so that its it is a pointer to type. */
|
/* modify type so that its it is a pointer to type. */
|
||||||
ST_FUNC void mk_pointer(CType *type)
|
void mk_pointer(CType *type)
|
||||||
{
|
{
|
||||||
Sym *s;
|
Sym *s;
|
||||||
s = sym_push(SYM_FIELD, type, 0, -1);
|
s = sym_push(SYM_FIELD, type, 0, -1);
|
||||||
|
@ -3317,7 +3307,7 @@ static void gen_assign_cast(CType *dt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store vtop in lvalue pushed on stack */
|
/* store vtop in lvalue pushed on stack */
|
||||||
ST_FUNC void vstore(void)
|
void vstore(void)
|
||||||
{
|
{
|
||||||
int sbt, dbt, ft, r, size, align, bit_size, bit_pos, delayed_cast;
|
int sbt, dbt, ft, r, size, align, bit_size, bit_pos, delayed_cast;
|
||||||
|
|
||||||
|
@ -3369,7 +3359,7 @@ ST_FUNC void vstore(void)
|
||||||
gen_cast(&vtop[-1].type);
|
gen_cast(&vtop[-1].type);
|
||||||
vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
|
vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
|
||||||
}
|
}
|
||||||
r = adjust_bf(vtop - 1, bit_pos, bit_size);
|
r = adjust_bf(vtop - 1);
|
||||||
if (dbt != VT_BOOL) {
|
if (dbt != VT_BOOL) {
|
||||||
gen_cast(&vtop[-1].type);
|
gen_cast(&vtop[-1].type);
|
||||||
dbt = vtop[-1].type.t & VT_BTYPE;
|
dbt = vtop[-1].type.t & VT_BTYPE;
|
||||||
|
@ -3463,7 +3453,7 @@ ST_FUNC void vstore(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* post defines POST/PRE add. c is the token ++ or -- */
|
/* post defines POST/PRE add. c is the token ++ or -- */
|
||||||
ST_FUNC void inc(int post, int c)
|
void inc(int post, int c)
|
||||||
{
|
{
|
||||||
test_lvalue();
|
test_lvalue();
|
||||||
vdup(); /* save lvalue */
|
vdup(); /* save lvalue */
|
||||||
|
@ -3480,7 +3470,7 @@ ST_FUNC void inc(int post, int c)
|
||||||
vpop(); /* if post op, return saved value */
|
vpop(); /* if post op, return saved value */
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC CString* parse_mult_str (const char *msg)
|
CString* parse_mult_str (const char *msg)
|
||||||
{
|
{
|
||||||
/* read the string */
|
/* read the string */
|
||||||
if (tok != TOK_STR)
|
if (tok != TOK_STR)
|
||||||
|
@ -3497,7 +3487,7 @@ ST_FUNC CString* parse_mult_str (const char *msg)
|
||||||
|
|
||||||
/* If I is >= 1 and a power of two, returns log2(i)+1.
|
/* If I is >= 1 and a power of two, returns log2(i)+1.
|
||||||
If I is 0 returns 0. */
|
If I is 0 returns 0. */
|
||||||
ST_FUNC int exact_log2p1(int i)
|
int exact_log2p1(int i)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
if (!i)
|
if (!i)
|
||||||
|
@ -3638,7 +3628,6 @@ redo:
|
||||||
case TOK_STDCALL3:
|
case TOK_STDCALL3:
|
||||||
ad->f.func_call = FUNC_STDCALL;
|
ad->f.func_call = FUNC_STDCALL;
|
||||||
break;
|
break;
|
||||||
#ifdef TCC_TARGET_I386
|
|
||||||
case TOK_REGPARM1:
|
case TOK_REGPARM1:
|
||||||
case TOK_REGPARM2:
|
case TOK_REGPARM2:
|
||||||
skip('(');
|
skip('(');
|
||||||
|
@ -3661,7 +3650,6 @@ redo:
|
||||||
case TOK_THISCALL3:
|
case TOK_THISCALL3:
|
||||||
ad->f.func_call = FUNC_THISCALL;
|
ad->f.func_call = FUNC_THISCALL;
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case TOK_MODE:
|
case TOK_MODE:
|
||||||
skip('(');
|
skip('(');
|
||||||
switch(tok) {
|
switch(tok) {
|
||||||
|
@ -4553,7 +4541,7 @@ static inline void convert_parameter_type(CType *pt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC CString* parse_asm_str(void)
|
CString* parse_asm_str(void)
|
||||||
{
|
{
|
||||||
skip('(');
|
skip('(');
|
||||||
return parse_mult_str("string constant");
|
return parse_mult_str("string constant");
|
||||||
|
@ -4865,7 +4853,7 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* indirection with full error checking and bound check */
|
/* indirection with full error checking and bound check */
|
||||||
ST_FUNC void indir(void)
|
void indir(void)
|
||||||
{
|
{
|
||||||
if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
|
if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
|
||||||
if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
|
if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
|
||||||
|
@ -4972,12 +4960,14 @@ static void parse_builtin_params(int nc, const char *args)
|
||||||
continue;
|
continue;
|
||||||
case 'V':
|
case 'V':
|
||||||
type.t = VT_CONSTANT;
|
type.t = VT_CONSTANT;
|
||||||
|
// fall through
|
||||||
case 'v':
|
case 'v':
|
||||||
type.t |= VT_VOID;
|
type.t |= VT_VOID;
|
||||||
mk_pointer (&type);
|
mk_pointer (&type);
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
type.t = VT_CONSTANT;
|
type.t = VT_CONSTANT;
|
||||||
|
// fall through
|
||||||
case 's':
|
case 's':
|
||||||
type.t |= char_type.t;
|
type.t |= char_type.t;
|
||||||
mk_pointer (&type);
|
mk_pointer (&type);
|
||||||
|
@ -5132,7 +5122,7 @@ static void parse_atomic(int atok)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void unary(void)
|
void unary(void)
|
||||||
{
|
{
|
||||||
int n, t, align, size, r;
|
int n, t, align, size, r;
|
||||||
CType type;
|
CType type;
|
||||||
|
@ -6176,7 +6166,7 @@ static void expr_eq(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gexpr(void)
|
void gexpr(void)
|
||||||
{
|
{
|
||||||
expr_eq();
|
expr_eq();
|
||||||
if (tok == ',') {
|
if (tok == ',') {
|
||||||
|
@ -6217,7 +6207,7 @@ static inline int64_t expr_const64(void)
|
||||||
|
|
||||||
/* parse an integer constant and return its value.
|
/* parse an integer constant and return its value.
|
||||||
Complain if it doesn't fit 32bit (signed or unsigned). */
|
Complain if it doesn't fit 32bit (signed or unsigned). */
|
||||||
ST_FUNC int expr_const(void)
|
int expr_const(void)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
int64_t wc = expr_const64();
|
int64_t wc = expr_const64();
|
||||||
|
@ -7680,13 +7670,11 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
p.local_offset = addr + size;
|
p.local_offset = addr + size;
|
||||||
if (v) {
|
if (v) {
|
||||||
/* local variable */
|
/* local variable */
|
||||||
#ifdef CONFIG_TCC_ASM
|
|
||||||
if (ad->asm_label) {
|
if (ad->asm_label) {
|
||||||
int reg = asm_parse_regvar(ad->asm_label);
|
int reg = asm_parse_regvar(ad->asm_label);
|
||||||
if (reg >= 0)
|
if (reg >= 0)
|
||||||
r = (r & ~VT_VALMASK) | reg;
|
r = (r & ~VT_VALMASK) | reg;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
sym = sym_push(v, type, r, addr);
|
sym = sym_push(v, type, r, addr);
|
||||||
if (ad->cleanup_func) {
|
if (ad->cleanup_func) {
|
||||||
Sym *cls = sym_push2(&all_cleanups,
|
Sym *cls = sym_push2(&all_cleanups,
|
||||||
|
@ -7733,8 +7721,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
sec = rodata_section;
|
sec = rodata_section;
|
||||||
} else if (has_init) {
|
} else if (has_init) {
|
||||||
sec = data_section;
|
sec = data_section;
|
||||||
/*if (tcc_state->g_debug & 4)
|
|
||||||
tcc_warning("rw data: %s", get_tok_str(v, 0));*/
|
|
||||||
} else if (tcc_state->nocommon)
|
} else if (tcc_state->nocommon)
|
||||||
sec = bss_section;
|
sec = bss_section;
|
||||||
}
|
}
|
||||||
|
|
2007
libtcc/tccpe.c
2007
libtcc/tccpe.c
File diff suppressed because it is too large
Load diff
126
libtcc/tccpp.c
126
libtcc/tccpp.c
|
@ -21,6 +21,9 @@
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
|
#include "token.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
/* #define to 1 to enable (see parse_pp_string()) */
|
/* #define to 1 to enable (see parse_pp_string()) */
|
||||||
#define ACCEPT_LF_IN_STRINGS 0
|
#define ACCEPT_LF_IN_STRINGS 0
|
||||||
|
@ -28,19 +31,19 @@
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
/* global variables */
|
/* global variables */
|
||||||
|
|
||||||
ST_DATA int tok_flags;
|
int tok_flags;
|
||||||
ST_DATA int parse_flags;
|
int parse_flags;
|
||||||
|
|
||||||
ST_DATA struct BufferedFile *file;
|
struct BufferedFile *file;
|
||||||
ST_DATA int tok;
|
int tok;
|
||||||
ST_DATA CValue tokc;
|
CValue tokc;
|
||||||
ST_DATA const int *macro_ptr;
|
const int *macro_ptr;
|
||||||
ST_DATA CString tokcstr; /* current parsed string, if any */
|
CString tokcstr; /* current parsed string, if any */
|
||||||
|
|
||||||
/* display benchmark infos */
|
/* display benchmark infos */
|
||||||
ST_DATA int tok_ident;
|
int tok_ident;
|
||||||
ST_DATA TokenSym **table_ident;
|
TokenSym **table_ident;
|
||||||
ST_DATA int pp_expr;
|
int pp_expr;
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
@ -64,7 +67,7 @@ static TokenString *macro_stack;
|
||||||
|
|
||||||
static const char tcc_keywords[] =
|
static const char tcc_keywords[] =
|
||||||
#define DEF(id, str) str "\0"
|
#define DEF(id, str) str "\0"
|
||||||
#include "tcctok.h"
|
#include "token.inc"
|
||||||
#undef DEF
|
#undef DEF
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -98,7 +101,7 @@ static const unsigned char tok_two_chars[] =
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
ST_FUNC void skip(int c)
|
void skip(int c)
|
||||||
{
|
{
|
||||||
if (tok != c) {
|
if (tok != c) {
|
||||||
char tmp[40];
|
char tmp[40];
|
||||||
|
@ -108,7 +111,7 @@ ST_FUNC void skip(int c)
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void expect(const char *msg)
|
void expect(const char *msg)
|
||||||
{
|
{
|
||||||
tcc_error("%s expected", msg);
|
tcc_error("%s expected", msg);
|
||||||
}
|
}
|
||||||
|
@ -339,7 +342,7 @@ static void cstr_realloc(CString *cstr, int new_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a byte */
|
/* add a byte */
|
||||||
ST_INLN void cstr_ccat(CString *cstr, int ch)
|
void cstr_ccat(CString *cstr, int ch)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
size = cstr->size + 1;
|
size = cstr->size + 1;
|
||||||
|
@ -349,7 +352,7 @@ ST_INLN void cstr_ccat(CString *cstr, int ch)
|
||||||
cstr->size = size;
|
cstr->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_INLN char *unicode_to_utf8 (char *b, uint32_t Uc)
|
char *unicode_to_utf8 (char *b, uint32_t Uc)
|
||||||
{
|
{
|
||||||
if (Uc<0x80) *b++=Uc;
|
if (Uc<0x80) *b++=Uc;
|
||||||
else if (Uc<0x800) *b++=192+Uc/64, *b++=128+Uc%64;
|
else if (Uc<0x800) *b++=192+Uc/64, *b++=128+Uc%64;
|
||||||
|
@ -361,7 +364,7 @@ ST_INLN char *unicode_to_utf8 (char *b, uint32_t Uc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a unicode character expanded into utf8 */
|
/* add a unicode character expanded into utf8 */
|
||||||
ST_INLN void cstr_u8cat(CString *cstr, int ch)
|
void cstr_u8cat(CString *cstr, int ch)
|
||||||
{
|
{
|
||||||
char buf[4], *e;
|
char buf[4], *e;
|
||||||
e = unicode_to_utf8(buf, (uint32_t)ch);
|
e = unicode_to_utf8(buf, (uint32_t)ch);
|
||||||
|
@ -369,7 +372,7 @@ ST_INLN void cstr_u8cat(CString *cstr, int ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add string of 'len', or of its len/len+1 when 'len' == -1/0 */
|
/* add string of 'len', or of its len/len+1 when 'len' == -1/0 */
|
||||||
ST_FUNC void cstr_cat(CString *cstr, const char *str, int len)
|
void cstr_cat(CString *cstr, const char *str, int len)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
|
@ -382,7 +385,7 @@ ST_FUNC void cstr_cat(CString *cstr, const char *str, int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a wide char */
|
/* add a wide char */
|
||||||
ST_FUNC void cstr_wccat(CString *cstr, int ch)
|
void cstr_wccat(CString *cstr, int ch)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
size = cstr->size + sizeof(nwchar_t);
|
size = cstr->size + sizeof(nwchar_t);
|
||||||
|
@ -392,24 +395,24 @@ ST_FUNC void cstr_wccat(CString *cstr, int ch)
|
||||||
cstr->size = size;
|
cstr->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void cstr_new(CString *cstr)
|
void cstr_new(CString *cstr)
|
||||||
{
|
{
|
||||||
memset(cstr, 0, sizeof(CString));
|
memset(cstr, 0, sizeof(CString));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free string and reset it to NULL */
|
/* free string and reset it to NULL */
|
||||||
ST_FUNC void cstr_free(CString *cstr)
|
void cstr_free(CString *cstr)
|
||||||
{
|
{
|
||||||
tcc_free(cstr->data);
|
tcc_free(cstr->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset string to empty */
|
/* reset string to empty */
|
||||||
ST_FUNC void cstr_reset(CString *cstr)
|
void cstr_reset(CString *cstr)
|
||||||
{
|
{
|
||||||
cstr->size = 0;
|
cstr->size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap)
|
int cstr_vprintf(CString *cstr, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
va_list v;
|
va_list v;
|
||||||
int len, size = 80;
|
int len, size = 80;
|
||||||
|
@ -429,7 +432,7 @@ ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int cstr_printf(CString *cstr, const char *fmt, ...)
|
int cstr_printf(CString *cstr, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap; int len;
|
va_list ap; int len;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
@ -496,7 +499,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
|
||||||
|
|
||||||
|
|
||||||
/* find a token and add it if not found */
|
/* find a token and add it if not found */
|
||||||
ST_FUNC TokenSym *tok_alloc(const char *str, int len)
|
TokenSym *tok_alloc(const char *str, int len)
|
||||||
{
|
{
|
||||||
TokenSym *ts, **pts;
|
TokenSym *ts, **pts;
|
||||||
int i;
|
int i;
|
||||||
|
@ -519,7 +522,7 @@ ST_FUNC TokenSym *tok_alloc(const char *str, int len)
|
||||||
return tok_alloc_new(pts, str, len);
|
return tok_alloc_new(pts, str, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int tok_alloc_const(const char *str)
|
int tok_alloc_const(const char *str)
|
||||||
{
|
{
|
||||||
return tok_alloc(str, strlen(str))->tok;
|
return tok_alloc(str, strlen(str))->tok;
|
||||||
}
|
}
|
||||||
|
@ -527,7 +530,7 @@ ST_FUNC int tok_alloc_const(const char *str)
|
||||||
|
|
||||||
/* XXX: buffer overflow */
|
/* XXX: buffer overflow */
|
||||||
/* XXX: float tokens */
|
/* XXX: float tokens */
|
||||||
ST_FUNC const char *get_tok_str(int v, CValue *cv)
|
const char *get_tok_str(int v, CValue *cv)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
int i, len;
|
int i, len;
|
||||||
|
@ -551,6 +554,7 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv)
|
||||||
break;
|
break;
|
||||||
case TOK_LCHAR:
|
case TOK_LCHAR:
|
||||||
cstr_ccat(&cstr_buf, 'L');
|
cstr_ccat(&cstr_buf, 'L');
|
||||||
|
// fall through
|
||||||
case TOK_CCHAR:
|
case TOK_CCHAR:
|
||||||
cstr_ccat(&cstr_buf, '\'');
|
cstr_ccat(&cstr_buf, '\'');
|
||||||
add_char(&cstr_buf, cv->i);
|
add_char(&cstr_buf, cv->i);
|
||||||
|
@ -562,6 +566,7 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv)
|
||||||
return (char*)cv->str.data;
|
return (char*)cv->str.data;
|
||||||
case TOK_LSTR:
|
case TOK_LSTR:
|
||||||
cstr_ccat(&cstr_buf, 'L');
|
cstr_ccat(&cstr_buf, 'L');
|
||||||
|
// fall through
|
||||||
case TOK_STR:
|
case TOK_STR:
|
||||||
cstr_ccat(&cstr_buf, '\"');
|
cstr_ccat(&cstr_buf, '\"');
|
||||||
if (v == TOK_STR) {
|
if (v == TOK_STR) {
|
||||||
|
@ -1000,7 +1005,7 @@ static inline int tok_size(const int *p)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* token string handling */
|
/* token string handling */
|
||||||
ST_INLN void tok_str_new(TokenString *s)
|
void tok_str_new(TokenString *s)
|
||||||
{
|
{
|
||||||
s->str = NULL;
|
s->str = NULL;
|
||||||
s->len = s->need_spc = 0;
|
s->len = s->need_spc = 0;
|
||||||
|
@ -1008,25 +1013,25 @@ ST_INLN void tok_str_new(TokenString *s)
|
||||||
s->last_line_num = -1;
|
s->last_line_num = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC TokenString *tok_str_alloc(void)
|
TokenString *tok_str_alloc(void)
|
||||||
{
|
{
|
||||||
TokenString *str = tal_realloc(tokstr_alloc, 0, sizeof *str);
|
TokenString *str = tal_realloc(tokstr_alloc, 0, sizeof *str);
|
||||||
tok_str_new(str);
|
tok_str_new(str);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tok_str_free_str(int *str)
|
void tok_str_free_str(int *str)
|
||||||
{
|
{
|
||||||
tal_free(tokstr_alloc, str);
|
tal_free(tokstr_alloc, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tok_str_free(TokenString *str)
|
void tok_str_free(TokenString *str)
|
||||||
{
|
{
|
||||||
tok_str_free_str(str->str);
|
tok_str_free_str(str->str);
|
||||||
tal_free(tokstr_alloc, str);
|
tal_free(tokstr_alloc, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int *tok_str_realloc(TokenString *s, int new_size)
|
int *tok_str_realloc(TokenString *s, int new_size)
|
||||||
{
|
{
|
||||||
int *str, size;
|
int *str, size;
|
||||||
|
|
||||||
|
@ -1043,7 +1048,7 @@ ST_FUNC int *tok_str_realloc(TokenString *s, int new_size)
|
||||||
return s->str;
|
return s->str;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tok_str_add(TokenString *s, int t)
|
void tok_str_add(TokenString *s, int t)
|
||||||
{
|
{
|
||||||
int len, *str;
|
int len, *str;
|
||||||
|
|
||||||
|
@ -1055,7 +1060,7 @@ ST_FUNC void tok_str_add(TokenString *s, int t)
|
||||||
s->len = len;
|
s->len = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void begin_macro(TokenString *str, int alloc)
|
void begin_macro(TokenString *str, int alloc)
|
||||||
{
|
{
|
||||||
str->alloc = alloc;
|
str->alloc = alloc;
|
||||||
str->prev = macro_stack;
|
str->prev = macro_stack;
|
||||||
|
@ -1065,7 +1070,7 @@ ST_FUNC void begin_macro(TokenString *str, int alloc)
|
||||||
macro_stack = str;
|
macro_stack = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void end_macro(void)
|
void end_macro(void)
|
||||||
{
|
{
|
||||||
TokenString *str = macro_stack;
|
TokenString *str = macro_stack;
|
||||||
macro_stack = str->prev;
|
macro_stack = str->prev;
|
||||||
|
@ -1154,7 +1159,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add the current parse token in token string 's' */
|
/* add the current parse token in token string 's' */
|
||||||
ST_FUNC void tok_str_add_tok(TokenString *s)
|
void tok_str_add_tok(TokenString *s)
|
||||||
{
|
{
|
||||||
CValue cval;
|
CValue cval;
|
||||||
|
|
||||||
|
@ -1272,7 +1277,7 @@ static int macro_is_equal(const int *a, const int *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* defines handling */
|
/* defines handling */
|
||||||
ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg)
|
void define_push(int v, int macro_type, int *str, Sym *first_arg)
|
||||||
{
|
{
|
||||||
Sym *s, *o;
|
Sym *s, *o;
|
||||||
|
|
||||||
|
@ -1287,14 +1292,14 @@ ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* undefined a define symbol. Its name is just set to zero */
|
/* undefined a define symbol. Its name is just set to zero */
|
||||||
ST_FUNC void define_undef(Sym *s)
|
void define_undef(Sym *s)
|
||||||
{
|
{
|
||||||
int v = s->v;
|
int v = s->v;
|
||||||
if (v >= TOK_IDENT && v < tok_ident)
|
if (v >= TOK_IDENT && v < tok_ident)
|
||||||
table_ident[v - TOK_IDENT]->sym_define = NULL;
|
table_ident[v - TOK_IDENT]->sym_define = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_INLN Sym *define_find(int v)
|
Sym *define_find(int v)
|
||||||
{
|
{
|
||||||
v -= TOK_IDENT;
|
v -= TOK_IDENT;
|
||||||
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
||||||
|
@ -1303,7 +1308,7 @@ ST_INLN Sym *define_find(int v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free define stack until top reaches 'b' */
|
/* free define stack until top reaches 'b' */
|
||||||
ST_FUNC void free_defines(Sym *b)
|
void free_defines(Sym *b)
|
||||||
{
|
{
|
||||||
while (define_stack != b) {
|
while (define_stack != b) {
|
||||||
Sym *top = define_stack;
|
Sym *top = define_stack;
|
||||||
|
@ -1314,22 +1319,7 @@ ST_FUNC void free_defines(Sym *b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fake the nth "#if defined test_..." for tcc -dt -run */
|
void skip_to_eol(int warn)
|
||||||
static void maybe_run_test(TCCState *s)
|
|
||||||
{
|
|
||||||
const char *p;
|
|
||||||
if (s->include_stack_ptr != s->include_stack)
|
|
||||||
return;
|
|
||||||
p = get_tok_str(tok, NULL);
|
|
||||||
if (0 != memcmp(p, "test_", 5))
|
|
||||||
return;
|
|
||||||
/*if (0 != --s->run_test)
|
|
||||||
return;*/
|
|
||||||
fprintf(s->ppfp, &"\n[%s]\n"[!(s->dflag & 32)], p), fflush(s->ppfp);
|
|
||||||
define_push(tok, MACRO_OBJ, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
ST_FUNC void skip_to_eol(int warn)
|
|
||||||
{
|
{
|
||||||
if (tok == TOK_LINEFEED)
|
if (tok == TOK_LINEFEED)
|
||||||
return;
|
return;
|
||||||
|
@ -1521,7 +1511,7 @@ static int expr_preprocess(TCCState *s1)
|
||||||
return c != 0;
|
return c != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void pp_error(CString *cs)
|
void pp_error(CString *cs)
|
||||||
{
|
{
|
||||||
cstr_printf(cs, "bad preprocessor expression: #%s", get_tok_str(pp_expr, 0));
|
cstr_printf(cs, "bad preprocessor expression: #%s", get_tok_str(pp_expr, 0));
|
||||||
macro_ptr = macro_stack->str;
|
macro_ptr = macro_stack->str;
|
||||||
|
@ -1530,7 +1520,7 @@ ST_FUNC void pp_error(CString *cs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse after #define */
|
/* parse after #define */
|
||||||
ST_FUNC void parse_define(void)
|
void parse_define(void)
|
||||||
{
|
{
|
||||||
Sym *s, *first, **ps;
|
Sym *s, *first, **ps;
|
||||||
int v, t, varg, is_vaargs, t0;
|
int v, t, varg, is_vaargs, t0;
|
||||||
|
@ -1780,7 +1770,7 @@ pragma_err:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* put alternative filename */
|
/* put alternative filename */
|
||||||
ST_FUNC void tccpp_putfile(const char *filename)
|
void tccpp_putfile(const char *filename)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
|
@ -1802,7 +1792,7 @@ ST_FUNC void tccpp_putfile(const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is_bof is true if first non space token at beginning of file */
|
/* is_bof is true if first non space token at beginning of file */
|
||||||
ST_FUNC void preprocess(int is_bof)
|
void preprocess(int is_bof)
|
||||||
{
|
{
|
||||||
TCCState *s1 = tcc_state;
|
TCCState *s1 = tcc_state;
|
||||||
int c, n, saved_parse_flags;
|
int c, n, saved_parse_flags;
|
||||||
|
@ -2659,7 +2649,7 @@ maybe_newline:
|
||||||
if (!(isidnum_table['$' - CH_EOF] & IS_ID)
|
if (!(isidnum_table['$' - CH_EOF] & IS_ID)
|
||||||
|| (parse_flags & PARSE_FLAG_ASM_FILE))
|
|| (parse_flags & PARSE_FLAG_ASM_FILE))
|
||||||
goto parse_simple;
|
goto parse_simple;
|
||||||
|
// fall through
|
||||||
case 'a': case 'b': case 'c': case 'd':
|
case 'a': case 'b': case 'c': case 'd':
|
||||||
case 'e': case 'f': case 'g': case 'h':
|
case 'e': case 'f': case 'g': case 'h':
|
||||||
case 'i': case 'j': case 'k': case 'l':
|
case 'i': case 'j': case 'k': case 'l':
|
||||||
|
@ -3465,7 +3455,7 @@ static int macro_subst(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return next token with macro substitution */
|
/* return next token with macro substitution */
|
||||||
ST_FUNC void next(void)
|
void next(void)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
while (macro_ptr) {
|
while (macro_ptr) {
|
||||||
|
@ -3524,7 +3514,7 @@ convert:
|
||||||
|
|
||||||
/* push back current token and set current token to 'last_tok'. Only
|
/* push back current token and set current token to 'last_tok'. Only
|
||||||
identifier case handled for labels. */
|
identifier case handled for labels. */
|
||||||
ST_INLN void unget_tok(int last_tok)
|
void unget_tok(int last_tok)
|
||||||
{
|
{
|
||||||
TokenString *str = &unget_buf;
|
TokenString *str = &unget_buf;
|
||||||
int alloc = 0;
|
int alloc = 0;
|
||||||
|
@ -3595,7 +3585,7 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm)
|
||||||
cstr_printf(cs, "#define __BASE_FILE__ \"%s\"\n", file->filename);
|
cstr_printf(cs, "#define __BASE_FILE__ \"%s\"\n", file->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void preprocess_start(TCCState *s1, int filetype)
|
void preprocess_start(TCCState *s1, int filetype)
|
||||||
{
|
{
|
||||||
int is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP));
|
int is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP));
|
||||||
|
|
||||||
|
@ -3631,7 +3621,7 @@ ST_FUNC void preprocess_start(TCCState *s1, int filetype)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cleanup from error/setjmp */
|
/* cleanup from error/setjmp */
|
||||||
ST_FUNC void preprocess_end(TCCState *s1)
|
void preprocess_end(TCCState *s1)
|
||||||
{
|
{
|
||||||
while (macro_stack)
|
while (macro_stack)
|
||||||
end_macro();
|
end_macro();
|
||||||
|
@ -3641,14 +3631,14 @@ ST_FUNC void preprocess_end(TCCState *s1)
|
||||||
tccpp_delete(s1);
|
tccpp_delete(s1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int set_idnum(int c, int val)
|
int set_idnum(int c, int val)
|
||||||
{
|
{
|
||||||
int prev = isidnum_table[c - CH_EOF];
|
int prev = isidnum_table[c - CH_EOF];
|
||||||
isidnum_table[c - CH_EOF] = val;
|
isidnum_table[c - CH_EOF] = val;
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tccpp_new(TCCState *s)
|
void tccpp_new(TCCState *s)
|
||||||
{
|
{
|
||||||
int i, c;
|
int i, c;
|
||||||
const char *p, *r;
|
const char *p, *r;
|
||||||
|
@ -3700,7 +3690,7 @@ ST_FUNC void tccpp_new(TCCState *s)
|
||||||
define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL);
|
define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tccpp_delete(TCCState *s)
|
void tccpp_delete(TCCState *s)
|
||||||
{
|
{
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
|
@ -3852,7 +3842,7 @@ static int pp_check_he0xE(int t, const char *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Preprocess the current file */
|
/* Preprocess the current file */
|
||||||
ST_FUNC int tcc_preprocess(TCCState *s1)
|
int tcc_preprocess(TCCState *s1)
|
||||||
{
|
{
|
||||||
BufferedFile **iptr;
|
BufferedFile **iptr;
|
||||||
int token_seen, spcs, level;
|
int token_seen, spcs, level;
|
||||||
|
|
98
libtcc/token.h
Normal file
98
libtcc/token.h
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#ifndef TCC_TOKEN_H
|
||||||
|
# define TCC_TOKEN_H 1
|
||||||
|
|
||||||
|
/* conditional ops */
|
||||||
|
# define TOK_LAND 0x90
|
||||||
|
# define TOK_LOR 0x91
|
||||||
|
/* warning: the following compare tokens depend on i386 asm code */
|
||||||
|
# define TOK_ULT 0x92
|
||||||
|
# define TOK_UGE 0x93
|
||||||
|
# define TOK_EQ 0x94
|
||||||
|
# define TOK_NE 0x95
|
||||||
|
# define TOK_ULE 0x96
|
||||||
|
# define TOK_UGT 0x97
|
||||||
|
# define TOK_Nset 0x98
|
||||||
|
# define TOK_Nclear 0x99
|
||||||
|
# define TOK_LT 0x9c
|
||||||
|
# define TOK_GE 0x9d
|
||||||
|
# define TOK_LE 0x9e
|
||||||
|
# define TOK_GT 0x9f
|
||||||
|
|
||||||
|
# define TOK_ISCOND(t) (t >= TOK_LAND && t <= TOK_GT)
|
||||||
|
|
||||||
|
# define TOK_DEC 0x80 /* -- */
|
||||||
|
# define TOK_MID 0x81 /* inc/dec, to void constant */
|
||||||
|
# define TOK_INC 0x82 /* ++ */
|
||||||
|
# define TOK_UDIV 0x83 /* unsigned division */
|
||||||
|
# define TOK_UMOD 0x84 /* unsigned modulo */
|
||||||
|
# define TOK_PDIV 0x85 /* fast division with undefined rounding for pointers */
|
||||||
|
# define TOK_UMULL 0x86 /* unsigned 32x32 -> 64 mul */
|
||||||
|
# define TOK_ADDC1 0x87 /* add with carry generation */
|
||||||
|
# define TOK_ADDC2 0x88 /* add with carry use */
|
||||||
|
# define TOK_SUBC1 0x89 /* add with carry generation */
|
||||||
|
# define TOK_SUBC2 0x8a /* add with carry use */
|
||||||
|
# define TOK_SHL '<' /* shift left */
|
||||||
|
# define TOK_SAR '>' /* signed shift right */
|
||||||
|
# define TOK_SHR 0x8b /* unsigned shift right */
|
||||||
|
# define TOK_NEG TOK_MID /* unary minus operation (for floats) */
|
||||||
|
|
||||||
|
# define TOK_ARROW 0xa0 /* -> */
|
||||||
|
# define TOK_DOTS 0xa1 /* three dots */
|
||||||
|
# define TOK_TWODOTS 0xa2 /* C++ token ? */
|
||||||
|
# define TOK_TWOSHARPS 0xa3 /* ## preprocessing token */
|
||||||
|
# define TOK_PLCHLDR 0xa4 /* placeholder token as defined in C99 */
|
||||||
|
# define TOK_PPJOIN (TOK_TWOSHARPS | SYM_FIELD) /* A '##' in a macro to mean pasting */
|
||||||
|
# define TOK_SOTYPE 0xa7 /* alias of '(' for parsing sizeof (type) */
|
||||||
|
|
||||||
|
/* assignment operators */
|
||||||
|
# define TOK_A_ADD 0xb0
|
||||||
|
# define TOK_A_SUB 0xb1
|
||||||
|
# define TOK_A_MUL 0xb2
|
||||||
|
# define TOK_A_DIV 0xb3
|
||||||
|
# define TOK_A_MOD 0xb4
|
||||||
|
# define TOK_A_AND 0xb5
|
||||||
|
# define TOK_A_OR 0xb6
|
||||||
|
# define TOK_A_XOR 0xb7
|
||||||
|
# define TOK_A_SHL 0xb8
|
||||||
|
# define TOK_A_SAR 0xb9
|
||||||
|
|
||||||
|
# define TOK_ASSIGN(t) (t >= TOK_A_ADD && t <= TOK_A_SAR)
|
||||||
|
# define TOK_ASSIGN_OP(t) ("+-*/%&|^<>"[t - TOK_A_ADD])
|
||||||
|
|
||||||
|
/* tokens that carry values (in additional token string space / tokc) --> */
|
||||||
|
# define TOK_CCHAR 0xc0 /* char constant in tokc */
|
||||||
|
# define TOK_LCHAR 0xc1
|
||||||
|
# define TOK_CINT 0xc2 /* number in tokc */
|
||||||
|
# define TOK_CUINT 0xc3 /* unsigned int constant */
|
||||||
|
# define TOK_CLLONG 0xc4 /* long long constant */
|
||||||
|
# define TOK_CULLONG 0xc5 /* unsigned long long constant */
|
||||||
|
# define TOK_CLONG 0xc6 /* long constant */
|
||||||
|
# define TOK_CULONG 0xc7 /* unsigned long constant */
|
||||||
|
# define TOK_STR 0xc8 /* pointer to string in tokc */
|
||||||
|
# define TOK_LSTR 0xc9
|
||||||
|
# define TOK_CFLOAT 0xca /* float constant */
|
||||||
|
# define TOK_CDOUBLE 0xcb /* double constant */
|
||||||
|
# define TOK_CLDOUBLE 0xcc /* long double constant */
|
||||||
|
# define TOK_PPNUM 0xcd /* preprocessor number */
|
||||||
|
# define TOK_PPSTR 0xce /* preprocessor string */
|
||||||
|
# define TOK_LINENUM 0xcf /* line number info */
|
||||||
|
|
||||||
|
# define TOK_HAS_VALUE(t) (t >= TOK_CCHAR && t <= TOK_LINENUM)
|
||||||
|
|
||||||
|
# define TOK_EOF (-1) /* end of file */
|
||||||
|
# define TOK_LINEFEED 10 /* line feed */
|
||||||
|
|
||||||
|
/* all identifiers and strings have token above that */
|
||||||
|
# define TOK_IDENT 256
|
||||||
|
|
||||||
|
enum tcc_token {
|
||||||
|
TOK_LAST = TOK_IDENT - 1
|
||||||
|
# define DEF(id, str) ,id
|
||||||
|
# include "token.inc"
|
||||||
|
# undef DEF
|
||||||
|
};
|
||||||
|
|
||||||
|
/* keywords: tok >= TOK_IDENT && tok < TOK_UIDENT */
|
||||||
|
# define TOK_UIDENT TOK_DEFINE
|
||||||
|
|
||||||
|
#endif /* !TCC_TOKEN_H */
|
|
@ -265,4 +265,4 @@
|
||||||
DEF_ASMDIR(symver)
|
DEF_ASMDIR(symver)
|
||||||
DEF_ASMDIR(section) /* must be last directive */
|
DEF_ASMDIR(section) /* must be last directive */
|
||||||
|
|
||||||
#include "i386/tok.h"
|
#include "i386/token.inc"
|
21
libtcc/utils/cstr.h
Normal file
21
libtcc/utils/cstr.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef LIBTCC_UTILS_CSTR_H
|
||||||
|
# define LIBTCC_UTILS_CSTR_H 1
|
||||||
|
|
||||||
|
# include <stdarg.h>
|
||||||
|
|
||||||
|
typedef struct CString {
|
||||||
|
int size;
|
||||||
|
int size_allocated;
|
||||||
|
char *data;
|
||||||
|
} CString;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#endif /* !LIBTCC_UTILS_CSTR_H */
|
20
libtcc1/Makefile.am
Normal file
20
libtcc1/Makefile.am
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
COMPILE = ../tcc/tcc
|
||||||
|
|
||||||
|
noinst_LIBRARIES = libtcc1.a
|
||||||
|
|
||||||
|
libtcc1_a_SOURCES = alloca.S atomic.S builtin.c libtcc1.c stdatomic.c
|
||||||
|
|
||||||
|
alloca.o: alloca.S
|
||||||
|
$(COMPILE) -o $@ -c $^ -I$(srcdir)/include
|
||||||
|
|
||||||
|
atomic.o: atomic.S
|
||||||
|
$(COMPILE) -o $@ -c $^ -I$(srcdir)/include
|
||||||
|
|
||||||
|
builtin.o: builtin.c
|
||||||
|
$(COMPILE) -o $@ -c $^ -I$(srcdir)/include
|
||||||
|
|
||||||
|
libtcc1.o: libtcc1.c
|
||||||
|
$(COMPILE) -o $@ -c $^ -I$(srcdir)/include
|
||||||
|
|
||||||
|
stdatomic.o: stdatomic.c
|
||||||
|
$(COMPILE) -o $@ -c $^ -I$(srcdir)/include
|
|
@ -1,96 +0,0 @@
|
||||||
/* ---------------------------------------------- */
|
|
||||||
/* alloca-bt.S */
|
|
||||||
|
|
||||||
#ifdef __leading_underscore
|
|
||||||
# define _(s) _##s
|
|
||||||
#else
|
|
||||||
# define _(s) s
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
#if defined __i386__
|
|
||||||
|
|
||||||
.globl _(__bound_alloca)
|
|
||||||
_(__bound_alloca):
|
|
||||||
pop %edx
|
|
||||||
pop %eax
|
|
||||||
mov %eax, %ecx
|
|
||||||
add $3+1,%eax
|
|
||||||
and $-4,%eax
|
|
||||||
jz p6
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
p4:
|
|
||||||
cmp $4096,%eax
|
|
||||||
jbe p5
|
|
||||||
test %eax,-4096(%esp)
|
|
||||||
sub $4096,%esp
|
|
||||||
sub $4096,%eax
|
|
||||||
jmp p4
|
|
||||||
|
|
||||||
p5:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sub %eax,%esp
|
|
||||||
mov %esp,%eax
|
|
||||||
|
|
||||||
push %edx
|
|
||||||
push %eax
|
|
||||||
push %ecx
|
|
||||||
push %eax
|
|
||||||
call _(__bound_new_region)
|
|
||||||
add $8, %esp
|
|
||||||
pop %eax
|
|
||||||
pop %edx
|
|
||||||
|
|
||||||
p6:
|
|
||||||
push %edx
|
|
||||||
push %edx
|
|
||||||
ret
|
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
#elif defined __x86_64__
|
|
||||||
|
|
||||||
.globl _(__bound_alloca)
|
|
||||||
_(__bound_alloca):
|
|
||||||
#ifdef _WIN32
|
|
||||||
inc %rcx # add one extra to separate regions
|
|
||||||
jmp _(alloca)
|
|
||||||
.globl _(__bound_alloca_nr)
|
|
||||||
_(__bound_alloca_nr):
|
|
||||||
dec %rcx
|
|
||||||
push %rax
|
|
||||||
mov %rcx,%rdx
|
|
||||||
mov %rax,%rcx
|
|
||||||
sub $32,%rsp
|
|
||||||
call _(__bound_new_region)
|
|
||||||
add $32,%rsp
|
|
||||||
pop %rax
|
|
||||||
ret
|
|
||||||
#else
|
|
||||||
pop %rdx
|
|
||||||
mov %rdi,%rax
|
|
||||||
mov %rax,%rsi # size, a second parm to the __bound_new_region
|
|
||||||
|
|
||||||
add $15 + 1,%rax # add one extra to separate regions
|
|
||||||
and $-16,%rax
|
|
||||||
jz p3
|
|
||||||
|
|
||||||
|
|
||||||
sub %rax,%rsp
|
|
||||||
mov %rsp,%rdi # pointer, a first parm to the __bound_new_region
|
|
||||||
mov %rsp,%rax
|
|
||||||
|
|
||||||
push %rdx
|
|
||||||
push %rax
|
|
||||||
call _(__bound_new_region)
|
|
||||||
pop %rax
|
|
||||||
pop %rdx
|
|
||||||
|
|
||||||
p3:
|
|
||||||
push %rdx
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
#endif
|
|
|
@ -7,9 +7,6 @@
|
||||||
# define _(s) s
|
# define _(s) s
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
#if defined __i386__
|
|
||||||
|
|
||||||
.globl _(alloca), _(__alloca)
|
.globl _(alloca), _(__alloca)
|
||||||
_(alloca):
|
_(alloca):
|
||||||
_(__alloca):
|
_(__alloca):
|
||||||
|
@ -35,51 +32,3 @@ p2:
|
||||||
push %eax
|
push %eax
|
||||||
lea 8(%esp),%eax
|
lea 8(%esp),%eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
#elif defined __x86_64__
|
|
||||||
|
|
||||||
.globl _(alloca)
|
|
||||||
_(alloca):
|
|
||||||
pop %rdx
|
|
||||||
#ifdef _WIN32
|
|
||||||
mov %rcx,%rax
|
|
||||||
#else
|
|
||||||
mov %rdi,%rax
|
|
||||||
#endif
|
|
||||||
add $15,%rax
|
|
||||||
and $-16,%rax
|
|
||||||
jz p3
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
p1:
|
|
||||||
cmp $4096,%rax
|
|
||||||
jbe p2
|
|
||||||
test %rax,-4096(%rsp)
|
|
||||||
sub $4096,%rsp
|
|
||||||
sub $4096,%rax
|
|
||||||
jmp p1
|
|
||||||
p2:
|
|
||||||
#endif
|
|
||||||
sub %rax,%rsp
|
|
||||||
mov %rsp,%rax
|
|
||||||
p3:
|
|
||||||
push %rdx
|
|
||||||
ret
|
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
#elif defined __arm__
|
|
||||||
|
|
||||||
.text
|
|
||||||
.align 2
|
|
||||||
.global alloca
|
|
||||||
.type alloca, %function
|
|
||||||
alloca:
|
|
||||||
rsb sp, r0, sp
|
|
||||||
bic sp, sp, #7
|
|
||||||
mov r0, sp
|
|
||||||
mov pc, lr
|
|
||||||
.size alloca, .-alloca
|
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,544 +0,0 @@
|
||||||
/* TCC ARM runtime EABI
|
|
||||||
Copyright (C) 2013 Thomas Preud'homme
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.*/
|
|
||||||
|
|
||||||
#ifdef __TINYC__
|
|
||||||
#define INT_MIN (-2147483647 - 1)
|
|
||||||
#define INT_MAX 2147483647
|
|
||||||
#define UINT_MAX 0xffffffff
|
|
||||||
#define LONG_MIN (-2147483647L - 1)
|
|
||||||
#define LONG_MAX 2147483647L
|
|
||||||
#define ULONG_MAX 0xffffffffUL
|
|
||||||
#define LLONG_MAX 9223372036854775807LL
|
|
||||||
#define LLONG_MIN (-9223372036854775807LL - 1)
|
|
||||||
#define ULLONG_MAX 0xffffffffffffffffULL
|
|
||||||
#else
|
|
||||||
#include <limits.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We rely on the little endianness and EABI calling convention for this to
|
|
||||||
work */
|
|
||||||
|
|
||||||
typedef struct double_unsigned_struct {
|
|
||||||
unsigned low;
|
|
||||||
unsigned high;
|
|
||||||
} double_unsigned_struct;
|
|
||||||
|
|
||||||
typedef struct unsigned_int_struct {
|
|
||||||
unsigned low;
|
|
||||||
int high;
|
|
||||||
} unsigned_int_struct;
|
|
||||||
|
|
||||||
#define REGS_RETURN(name, type) \
|
|
||||||
void name ## _return(type ret) {}
|
|
||||||
|
|
||||||
|
|
||||||
/* Float helper functions */
|
|
||||||
|
|
||||||
#define FLOAT_EXP_BITS 8
|
|
||||||
#define FLOAT_FRAC_BITS 23
|
|
||||||
|
|
||||||
#define DOUBLE_EXP_BITS 11
|
|
||||||
#define DOUBLE_FRAC_BITS 52
|
|
||||||
|
|
||||||
#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
|
|
||||||
|
|
||||||
REGS_RETURN(unsigned_int_struct, unsigned_int_struct)
|
|
||||||
REGS_RETURN(double_unsigned_struct, double_unsigned_struct)
|
|
||||||
|
|
||||||
/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
|
|
||||||
|
|
||||||
|
|
||||||
/* float to [unsigned] long long conversion */
|
|
||||||
#define DEFINE__AEABI_F2XLZ(name, with_sign) \
|
|
||||||
void __aeabi_ ## name(unsigned val) \
|
|
||||||
{ \
|
|
||||||
int exp, high_shift, sign; \
|
|
||||||
double_unsigned_struct ret; \
|
|
||||||
\
|
|
||||||
/* compute sign */ \
|
|
||||||
sign = val >> 31; \
|
|
||||||
\
|
|
||||||
/* compute real exponent */ \
|
|
||||||
exp = val >> FLOAT_FRAC_BITS; \
|
|
||||||
exp &= (1 << FLOAT_EXP_BITS) - 1; \
|
|
||||||
exp -= ONE_EXP(FLOAT); \
|
|
||||||
\
|
|
||||||
/* undefined behavior if truncated value cannot be represented */ \
|
|
||||||
if (with_sign) { \
|
|
||||||
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
|
|
||||||
return; \
|
|
||||||
} else { \
|
|
||||||
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
|
|
||||||
return; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
val &= (1 << FLOAT_FRAC_BITS) - 1; \
|
|
||||||
if (exp >= 32) { \
|
|
||||||
ret.high = 1 << (exp - 32); \
|
|
||||||
if (exp - 32 >= FLOAT_FRAC_BITS) { \
|
|
||||||
ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
|
|
||||||
ret.low = 0; \
|
|
||||||
} else { \
|
|
||||||
high_shift = FLOAT_FRAC_BITS - (exp - 32); \
|
|
||||||
ret.high |= val >> high_shift; \
|
|
||||||
ret.low = val << (32 - high_shift); \
|
|
||||||
} \
|
|
||||||
} else { \
|
|
||||||
ret.high = 0; \
|
|
||||||
ret.low = 1 << exp; \
|
|
||||||
if (exp > FLOAT_FRAC_BITS) \
|
|
||||||
ret.low |= val << (exp - FLOAT_FRAC_BITS); \
|
|
||||||
else \
|
|
||||||
ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* encode negative integer using 2's complement */ \
|
|
||||||
if (with_sign && sign) { \
|
|
||||||
ret.low = ~ret.low; \
|
|
||||||
ret.high = ~ret.high; \
|
|
||||||
if (ret.low == UINT_MAX) { \
|
|
||||||
ret.low = 0; \
|
|
||||||
ret.high++; \
|
|
||||||
} else \
|
|
||||||
ret.low++; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
double_unsigned_struct_return(ret); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* float to unsigned long long conversion */
|
|
||||||
DEFINE__AEABI_F2XLZ(f2ulz, 0)
|
|
||||||
|
|
||||||
/* float to long long conversion */
|
|
||||||
DEFINE__AEABI_F2XLZ(f2lz, 1)
|
|
||||||
|
|
||||||
/* double to [unsigned] long long conversion */
|
|
||||||
#define DEFINE__AEABI_D2XLZ(name, with_sign) \
|
|
||||||
void __aeabi_ ## name(double_unsigned_struct val) \
|
|
||||||
{ \
|
|
||||||
int exp, high_shift, sign; \
|
|
||||||
double_unsigned_struct ret; \
|
|
||||||
\
|
|
||||||
if ((val.high & ~0x80000000) == 0 && val.low == 0) { \
|
|
||||||
ret.low = ret.high = 0; \
|
|
||||||
goto _ret_; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* compute sign */ \
|
|
||||||
sign = val.high >> 31; \
|
|
||||||
\
|
|
||||||
/* compute real exponent */ \
|
|
||||||
exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
|
|
||||||
exp &= (1 << DOUBLE_EXP_BITS) - 1; \
|
|
||||||
exp -= ONE_EXP(DOUBLE); \
|
|
||||||
\
|
|
||||||
/* undefined behavior if truncated value cannot be represented */ \
|
|
||||||
if (with_sign) { \
|
|
||||||
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
|
|
||||||
return; \
|
|
||||||
} else { \
|
|
||||||
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
|
|
||||||
return; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
|
|
||||||
if (exp >= 32) { \
|
|
||||||
ret.high = 1 << (exp - 32); \
|
|
||||||
if (exp >= DOUBLE_FRAC_BITS) { \
|
|
||||||
high_shift = exp - DOUBLE_FRAC_BITS; \
|
|
||||||
ret.high |= val.high << high_shift; \
|
|
||||||
ret.high |= val.low >> (32 - high_shift); \
|
|
||||||
ret.low = val.low << high_shift; \
|
|
||||||
} else { \
|
|
||||||
high_shift = DOUBLE_FRAC_BITS - exp; \
|
|
||||||
ret.high |= val.high >> high_shift; \
|
|
||||||
ret.low = val.high << (32 - high_shift); \
|
|
||||||
ret.low |= val.low >> high_shift; \
|
|
||||||
} \
|
|
||||||
} else { \
|
|
||||||
ret.high = 0; \
|
|
||||||
ret.low = 1 << exp; \
|
|
||||||
if (exp > DOUBLE_FRAC_BITS - 32) { \
|
|
||||||
high_shift = exp - DOUBLE_FRAC_BITS - 32; \
|
|
||||||
ret.low |= val.high << high_shift; \
|
|
||||||
ret.low |= val.low >> (32 - high_shift); \
|
|
||||||
} else \
|
|
||||||
ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* encode negative integer using 2's complement */ \
|
|
||||||
if (with_sign && sign) { \
|
|
||||||
ret.low = ~ret.low; \
|
|
||||||
ret.high = ~ret.high; \
|
|
||||||
if (ret.low == UINT_MAX) { \
|
|
||||||
ret.low = 0; \
|
|
||||||
ret.high++; \
|
|
||||||
} else \
|
|
||||||
ret.low++; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
_ret_: \
|
|
||||||
double_unsigned_struct_return(ret); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* double to unsigned long long conversion */
|
|
||||||
DEFINE__AEABI_D2XLZ(d2ulz, 0)
|
|
||||||
|
|
||||||
/* double to long long conversion */
|
|
||||||
DEFINE__AEABI_D2XLZ(d2lz, 1)
|
|
||||||
|
|
||||||
/* long long to float conversion */
|
|
||||||
#define DEFINE__AEABI_XL2F(name, with_sign) \
|
|
||||||
unsigned __aeabi_ ## name(unsigned long long v) \
|
|
||||||
{ \
|
|
||||||
int s /* shift */, flb /* first lost bit */, sign = 0; \
|
|
||||||
unsigned p = 0 /* power */, ret; \
|
|
||||||
double_unsigned_struct val; \
|
|
||||||
\
|
|
||||||
/* fraction in negative float is encoded in 1's complement */ \
|
|
||||||
if (with_sign && (v & (1ULL << 63))) { \
|
|
||||||
sign = 1; \
|
|
||||||
v = ~v + 1; \
|
|
||||||
} \
|
|
||||||
val.low = v; \
|
|
||||||
val.high = v >> 32; \
|
|
||||||
/* fill fraction bits */ \
|
|
||||||
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
|
|
||||||
if (p) { \
|
|
||||||
ret = val.high & (p - 1); \
|
|
||||||
if (s < FLOAT_FRAC_BITS) { \
|
|
||||||
ret <<= FLOAT_FRAC_BITS - s; \
|
|
||||||
ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \
|
|
||||||
flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \
|
|
||||||
} else { \
|
|
||||||
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
|
|
||||||
ret >>= s - FLOAT_FRAC_BITS; \
|
|
||||||
} \
|
|
||||||
s += 32; \
|
|
||||||
} else { \
|
|
||||||
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
|
|
||||||
if (p) { \
|
|
||||||
ret = val.low & (p - 1); \
|
|
||||||
if (s <= FLOAT_FRAC_BITS) { \
|
|
||||||
ret <<= FLOAT_FRAC_BITS - s; \
|
|
||||||
flb = 0; \
|
|
||||||
} else { \
|
|
||||||
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
|
|
||||||
ret >>= s - FLOAT_FRAC_BITS; \
|
|
||||||
} \
|
|
||||||
} else \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
if (flb) \
|
|
||||||
ret++; \
|
|
||||||
\
|
|
||||||
/* fill exponent bits */ \
|
|
||||||
ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
|
|
||||||
\
|
|
||||||
/* fill sign bit */ \
|
|
||||||
ret |= sign << 31; \
|
|
||||||
\
|
|
||||||
return ret; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* unsigned long long to float conversion */
|
|
||||||
DEFINE__AEABI_XL2F(ul2f, 0)
|
|
||||||
|
|
||||||
/* long long to float conversion */
|
|
||||||
DEFINE__AEABI_XL2F(l2f, 1)
|
|
||||||
|
|
||||||
/* long long to double conversion */
|
|
||||||
#define __AEABI_XL2D(name, with_sign) \
|
|
||||||
void __aeabi_ ## name(unsigned long long v) \
|
|
||||||
{ \
|
|
||||||
int s /* shift */, high_shift, sign = 0; \
|
|
||||||
unsigned tmp, p = 0; \
|
|
||||||
double_unsigned_struct val, ret; \
|
|
||||||
\
|
|
||||||
/* fraction in negative float is encoded in 1's complement */ \
|
|
||||||
if (with_sign && (v & (1ULL << 63))) { \
|
|
||||||
sign = 1; \
|
|
||||||
v = ~v + 1; \
|
|
||||||
} \
|
|
||||||
val.low = v; \
|
|
||||||
val.high = v >> 32; \
|
|
||||||
\
|
|
||||||
/* fill fraction bits */ \
|
|
||||||
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
|
|
||||||
if (p) { \
|
|
||||||
tmp = val.high & (p - 1); \
|
|
||||||
if (s < DOUBLE_FRAC_BITS - 32) { \
|
|
||||||
high_shift = DOUBLE_FRAC_BITS - 32 - s; \
|
|
||||||
ret.high = tmp << high_shift; \
|
|
||||||
ret.high |= val.low >> (32 - high_shift); \
|
|
||||||
ret.low = val.low << high_shift; \
|
|
||||||
} else { \
|
|
||||||
high_shift = s - (DOUBLE_FRAC_BITS - 32); \
|
|
||||||
ret.high = tmp >> high_shift; \
|
|
||||||
ret.low = tmp << (32 - high_shift); \
|
|
||||||
ret.low |= val.low >> high_shift; \
|
|
||||||
if ((val.low >> (high_shift - 1)) & 1) { \
|
|
||||||
if (ret.low == UINT_MAX) { \
|
|
||||||
ret.high++; \
|
|
||||||
ret.low = 0; \
|
|
||||||
} else \
|
|
||||||
ret.low++; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
s += 32; \
|
|
||||||
} else { \
|
|
||||||
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
|
|
||||||
if (p) { \
|
|
||||||
tmp = val.low & (p - 1); \
|
|
||||||
if (s <= DOUBLE_FRAC_BITS - 32) { \
|
|
||||||
high_shift = DOUBLE_FRAC_BITS - 32 - s; \
|
|
||||||
ret.high = tmp << high_shift; \
|
|
||||||
ret.low = 0; \
|
|
||||||
} else { \
|
|
||||||
high_shift = s - (DOUBLE_FRAC_BITS - 32); \
|
|
||||||
ret.high = tmp >> high_shift; \
|
|
||||||
ret.low = tmp << (32 - high_shift); \
|
|
||||||
} \
|
|
||||||
} else { \
|
|
||||||
ret.high = ret.low = 0; \
|
|
||||||
goto _ret_; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* fill exponent bits */ \
|
|
||||||
ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
|
|
||||||
\
|
|
||||||
/* fill sign bit */ \
|
|
||||||
ret.high |= sign << 31; \
|
|
||||||
\
|
|
||||||
_ret_: \
|
|
||||||
double_unsigned_struct_return(ret); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* unsigned long long to double conversion */
|
|
||||||
__AEABI_XL2D(ul2d, 0)
|
|
||||||
|
|
||||||
/* long long to double conversion */
|
|
||||||
__AEABI_XL2D(l2d, 1)
|
|
||||||
|
|
||||||
|
|
||||||
/* Long long helper functions */
|
|
||||||
|
|
||||||
/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
|
|
||||||
|
|
||||||
#define define_aeabi_xdivmod_signed_type(basetype, type) \
|
|
||||||
typedef struct type { \
|
|
||||||
basetype quot; \
|
|
||||||
unsigned basetype rem; \
|
|
||||||
} type
|
|
||||||
|
|
||||||
#define define_aeabi_xdivmod_unsigned_type(basetype, type) \
|
|
||||||
typedef struct type { \
|
|
||||||
basetype quot; \
|
|
||||||
basetype rem; \
|
|
||||||
} type
|
|
||||||
|
|
||||||
#define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
|
|
||||||
static inline rettype aeabi_ ## name (type num, type den) \
|
|
||||||
{ \
|
|
||||||
rettype ret; \
|
|
||||||
type quot = 0; \
|
|
||||||
\
|
|
||||||
/* Increase quotient while it is less than numerator */ \
|
|
||||||
while (num >= den) { \
|
|
||||||
type q = 1; \
|
|
||||||
\
|
|
||||||
/* Find closest power of two */ \
|
|
||||||
while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
|
|
||||||
q <<= 1; \
|
|
||||||
\
|
|
||||||
/* Compute difference between current quotient and numerator */ \
|
|
||||||
num -= q * den; \
|
|
||||||
quot += q; \
|
|
||||||
} \
|
|
||||||
ret.quot = quot; \
|
|
||||||
ret.rem = num; \
|
|
||||||
return ret; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
|
|
||||||
void __aeabi_ ## name(type numerator, type denominator) \
|
|
||||||
{ \
|
|
||||||
unsigned type num, den; \
|
|
||||||
urettype uxdiv_ret; \
|
|
||||||
rettype ret; \
|
|
||||||
\
|
|
||||||
if (numerator >= 0) \
|
|
||||||
num = numerator; \
|
|
||||||
else \
|
|
||||||
num = 0 - numerator; \
|
|
||||||
if (denominator >= 0) \
|
|
||||||
den = denominator; \
|
|
||||||
else \
|
|
||||||
den = 0 - denominator; \
|
|
||||||
uxdiv_ret = aeabi_ ## uiname(num, den); \
|
|
||||||
/* signs differ */ \
|
|
||||||
if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
|
|
||||||
ret.quot = 0 - uxdiv_ret.quot; \
|
|
||||||
else \
|
|
||||||
ret.quot = uxdiv_ret.quot; \
|
|
||||||
if (numerator < 0) \
|
|
||||||
ret.rem = 0 - uxdiv_ret.rem; \
|
|
||||||
else \
|
|
||||||
ret.rem = uxdiv_ret.rem; \
|
|
||||||
\
|
|
||||||
rettype ## _return(ret); \
|
|
||||||
}
|
|
||||||
|
|
||||||
define_aeabi_xdivmod_signed_type(long long, lldiv_t);
|
|
||||||
define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t);
|
|
||||||
define_aeabi_xdivmod_signed_type(int, idiv_t);
|
|
||||||
define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t);
|
|
||||||
|
|
||||||
REGS_RETURN(lldiv_t, lldiv_t)
|
|
||||||
REGS_RETURN(ulldiv_t, ulldiv_t)
|
|
||||||
REGS_RETURN(idiv_t, idiv_t)
|
|
||||||
REGS_RETURN(uidiv_t, uidiv_t)
|
|
||||||
|
|
||||||
AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULLONG)
|
|
||||||
|
|
||||||
__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG)
|
|
||||||
|
|
||||||
void __aeabi_uldivmod(unsigned long long num, unsigned long long den)
|
|
||||||
{
|
|
||||||
ulldiv_t_return(aeabi_uldivmod(num, den));
|
|
||||||
}
|
|
||||||
|
|
||||||
void __aeabi_llsl(double_unsigned_struct val, int shift)
|
|
||||||
{
|
|
||||||
double_unsigned_struct ret;
|
|
||||||
|
|
||||||
if (shift >= 32) {
|
|
||||||
val.high = val.low;
|
|
||||||
val.low = 0;
|
|
||||||
shift -= 32;
|
|
||||||
}
|
|
||||||
if (shift > 0) {
|
|
||||||
ret.low = val.low << shift;
|
|
||||||
ret.high = (val.high << shift) | (val.low >> (32 - shift));
|
|
||||||
double_unsigned_struct_return(ret);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
double_unsigned_struct_return(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define aeabi_lsr(val, shift, fill, type) \
|
|
||||||
type ## _struct ret; \
|
|
||||||
\
|
|
||||||
if (shift >= 32) { \
|
|
||||||
val.low = val.high; \
|
|
||||||
val.high = fill; \
|
|
||||||
shift -= 32; \
|
|
||||||
} \
|
|
||||||
if (shift > 0) { \
|
|
||||||
ret.high = val.high >> shift; \
|
|
||||||
ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
|
|
||||||
type ## _struct_return(ret); \
|
|
||||||
return; \
|
|
||||||
} \
|
|
||||||
type ## _struct_return(val);
|
|
||||||
|
|
||||||
void __aeabi_llsr(double_unsigned_struct val, int shift)
|
|
||||||
{
|
|
||||||
aeabi_lsr(val, shift, 0, double_unsigned);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __aeabi_lasr(unsigned_int_struct val, int shift)
|
|
||||||
{
|
|
||||||
aeabi_lsr(val, shift, val.high >> 31, unsigned_int);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Integer division functions */
|
|
||||||
|
|
||||||
AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
|
|
||||||
|
|
||||||
int __aeabi_idiv(int numerator, int denominator)
|
|
||||||
{
|
|
||||||
unsigned num, den;
|
|
||||||
uidiv_t ret;
|
|
||||||
|
|
||||||
if (numerator >= 0)
|
|
||||||
num = numerator;
|
|
||||||
else
|
|
||||||
num = 0 - numerator;
|
|
||||||
if (denominator >= 0)
|
|
||||||
den = denominator;
|
|
||||||
else
|
|
||||||
den = 0 - denominator;
|
|
||||||
ret = aeabi_uidivmod(num, den);
|
|
||||||
if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
|
|
||||||
ret.quot *= -1;
|
|
||||||
return ret.quot;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned __aeabi_uidiv(unsigned num, unsigned den)
|
|
||||||
{
|
|
||||||
return aeabi_uidivmod(num, den).quot;
|
|
||||||
}
|
|
||||||
|
|
||||||
__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT)
|
|
||||||
|
|
||||||
void __aeabi_uidivmod(unsigned num, unsigned den)
|
|
||||||
{
|
|
||||||
uidiv_t_return(aeabi_uidivmod(num, den));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some targets do not have all eabi calls (OpenBSD) */
|
|
||||||
typedef __SIZE_TYPE__ size_t;
|
|
||||||
extern void *memcpy(void *dest, const void *src, size_t n);
|
|
||||||
extern void *memmove(void *dest, const void *src, size_t n);
|
|
||||||
extern void *memset(void *s, int c, size_t n);
|
|
||||||
|
|
||||||
void *
|
|
||||||
__aeabi_memcpy (void *dest, const void *src, size_t n)
|
|
||||||
{
|
|
||||||
return memcpy (dest, src, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
__aeabi_memmove (void *dest, const void *src, size_t n)
|
|
||||||
{
|
|
||||||
return memmove (dest, src, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
__aeabi_memmove4 (void *dest, const void *src, size_t n)
|
|
||||||
{
|
|
||||||
return memmove (dest, src, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
__aeabi_memmove8 (void *dest, const void *src, size_t n)
|
|
||||||
{
|
|
||||||
return memmove (dest, src, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
__aeabi_memset (void *s, size_t n, int c)
|
|
||||||
{
|
|
||||||
return memset (s, c, n);
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
/* armflush.c - flush the instruction cache
|
|
||||||
|
|
||||||
__clear_cache is used in tccrun.c, It is a built-in
|
|
||||||
intrinsic with gcc. However tcc in order to compile
|
|
||||||
itself needs this function */
|
|
||||||
|
|
||||||
#ifdef __TINYC__
|
|
||||||
|
|
||||||
/* syscall wrapper */
|
|
||||||
unsigned _tccsyscall(unsigned syscall_nr, ...);
|
|
||||||
|
|
||||||
/* arm-tcc supports only fake asm currently */
|
|
||||||
__asm__(
|
|
||||||
".global _tccsyscall\n"
|
|
||||||
"_tccsyscall:\n"
|
|
||||||
"push {r7, lr}\n\t"
|
|
||||||
"mov r7, r0\n\t"
|
|
||||||
"mov r0, r1\n\t"
|
|
||||||
"mov r1, r2\n\t"
|
|
||||||
"mov r2, r3\n\t"
|
|
||||||
"svc #0\n\t"
|
|
||||||
"pop {r7, pc}"
|
|
||||||
);
|
|
||||||
|
|
||||||
/* from unistd.h: */
|
|
||||||
#if defined(__thumb__) || defined(__ARM_EABI__)
|
|
||||||
# define __NR_SYSCALL_BASE 0x0
|
|
||||||
#else
|
|
||||||
# define __NR_SYSCALL_BASE 0x900000
|
|
||||||
#endif
|
|
||||||
#define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000)
|
|
||||||
#define __ARM_NR_cacheflush (__ARM_NR_BASE+2)
|
|
||||||
|
|
||||||
#define syscall _tccsyscall
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Flushing for tccrun */
|
|
||||||
void __clear_cache(void *beginning, void *end)
|
|
||||||
{
|
|
||||||
/* __ARM_NR_cacheflush is kernel private and should not be used in user space.
|
|
||||||
* However, there is no ARM asm parser in tcc so we use it for now */
|
|
||||||
syscall(__ARM_NR_cacheflush, beginning, end, 0);
|
|
||||||
}
|
|
824
libtcc1/atomic.S
824
libtcc1/atomic.S
|
@ -12,7 +12,6 @@
|
||||||
# define _(s) s
|
# define _(s) s
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined __i386__
|
|
||||||
.text
|
.text
|
||||||
.align 2
|
.align 2
|
||||||
|
|
||||||
|
@ -33,826 +32,3 @@ _(__atomic_clear):
|
||||||
xchgb (%edx), %al
|
xchgb (%edx), %al
|
||||||
ret
|
ret
|
||||||
.size _(__atomic_clear), .-_(__atomic_clear)
|
.size _(__atomic_clear), .-_(__atomic_clear)
|
||||||
|
|
||||||
#elif defined __x86_64__
|
|
||||||
.text
|
|
||||||
.align 2
|
|
||||||
|
|
||||||
.global _(__atomic_test_and_set)
|
|
||||||
.type _(__atomic_test_and_set), %function
|
|
||||||
_(__atomic_test_and_set):
|
|
||||||
movl $1, %eax
|
|
||||||
xchgb (%rdi), %al
|
|
||||||
ret
|
|
||||||
.size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
|
|
||||||
|
|
||||||
.global _(__atomic_clear)
|
|
||||||
.type _(__atomic_clear), %function
|
|
||||||
_(__atomic_clear):
|
|
||||||
xorl %eax, %eax
|
|
||||||
xchgb (%rdi), %al
|
|
||||||
ret
|
|
||||||
.size _(__atomic_clear), .-_(__atomic_clear)
|
|
||||||
|
|
||||||
#elif defined __arm__
|
|
||||||
|
|
||||||
#ifndef __TINYC__
|
|
||||||
.arch armv6k
|
|
||||||
.syntax unified
|
|
||||||
#endif
|
|
||||||
.text
|
|
||||||
.align 2
|
|
||||||
|
|
||||||
.global _(fetch_and_add_arm)
|
|
||||||
.type _(fetch_and_add_arm), %function
|
|
||||||
_(fetch_and_add_arm):
|
|
||||||
mcr p15, #0, r0, c7, c10, #5
|
|
||||||
.L0:
|
|
||||||
ldrex r3, [r0]
|
|
||||||
add r3, r3, r1
|
|
||||||
strex r2, r3, [r0]
|
|
||||||
cmp r2, #0
|
|
||||||
bne .L0
|
|
||||||
mcr p15, #0, r0, c7, c10, #5
|
|
||||||
bx lr
|
|
||||||
.size _(fetch_and_add_arm), .-_(fetch_and_add_arm)
|
|
||||||
|
|
||||||
.global _(__atomic_test_and_set)
|
|
||||||
.type _(__atomic_test_and_set), %function
|
|
||||||
_(__atomic_test_and_set):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0xe92d4030
|
|
||||||
.int 0xee070fba
|
|
||||||
.int 0xe5d03000
|
|
||||||
.int 0xe24dd014
|
|
||||||
.int 0xe1a05000
|
|
||||||
.int 0xe2533000
|
|
||||||
.int 0xe1a04001
|
|
||||||
.int 0x13a03001
|
|
||||||
.int 0xee070fba
|
|
||||||
.int 0xe5cd300f
|
|
||||||
.int 0xe3a03001
|
|
||||||
.int 0xe1a02003
|
|
||||||
.int 0xe28d100f
|
|
||||||
.int 0xe1a00005
|
|
||||||
.int 0xe58d4004
|
|
||||||
.int 0xe58d4000
|
|
||||||
.int 0xeb000009
|
|
||||||
.int 0xe3500000
|
|
||||||
.int 0x0afffff6
|
|
||||||
.int 0xe5dd000f
|
|
||||||
.int 0xe28dd014
|
|
||||||
.int 0xe8bd8030
|
|
||||||
#else
|
|
||||||
push {r4, r5, lr}
|
|
||||||
mcr p15, 0, r0, c7, c10, 5
|
|
||||||
ldrb r3, [r0]
|
|
||||||
sub sp, sp, #20
|
|
||||||
mov r5, r0
|
|
||||||
subs r3, r3, #0
|
|
||||||
mov r4, r1
|
|
||||||
movne r3, #1
|
|
||||||
mcr p15, 0, r0, c7, c10, 5
|
|
||||||
strb r3, [sp, #15]
|
|
||||||
.L20:
|
|
||||||
mov r3, #1
|
|
||||||
mov r2, r3
|
|
||||||
add r1, sp, #15
|
|
||||||
mov r0, r5
|
|
||||||
str r4, [sp, #4]
|
|
||||||
str r4, [sp]
|
|
||||||
bl __atomic_compare_exchange_1
|
|
||||||
cmp r0, #0
|
|
||||||
beq .L20
|
|
||||||
ldrb r0, [sp, #15]
|
|
||||||
add sp, sp, #20
|
|
||||||
pop {r4, r5, pc}
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
|
|
||||||
|
|
||||||
.global _(__atomic_clear)
|
|
||||||
.type _(__atomic_clear), %function
|
|
||||||
_(__atomic_clear):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0xe3a03000
|
|
||||||
.int 0xee070fba
|
|
||||||
.int 0xe5c03000
|
|
||||||
.int 0xee070fba
|
|
||||||
.int 0xe12fff1e
|
|
||||||
#else
|
|
||||||
mov r3, #0
|
|
||||||
mcr p15, 0, r0, c7, c10, 5
|
|
||||||
strb r3, [r0]
|
|
||||||
mcr p15, 0, r0, c7, c10, 5
|
|
||||||
bx lr
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_clear), .-_(__atomic_clear)
|
|
||||||
|
|
||||||
.global _(__atomic_compare_exchange_1)
|
|
||||||
.type _(__atomic_compare_exchange_1), %function
|
|
||||||
_(__atomic_compare_exchange_1):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0xe52de004
|
|
||||||
.int 0xe5d13000
|
|
||||||
.int 0xf57ff05b
|
|
||||||
.int 0xe1d0cf9f
|
|
||||||
.int 0xe15c0003
|
|
||||||
.int 0x1a000002
|
|
||||||
.int 0xe1c0ef92
|
|
||||||
.int 0xe35e0000
|
|
||||||
.int 0x1afffff9
|
|
||||||
.int 0x03a00001
|
|
||||||
.int 0x13a00000
|
|
||||||
.int 0xf57ff05b
|
|
||||||
.int 0x15c1c000
|
|
||||||
.int 0xe49df004
|
|
||||||
#else
|
|
||||||
str lr, [sp, #-4]!
|
|
||||||
ldrb r3, [r1]
|
|
||||||
mcr p15, 0, r0, c7, c10, 5
|
|
||||||
.L1:
|
|
||||||
ldrexb ip, [r0]
|
|
||||||
cmp ip, r3
|
|
||||||
bne .L2
|
|
||||||
strexb lr, r2, [r0]
|
|
||||||
cmp lr, #0
|
|
||||||
bne .L1
|
|
||||||
.L2:
|
|
||||||
mcr p15, 0, r0, c7, c10, 5
|
|
||||||
moveq r0, #1
|
|
||||||
movne r0, #0
|
|
||||||
strbne ip, [r1]
|
|
||||||
ldr pc, [sp], #4
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1)
|
|
||||||
|
|
||||||
.global _(__atomic_compare_exchange_2)
|
|
||||||
.type _(__atomic_compare_exchange_2), %function
|
|
||||||
_(__atomic_compare_exchange_2):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0xe52de004
|
|
||||||
.int 0xe1d130b0
|
|
||||||
.int 0xf57ff05b
|
|
||||||
.int 0xe1f0cf9f
|
|
||||||
.int 0xe15c0003
|
|
||||||
.int 0x1a000002
|
|
||||||
.int 0xe1e0ef92
|
|
||||||
.int 0xe35e0000
|
|
||||||
.int 0x1afffff9
|
|
||||||
.int 0x03a00001
|
|
||||||
.int 0x13a00000
|
|
||||||
.int 0xf57ff05b
|
|
||||||
.int 0x11c1c0b0
|
|
||||||
.int 0xe49df004
|
|
||||||
#else
|
|
||||||
str lr, [sp, #-4]!
|
|
||||||
ldrh r3, [r1]
|
|
||||||
mcr p15, 0, r0, c7, c10, 5
|
|
||||||
.L3:
|
|
||||||
ldrexh ip, [r0]
|
|
||||||
cmp ip, r3
|
|
||||||
bne .L4
|
|
||||||
strexh lr, r2, [r0]
|
|
||||||
cmp lr, #0
|
|
||||||
bne .L3
|
|
||||||
.L4:
|
|
||||||
mcr p15, 0, r0, c7, c10, 5
|
|
||||||
moveq r0, #1
|
|
||||||
movne r0, #0
|
|
||||||
strhne ip, [r1]
|
|
||||||
ldr pc, [sp], #4
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2)
|
|
||||||
|
|
||||||
.global _(__atomic_compare_exchange_4)
|
|
||||||
.type _(__atomic_compare_exchange_4), %function
|
|
||||||
_(__atomic_compare_exchange_4):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0xe52de004
|
|
||||||
.int 0xe5913000
|
|
||||||
.int 0xf57ff05b
|
|
||||||
.int 0xe190cf9f
|
|
||||||
.int 0xe15c0003
|
|
||||||
.int 0x1a000002
|
|
||||||
.int 0xe180ef92
|
|
||||||
.int 0xe35e0000
|
|
||||||
.int 0x1afffff9
|
|
||||||
.int 0x03a00001
|
|
||||||
.int 0x13a00000
|
|
||||||
.int 0xf57ff05b
|
|
||||||
.int 0x1581c000
|
|
||||||
.int 0xe49df004
|
|
||||||
#else
|
|
||||||
str lr, [sp, #-4]!
|
|
||||||
ldr r3, [r1]
|
|
||||||
mcr p15, 0, r0, c7, c10, 5
|
|
||||||
.L5:
|
|
||||||
ldrex ip, [r0]
|
|
||||||
cmp ip, r3
|
|
||||||
bne .L6
|
|
||||||
strex lr, r2, [r0]
|
|
||||||
cmp lr, #0
|
|
||||||
bne .L5
|
|
||||||
.L6:
|
|
||||||
mcr p15, 0, r0, c7, c10, 5
|
|
||||||
moveq r0, #1
|
|
||||||
movne r0, #0
|
|
||||||
strne ip, [r1]
|
|
||||||
ldr pc, [sp], #4
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4)
|
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
#elif defined __aarch64__
|
|
||||||
|
|
||||||
.text
|
|
||||||
.align 2
|
|
||||||
|
|
||||||
.global _(fetch_and_add_arm64)
|
|
||||||
.type _(fetch_and_add_arm64), %function
|
|
||||||
_(fetch_and_add_arm64):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0x885f7c02
|
|
||||||
.int 0x0b010042
|
|
||||||
.int 0x8803fc02
|
|
||||||
.int 0x35ffffa3
|
|
||||||
.int 0xd5033bbf
|
|
||||||
.int 0xd65f03c0
|
|
||||||
#else
|
|
||||||
ldxr w2, [x0]
|
|
||||||
add w2, w2, w1
|
|
||||||
stlxr w3, w2, [x0]
|
|
||||||
cbnz w3, _(fetch_and_add_arm64)
|
|
||||||
dmb ish
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(fetch_and_add_arm64), .-_(fetch_and_add_arm64)
|
|
||||||
|
|
||||||
.global _(__atomic_test_and_set)
|
|
||||||
.type _(__atomic_test_and_set), %function
|
|
||||||
_(__atomic_test_and_set):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0xa9bf7bfd
|
|
||||||
.int 0xaa0003e1
|
|
||||||
.int 0x52800020
|
|
||||||
.int 0x910003fd
|
|
||||||
.int 0x2a0003f0
|
|
||||||
.int 0x085ffc20
|
|
||||||
.int 0x0811fc30
|
|
||||||
.int 0x35ffffd1
|
|
||||||
.int 0xa8c17bfd
|
|
||||||
.int 0xd65f03c0
|
|
||||||
#else
|
|
||||||
stp x29, x30, [sp, -16]!
|
|
||||||
mov x1, x0
|
|
||||||
mov w0, 1
|
|
||||||
mov x29, sp
|
|
||||||
mov w16, w0
|
|
||||||
.L20:
|
|
||||||
ldaxrb w0, [x1]
|
|
||||||
stlxrb w17, w16, [x1]
|
|
||||||
cbnz w17, .L20
|
|
||||||
ldp x29, x30, [sp], 16
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
|
|
||||||
|
|
||||||
.global _(__atomic_clear)
|
|
||||||
.type _(__atomic_clear), %function
|
|
||||||
_(__atomic_clear):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0x089ffc1f
|
|
||||||
.int 0xd65f03c0
|
|
||||||
#else
|
|
||||||
stlrb wzr, [x0]
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_clear), .-_(__atomic_clear)
|
|
||||||
|
|
||||||
.global _(__atomic_compare_exchange_1)
|
|
||||||
.type _(__atomic_compare_exchange_1), %function
|
|
||||||
_(__atomic_compare_exchange_1):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0xa9be7bfd
|
|
||||||
.int 0x910003fd
|
|
||||||
.int 0xa90153f3
|
|
||||||
.int 0xaa0103f3
|
|
||||||
.int 0x12001c41
|
|
||||||
.int 0xaa0003e2
|
|
||||||
.int 0x39400274
|
|
||||||
.int 0x2a1403e0
|
|
||||||
.int 0x53001c10
|
|
||||||
.int 0x085ffc40
|
|
||||||
.int 0x6b10001f
|
|
||||||
.int 0x54000061
|
|
||||||
.int 0x0811fc41
|
|
||||||
.int 0x35ffff91
|
|
||||||
.int 0x6b34001f
|
|
||||||
.int 0x1a9f17e1
|
|
||||||
.int 0x54000040
|
|
||||||
.int 0x39000260
|
|
||||||
.int 0x2a0103e0
|
|
||||||
.int 0xa94153f3
|
|
||||||
.int 0xa8c27bfd
|
|
||||||
.int 0xd65f03c0
|
|
||||||
#else
|
|
||||||
stp x29, x30, [sp, -32]!
|
|
||||||
mov x29, sp
|
|
||||||
stp x19, x20, [sp, 16]
|
|
||||||
mov x19, x1
|
|
||||||
and w1, w2, 255
|
|
||||||
mov x2, x0
|
|
||||||
ldrb w20, [x19]
|
|
||||||
mov w0, w20
|
|
||||||
uxtb w16, w0
|
|
||||||
.L1:
|
|
||||||
ldaxrb w0, [x2]
|
|
||||||
cmp w0, w16
|
|
||||||
b.ne .L2
|
|
||||||
stlxrb w17, w1, [x2]
|
|
||||||
cbnz w17, .L1
|
|
||||||
.L2:
|
|
||||||
cmp w0, w20, uxtb
|
|
||||||
cset w1, eq
|
|
||||||
beq .L3
|
|
||||||
strb w0, [x19]
|
|
||||||
.L3:
|
|
||||||
mov w0, w1
|
|
||||||
ldp x19, x20, [sp, 16]
|
|
||||||
ldp x29, x30, [sp], 32
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1)
|
|
||||||
|
|
||||||
.global _(__atomic_compare_exchange_2)
|
|
||||||
.type _(__atomic_compare_exchange_2), %function
|
|
||||||
_(__atomic_compare_exchange_2):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0xa9be7bfd
|
|
||||||
.int 0x910003fd
|
|
||||||
.int 0xa90153f3
|
|
||||||
.int 0xaa0103f3
|
|
||||||
.int 0x12003c41
|
|
||||||
.int 0xaa0003e2
|
|
||||||
.int 0x79400274
|
|
||||||
.int 0x2a1403e0
|
|
||||||
.int 0x53003c10
|
|
||||||
.int 0x485ffc40
|
|
||||||
.int 0x6b10001f
|
|
||||||
.int 0x54000061
|
|
||||||
.int 0x4811fc41
|
|
||||||
.int 0x35ffff91
|
|
||||||
.int 0x6b34201f
|
|
||||||
.int 0x1a9f17e1
|
|
||||||
.int 0x54000040
|
|
||||||
.int 0x79000260
|
|
||||||
.int 0x2a0103e0
|
|
||||||
.int 0xa94153f3
|
|
||||||
.int 0xa8c27bfd
|
|
||||||
.int 0xd65f03c0
|
|
||||||
#else
|
|
||||||
stp x29, x30, [sp, -32]!
|
|
||||||
mov x29, sp
|
|
||||||
stp x19, x20, [sp, 16]
|
|
||||||
mov x19, x1
|
|
||||||
and w1, w2, 65535
|
|
||||||
mov x2, x0
|
|
||||||
ldrh w20, [x19]
|
|
||||||
mov w0, w20
|
|
||||||
uxth w16, w0
|
|
||||||
.L4:
|
|
||||||
ldaxrh w0, [x2]
|
|
||||||
cmp w0, w16
|
|
||||||
b.ne .L5
|
|
||||||
stlxrh w17, w1, [x2]
|
|
||||||
cbnz w17, .L4
|
|
||||||
.L5:
|
|
||||||
cmp w0, w20, uxth
|
|
||||||
cset w1, eq
|
|
||||||
beq .L6
|
|
||||||
strh w0, [x19]
|
|
||||||
.L6:
|
|
||||||
mov w0, w1
|
|
||||||
ldp x19, x20, [sp, 16]
|
|
||||||
ldp x29, x30, [sp], 32
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2)
|
|
||||||
|
|
||||||
.global _(__atomic_compare_exchange_4)
|
|
||||||
.type _(__atomic_compare_exchange_4), %function
|
|
||||||
_(__atomic_compare_exchange_4):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0xa9be7bfd
|
|
||||||
.int 0x910003fd
|
|
||||||
.int 0xa90153f3
|
|
||||||
.int 0xaa0103f3
|
|
||||||
.int 0x2a0203e1
|
|
||||||
.int 0xaa0003e2
|
|
||||||
.int 0xb9400274
|
|
||||||
.int 0x2a1403e0
|
|
||||||
.int 0x2a0003f0
|
|
||||||
.int 0x885ffc40
|
|
||||||
.int 0x6b10001f
|
|
||||||
.int 0x54000061
|
|
||||||
.int 0x8811fc41
|
|
||||||
.int 0x35ffff91
|
|
||||||
.int 0x6b14001f
|
|
||||||
.int 0x1a9f17e1
|
|
||||||
.int 0x54000040
|
|
||||||
.int 0xb9000260
|
|
||||||
.int 0x2a0103e0
|
|
||||||
.int 0xa94153f3
|
|
||||||
.int 0xa8c27bfd
|
|
||||||
.int 0xd65f03c0
|
|
||||||
#else
|
|
||||||
stp x29, x30, [sp, -32]!
|
|
||||||
mov x29, sp
|
|
||||||
stp x19, x20, [sp, 16]
|
|
||||||
mov x19, x1
|
|
||||||
mov w1, w2
|
|
||||||
mov x2, x0
|
|
||||||
ldr w20, [x19]
|
|
||||||
mov w0, w20
|
|
||||||
mov w16, w0
|
|
||||||
.L7:
|
|
||||||
ldaxr w0, [x2]
|
|
||||||
cmp w0, w16
|
|
||||||
b.ne .L8
|
|
||||||
stlxr w17, w1, [x2]
|
|
||||||
cbnz w17, .L7
|
|
||||||
.L8:
|
|
||||||
cmp w0, w20
|
|
||||||
cset w1, eq
|
|
||||||
beq .L9
|
|
||||||
str w0, [x19]
|
|
||||||
.L9:
|
|
||||||
mov w0, w1
|
|
||||||
ldp x19, x20, [sp, 16]
|
|
||||||
ldp x29, x30, [sp], 32
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4)
|
|
||||||
|
|
||||||
.global _(__atomic_compare_exchange_8)
|
|
||||||
.type _(__atomic_compare_exchange_8), %function
|
|
||||||
_(__atomic_compare_exchange_8):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0xa9be7bfd
|
|
||||||
.int 0x910003fd
|
|
||||||
.int 0xa90153f3
|
|
||||||
.int 0xaa0103f3
|
|
||||||
.int 0xaa0203e1
|
|
||||||
.int 0xaa0003e2
|
|
||||||
.int 0xf9400274
|
|
||||||
.int 0xaa1403e0
|
|
||||||
.int 0xaa0003f0
|
|
||||||
.int 0xc85ffc40
|
|
||||||
.int 0xeb10001f
|
|
||||||
.int 0x54000061
|
|
||||||
.int 0xc811fc41
|
|
||||||
.int 0x35ffff91
|
|
||||||
.int 0xeb14001f
|
|
||||||
.int 0x1a9f17e1
|
|
||||||
.int 0x54000040
|
|
||||||
.int 0xf9000260
|
|
||||||
.int 0x2a0103e0
|
|
||||||
.int 0xa94153f3
|
|
||||||
.int 0xa8c27bfd
|
|
||||||
.int 0xd65f03c0
|
|
||||||
#else
|
|
||||||
stp x29, x30, [sp, -32]!
|
|
||||||
mov x29, sp
|
|
||||||
stp x19, x20, [sp, 16]
|
|
||||||
mov x19, x1
|
|
||||||
mov x1, x2
|
|
||||||
mov x2, x0
|
|
||||||
ldr x20, [x19]
|
|
||||||
mov x0, x20
|
|
||||||
mov x16, x0
|
|
||||||
.L10:
|
|
||||||
ldaxr x0, [x2]
|
|
||||||
cmp x0, x16
|
|
||||||
b.ne .L11
|
|
||||||
stlxr w17, x1, [x2]
|
|
||||||
cbnz w17, .L10
|
|
||||||
.L11:
|
|
||||||
cmp x0, x20
|
|
||||||
cset w1, eq
|
|
||||||
beq .L12
|
|
||||||
str x0, [x19]
|
|
||||||
.L12:
|
|
||||||
mov w0, w1
|
|
||||||
ldp x19, x20, [sp, 16]
|
|
||||||
ldp x29, x30, [sp], 32
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_compare_exchange_8), .-_(__atomic_compare_exchange_8)
|
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
#elif defined __riscv
|
|
||||||
|
|
||||||
.text
|
|
||||||
.align 2
|
|
||||||
|
|
||||||
.global _(fetch_and_add_riscv64)
|
|
||||||
.type _(fetch_and_add_riscv64), %function
|
|
||||||
_(fetch_and_add_riscv64):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0x0f50000f
|
|
||||||
.int 0x004b5202f
|
|
||||||
.short 0x8082
|
|
||||||
#else
|
|
||||||
fence iorw,ow
|
|
||||||
amoadd.w.aq zero,a1,0(a0)
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(fetch_and_add_riscv64), .-_(fetch_and_add_riscv64)
|
|
||||||
|
|
||||||
.global _(__atomic_test_and_set)
|
|
||||||
.type _(__atomic_test_and_set), %function
|
|
||||||
_(__atomic_test_and_set):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0x00357793
|
|
||||||
.int 0x0037979b
|
|
||||||
.short 0x4685
|
|
||||||
.short 0x9971
|
|
||||||
.int 0x00f696bb
|
|
||||||
.int 0x0f50000f
|
|
||||||
.int 0x44d5272f
|
|
||||||
.int 0x00f7553b
|
|
||||||
.int 0x0ff57513
|
|
||||||
.short 0x8082
|
|
||||||
#else
|
|
||||||
andi a5,a0,3
|
|
||||||
slliw a5,a5,3
|
|
||||||
li a3,1
|
|
||||||
andi a0,a0,-4
|
|
||||||
sllw a3,a3,a5
|
|
||||||
fence iorw,ow; amoor.w.aq a4,a3,0(a0)
|
|
||||||
srlw a0,a4,a5
|
|
||||||
andi a0,a0,0xff
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
|
|
||||||
|
|
||||||
.global _(__atomic_clear)
|
|
||||||
.type _(__atomic_clear), %function
|
|
||||||
_(__atomic_clear):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0x0ff0000f
|
|
||||||
.int 0x00050023
|
|
||||||
.int 0x0ff0000f
|
|
||||||
.short 0x8082
|
|
||||||
#else
|
|
||||||
fence iorw,iorw
|
|
||||||
sb zero,0(a0)
|
|
||||||
fence iorw,iorw
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_clear), .-_(__atomic_clear)
|
|
||||||
|
|
||||||
.global _(__atomic_compare_exchange_1)
|
|
||||||
.type _(__atomic_compare_exchange_1), %function
|
|
||||||
_(__atomic_compare_exchange_1):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.short 0x1141
|
|
||||||
.short 0x86ba
|
|
||||||
.short 0x873e
|
|
||||||
.short 0xe406
|
|
||||||
.int 0x0ff0000f
|
|
||||||
.int 0x0005c803
|
|
||||||
.int 0xff857893
|
|
||||||
.int 0x0008b783
|
|
||||||
.short 0x891d
|
|
||||||
.short 0x050e
|
|
||||||
.int 0x0ff00693
|
|
||||||
.int 0x00a696b3
|
|
||||||
.int 0x00a81833
|
|
||||||
.int 0x00a61633
|
|
||||||
.int 0xfff6c713
|
|
||||||
.short 0x8f7d
|
|
||||||
.int 0x00f6f333
|
|
||||||
.short 0x8f51
|
|
||||||
.int 0x03031263
|
|
||||||
.int 0x1008b32f
|
|
||||||
.int 0x00f31663
|
|
||||||
.int 0x18e8be2f
|
|
||||||
.int 0xfe0e1ae3
|
|
||||||
.int 0x40f30733
|
|
||||||
.short 0x879a
|
|
||||||
.short 0xff69
|
|
||||||
.int 0x0ff0000f
|
|
||||||
.short 0x4505
|
|
||||||
.short 0xa801
|
|
||||||
.int 0x00a7d7b3
|
|
||||||
.int 0x00f58023
|
|
||||||
.int 0x0ff0000f
|
|
||||||
.short 0x4501
|
|
||||||
.short 0x60a2
|
|
||||||
.short 0x0141
|
|
||||||
.short 0x8082
|
|
||||||
#else
|
|
||||||
addi sp,sp,-16
|
|
||||||
mv a3,a4
|
|
||||||
mv a4,a5
|
|
||||||
sd ra,8(sp)
|
|
||||||
fence
|
|
||||||
lbu a6,0(a1)
|
|
||||||
andi a7,a0,-8
|
|
||||||
ld a5,0(a7)
|
|
||||||
andi a0,a0,7
|
|
||||||
slli a0,a0,0x3
|
|
||||||
li a3,255
|
|
||||||
sll a3,a3,a0
|
|
||||||
sll a6,a6,a0
|
|
||||||
sll a2,a2,a0
|
|
||||||
.L1:
|
|
||||||
not a4,a3
|
|
||||||
and a4,a4,a5
|
|
||||||
and t1,a3,a5
|
|
||||||
or a4,a4,a2
|
|
||||||
bne t1,a6,.L4
|
|
||||||
.L2:
|
|
||||||
lr.d t1,(a7)
|
|
||||||
bne t1,a5,.L3
|
|
||||||
sc.d t3,a4,(a7)
|
|
||||||
bnez t3,.L2
|
|
||||||
.L3:
|
|
||||||
sub a4,t1,a5
|
|
||||||
mv a5,t1
|
|
||||||
bnez a4,.L1
|
|
||||||
fence
|
|
||||||
li a0,1
|
|
||||||
j .L5
|
|
||||||
.L4:
|
|
||||||
srl a5,a5,a0
|
|
||||||
sb a5,0(a1)
|
|
||||||
fence
|
|
||||||
li a0,0
|
|
||||||
.L5:
|
|
||||||
ld ra,8(sp)
|
|
||||||
addi sp,sp,16
|
|
||||||
jr ra
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1)
|
|
||||||
|
|
||||||
.global _(__atomic_compare_exchange_2)
|
|
||||||
.type _(__atomic_compare_exchange_2), %function
|
|
||||||
_(__atomic_compare_exchange_2):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.short 0x1141
|
|
||||||
.short 0x86ba
|
|
||||||
.short 0x873e
|
|
||||||
.short 0xe406
|
|
||||||
.int 0x0ff0000f
|
|
||||||
.int 0x0005d803
|
|
||||||
.int 0xff857893
|
|
||||||
.short 0x67c1
|
|
||||||
.short 0x891d
|
|
||||||
.int 0x0008b703
|
|
||||||
.short 0x050e
|
|
||||||
.short 0x17fd
|
|
||||||
.int 0x00a797b3
|
|
||||||
.int 0x00a81833
|
|
||||||
.int 0x00a61633
|
|
||||||
.int 0xfff7c693
|
|
||||||
.short 0x8ef9
|
|
||||||
.int 0x00e7f333
|
|
||||||
.short 0x8ed1
|
|
||||||
.int 0x03031263
|
|
||||||
.int 0x1008b32f
|
|
||||||
.int 0x00e31663
|
|
||||||
.int 0x18d8be2f
|
|
||||||
.int 0xfe0e1ae3
|
|
||||||
.int 0x40e306b3
|
|
||||||
.short 0x871a
|
|
||||||
.short 0xfee9
|
|
||||||
.int 0x0ff0000f
|
|
||||||
.short 0x4505
|
|
||||||
.short 0xa801
|
|
||||||
.int 0x00a75733
|
|
||||||
.int 0x00e59023
|
|
||||||
.int 0x0ff0000f
|
|
||||||
.short 0x4501
|
|
||||||
.short 0x60a2
|
|
||||||
.short 0x0141
|
|
||||||
.short 0x8082
|
|
||||||
#else
|
|
||||||
addi sp,sp,-16
|
|
||||||
mv a3,a4
|
|
||||||
mv a4,a5
|
|
||||||
sd ra,8(sp)
|
|
||||||
fence
|
|
||||||
lhu a6,0(a1)
|
|
||||||
andi a7,a0,-8
|
|
||||||
lui a5,0x10
|
|
||||||
andi a0,a0,7
|
|
||||||
ld a4,0(a7)
|
|
||||||
slli a0,a0,0x3
|
|
||||||
addi a5,a5,-1
|
|
||||||
sll a5,a5,a0
|
|
||||||
sll a6,a6,a0
|
|
||||||
sll a2,a2,a0
|
|
||||||
.L6:
|
|
||||||
not a3,a5
|
|
||||||
and a3,a3,a4
|
|
||||||
and t1,a5,a4
|
|
||||||
or a3,a3,a2
|
|
||||||
bne t1,a6,.L9
|
|
||||||
.L7:
|
|
||||||
lr.d t1,(a7)
|
|
||||||
bne t1,a4,.L8
|
|
||||||
sc.d t3,a3,(a7)
|
|
||||||
bnez t3,.L7
|
|
||||||
.L8:
|
|
||||||
sub a3,t1,a4
|
|
||||||
mv a4,t1
|
|
||||||
bnez a3,.L6
|
|
||||||
fence
|
|
||||||
li a0,1
|
|
||||||
j .L10
|
|
||||||
.L9:
|
|
||||||
srl a4,a4,a0
|
|
||||||
sh a4,0(a1)
|
|
||||||
fence
|
|
||||||
li a0,0
|
|
||||||
.L10:
|
|
||||||
ld ra,8(sp)
|
|
||||||
addi sp,sp,16
|
|
||||||
jr ra
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2)
|
|
||||||
|
|
||||||
.global _(__atomic_compare_exchange_4)
|
|
||||||
.type _(__atomic_compare_exchange_4), %function
|
|
||||||
_(__atomic_compare_exchange_4):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.short 0x419c
|
|
||||||
.int 0x0f50000f
|
|
||||||
.int 0x1405272f
|
|
||||||
.int 0x00f71663
|
|
||||||
.int 0x1cc5282f
|
|
||||||
.int 0xfe081ae3
|
|
||||||
.int 0x40f707bb
|
|
||||||
.int 0x0017b513
|
|
||||||
.short 0xc391
|
|
||||||
.short 0xc198
|
|
||||||
.short 0x8905
|
|
||||||
.short 0x8082
|
|
||||||
#else
|
|
||||||
lw a5,0(a1)
|
|
||||||
fence iorw,ow;
|
|
||||||
.L11:
|
|
||||||
lr.w.aq a4,0(a0)
|
|
||||||
bne a4,a5,.L12
|
|
||||||
sc.w.aq a6,a2,0(a0)
|
|
||||||
bnez a6,.L11
|
|
||||||
.L12:
|
|
||||||
subw a5,a4,a5
|
|
||||||
seqz a0,a5
|
|
||||||
beq a5,zero,.L13
|
|
||||||
sw a4,0(a1)
|
|
||||||
.L13:
|
|
||||||
andi a0,a0,1
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4)
|
|
||||||
|
|
||||||
.global _(__atomic_compare_exchange_8)
|
|
||||||
.type _(__atomic_compare_exchange_8), %function
|
|
||||||
_(__atomic_compare_exchange_8):
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.short 0x619c
|
|
||||||
.int 0x0f50000f
|
|
||||||
.int 0x1405372f
|
|
||||||
.int 0x00f71563
|
|
||||||
.int 0x1cc536af
|
|
||||||
.short 0xfaf5
|
|
||||||
.int 0x40f707b3
|
|
||||||
.int 0x0017b513
|
|
||||||
.short 0xc391
|
|
||||||
.short 0xe198
|
|
||||||
.short 0x8905
|
|
||||||
.short 0x8082
|
|
||||||
#else
|
|
||||||
ld a5,0(a1)
|
|
||||||
fence iorw,ow;
|
|
||||||
.L14:
|
|
||||||
lr.d.aq a4,0(a0)
|
|
||||||
bne a4,a5,.L15
|
|
||||||
sc.d.aq a3,a2,0(a0)
|
|
||||||
bnez a3,.L14
|
|
||||||
.L15:
|
|
||||||
sub a5,a4,a5
|
|
||||||
seqz a0,a5
|
|
||||||
beq a5,zero,.L16
|
|
||||||
sd a4,0(a1)
|
|
||||||
.L16:
|
|
||||||
andi a0,a0,1
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
.size _(__atomic_compare_exchange_8), .-_(__atomic_compare_exchange_8)
|
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
#endif
|
|
||||||
|
|
2281
libtcc1/bcheck.c
2281
libtcc1/bcheck.c
File diff suppressed because it is too large
Load diff
|
@ -1,74 +0,0 @@
|
||||||
/* ------------------------------------------------------------- */
|
|
||||||
/* stubs for calling bcheck functions from a dll. */
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define REDIR_ALL \
|
|
||||||
REDIR(__bt_init) \
|
|
||||||
REDIR(__bt_exit) \
|
|
||||||
REDIR(tcc_backtrace) \
|
|
||||||
\
|
|
||||||
REDIR(__bound_ptr_add) \
|
|
||||||
REDIR(__bound_ptr_indir1) \
|
|
||||||
REDIR(__bound_ptr_indir2) \
|
|
||||||
REDIR(__bound_ptr_indir4) \
|
|
||||||
REDIR(__bound_ptr_indir8) \
|
|
||||||
REDIR(__bound_ptr_indir12) \
|
|
||||||
REDIR(__bound_ptr_indir16) \
|
|
||||||
REDIR(__bound_local_new) \
|
|
||||||
REDIR(__bound_local_delete) \
|
|
||||||
REDIR(__bound_new_region) \
|
|
||||||
\
|
|
||||||
REDIR(__bound_free) \
|
|
||||||
REDIR(__bound_malloc) \
|
|
||||||
REDIR(__bound_realloc) \
|
|
||||||
REDIR(__bound_memcpy) \
|
|
||||||
REDIR(__bound_memcmp) \
|
|
||||||
REDIR(__bound_memmove) \
|
|
||||||
REDIR(__bound_memset) \
|
|
||||||
REDIR(__bound_strlen) \
|
|
||||||
REDIR(__bound_strcpy) \
|
|
||||||
REDIR(__bound_strncpy) \
|
|
||||||
REDIR(__bound_strcmp) \
|
|
||||||
REDIR(__bound_strncmp) \
|
|
||||||
REDIR(__bound_strcat) \
|
|
||||||
REDIR(__bound_strchr) \
|
|
||||||
REDIR(__bound_strdup)
|
|
||||||
|
|
||||||
#ifdef __leading_underscore
|
|
||||||
#define _(s) "_"#s
|
|
||||||
#else
|
|
||||||
#define _(s) #s
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define REDIR(s) void *s;
|
|
||||||
static struct { REDIR_ALL } all_ptrs;
|
|
||||||
#undef REDIR
|
|
||||||
#define REDIR(s) #s"\0"
|
|
||||||
static const char all_names[] = REDIR_ALL;
|
|
||||||
#undef REDIR
|
|
||||||
#define REDIR(s) __asm__(".global " _(s) ";" _(s) ": jmp *%0" : : "m" (all_ptrs.s) );
|
|
||||||
static void all_jmps() { REDIR_ALL }
|
|
||||||
#undef REDIR
|
|
||||||
|
|
||||||
void __bt_init_dll(int bcheck)
|
|
||||||
{
|
|
||||||
const char *s = all_names;
|
|
||||||
void **p = (void**)&all_ptrs;
|
|
||||||
do {
|
|
||||||
*p = (void*)GetProcAddress(GetModuleHandle(NULL), (char*)s);
|
|
||||||
if (NULL == *p) {
|
|
||||||
char buf[100];
|
|
||||||
sprintf(buf,
|
|
||||||
"Error: function '%s()' not found in executable. "
|
|
||||||
"(Need -bt or -b for linking the exe.)", s);
|
|
||||||
if (GetStdHandle(STD_ERROR_HANDLE))
|
|
||||||
fprintf(stderr, "TCC/BCHECK: %s\n", buf), fflush(stderr);
|
|
||||||
else
|
|
||||||
MessageBox(NULL, buf, "TCC/BCHECK", MB_ICONERROR);
|
|
||||||
ExitProcess(1);
|
|
||||||
}
|
|
||||||
s = strchr(s,'\0') + 1, ++p;
|
|
||||||
} while (*s && (bcheck || p < &all_ptrs.__bound_ptr_add));
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
/* ------------------------------------------------------------- */
|
|
||||||
/* for linking rt_printline and the signal/exception handler
|
|
||||||
from tccrun.c into executables. */
|
|
||||||
|
|
||||||
#define CONFIG_TCC_BACKTRACE_ONLY
|
|
||||||
#define ONE_SOURCE 1
|
|
||||||
#define pstrcpy tcc_pstrcpy
|
|
||||||
#include "../tccrun.c"
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
# define __declspec(n)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__declspec(dllexport)
|
|
||||||
void __bt_init(rt_context *p, int is_exe)
|
|
||||||
{
|
|
||||||
__attribute__((weak)) int main();
|
|
||||||
__attribute__((weak)) void __bound_init(void*, int);
|
|
||||||
|
|
||||||
//fprintf(stderr, "__bt_init %d %p %p %p\n", is_exe, p, p->stab_sym, p->bounds_start), fflush(stderr);
|
|
||||||
|
|
||||||
/* call __bound_init here due to redirection of sigaction */
|
|
||||||
/* needed to add global symbols */
|
|
||||||
if (p->bounds_start)
|
|
||||||
__bound_init(p->bounds_start, -1);
|
|
||||||
|
|
||||||
/* add to chain */
|
|
||||||
rt_wait_sem();
|
|
||||||
p->next = g_rc, g_rc = p;
|
|
||||||
rt_post_sem();
|
|
||||||
if (is_exe) {
|
|
||||||
/* we are the executable (not a dll) */
|
|
||||||
p->top_func = main;
|
|
||||||
set_exception_handler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__declspec(dllexport)
|
|
||||||
void __bt_exit(rt_context *p)
|
|
||||||
{
|
|
||||||
struct rt_context *rc, **pp;
|
|
||||||
__attribute__((weak)) void __bound_exit_dll(void*);
|
|
||||||
|
|
||||||
//fprintf(stderr, "__bt_exit %d %p\n", !!p->top_func, p);
|
|
||||||
|
|
||||||
if (p->bounds_start)
|
|
||||||
__bound_exit_dll(p->bounds_start);
|
|
||||||
|
|
||||||
/* remove from chain */
|
|
||||||
rt_wait_sem();
|
|
||||||
for (pp = &g_rc; rc = *pp, rc; pp = &rc->next)
|
|
||||||
if (rc == p) {
|
|
||||||
*pp = rc->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
rt_post_sem();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy a string and truncate it. */
|
|
||||||
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s)
|
|
||||||
{
|
|
||||||
int l = strlen(s);
|
|
||||||
if (l >= buf_size)
|
|
||||||
l = buf_size - 1;
|
|
||||||
memcpy(buf, s, l);
|
|
||||||
buf[l] = 0;
|
|
||||||
return buf;
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/* ------------------------------------------------------------- */
|
|
||||||
/* function to get a stack backtrace on demand with a message */
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#undef __attribute__
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
# define DLL_EXPORT __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
# define DLL_EXPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Needed when using ...libtcc1-usegcc=yes in lib/Makefile */
|
|
||||||
#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wframe-address"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct rt_frame {
|
|
||||||
void *ip, *fp, *sp;
|
|
||||||
} rt_frame;
|
|
||||||
|
|
||||||
__attribute__((weak))
|
|
||||||
int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap);
|
|
||||||
|
|
||||||
DLL_EXPORT int tcc_backtrace(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (_tcc_backtrace) {
|
|
||||||
rt_frame f;
|
|
||||||
f.fp = __builtin_frame_address(1);
|
|
||||||
f.ip = __builtin_return_address(0);
|
|
||||||
va_start(ap, fmt);
|
|
||||||
ret = _tcc_backtrace(&f, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
} else {
|
|
||||||
const char *p, *nl = "\n";
|
|
||||||
if (fmt[0] == '^' && (p = strchr(fmt + 1, fmt[0])))
|
|
||||||
fmt = p + 1;
|
|
||||||
if (fmt[0] == '\001')
|
|
||||||
++fmt, nl = "";
|
|
||||||
va_start(ap, fmt);
|
|
||||||
ret = vfprintf(stderr, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
fprintf(stderr, "%s", nl), fflush(stderr);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
|
@ -1 +0,0 @@
|
||||||
void * __dso_handle __attribute((visibility("hidden"))) = &__dso_handle;
|
|
|
@ -57,102 +57,34 @@
|
||||||
#define __ORDER_LITTLE_ENDIAN__ 1234
|
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||||
#define __ORDER_BIG_ENDIAN__ 4321
|
#define __ORDER_BIG_ENDIAN__ 4321
|
||||||
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||||
#if defined _WIN32
|
|
||||||
#define __WCHAR_TYPE__ unsigned short
|
|
||||||
#define __WINT_TYPE__ unsigned short
|
|
||||||
#elif defined __linux__
|
|
||||||
#define __WCHAR_TYPE__ int
|
|
||||||
#define __WINT_TYPE__ unsigned int
|
|
||||||
#else
|
|
||||||
#define __WCHAR_TYPE__ int
|
#define __WCHAR_TYPE__ int
|
||||||
#define __WINT_TYPE__ int
|
#define __WINT_TYPE__ int
|
||||||
#endif
|
|
||||||
|
|
||||||
#if __STDC_VERSION__ >= 201112L
|
|
||||||
|
#if __STDC_VERSION__ >= 201112L
|
||||||
# define __STDC_NO_ATOMICS__ 1
|
# define __STDC_NO_ATOMICS__ 1
|
||||||
# define __STDC_NO_COMPLEX__ 1
|
# define __STDC_NO_COMPLEX__ 1
|
||||||
# define __STDC_NO_THREADS__ 1
|
# define __STDC_NO_THREADS__ 1
|
||||||
#if !defined _WIN32
|
|
||||||
# define __STDC_UTF_16__ 1
|
# define __STDC_UTF_16__ 1
|
||||||
# define __STDC_UTF_32__ 1
|
# define __STDC_UTF_32__ 1
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined _WIN32
|
|
||||||
#define __declspec(x) __attribute__((x))
|
|
||||||
#define __cdecl
|
|
||||||
|
|
||||||
#elif defined __FreeBSD__
|
|
||||||
#define __GNUC__ 9
|
|
||||||
#define __GNUC_MINOR__ 3
|
|
||||||
#define __GNUC_PATCHLEVEL__ 0
|
|
||||||
#define __GNUC_STDC_INLINE__ 1
|
|
||||||
#define __NO_TLS 1
|
|
||||||
#define __RUNETYPE_INTERNAL 1
|
|
||||||
# if __SIZEOF_POINTER__ == 8
|
|
||||||
/* FIXME, __int128_t is used by setjump */
|
|
||||||
#define __int128_t struct { unsigned char _dummy[16] __attribute((aligned(16))); }
|
|
||||||
#define __SIZEOF_SIZE_T__ 8
|
|
||||||
#define __SIZEOF_PTRDIFF_T__ 8
|
|
||||||
#else
|
|
||||||
#define __SIZEOF_SIZE_T__ 4
|
|
||||||
#define __SIZEOF_PTRDIFF_T__ 4
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#elif defined __FreeBSD_kernel__
|
|
||||||
|
|
||||||
#elif defined __NetBSD__
|
|
||||||
#define __GNUC__ 4
|
|
||||||
#define __GNUC_MINOR__ 1
|
|
||||||
#define __GNUC_PATCHLEVEL__ 0
|
|
||||||
#define _Pragma(x)
|
|
||||||
#define __ELF__ 1
|
|
||||||
#if defined __aarch64__
|
|
||||||
#define _LOCORE /* avoids usage of __asm */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined __OpenBSD__
|
|
||||||
#define __GNUC__ 4
|
|
||||||
#define _ANSI_LIBRARY 1
|
|
||||||
|
|
||||||
#elif defined __APPLE__
|
|
||||||
/* emulate APPLE-GCC to make libc's headerfiles compile: */
|
|
||||||
#define __GNUC__ 4 /* darwin emits warning on GCC<4 */
|
|
||||||
#define __APPLE_CC__ 1 /* for <TargetConditionals.h> */
|
|
||||||
#define __LITTLE_ENDIAN__ 1
|
|
||||||
#define _DONT_USE_CTYPE_INLINE_ 1
|
|
||||||
/* avoids usage of GCC/clang specific builtins in libc-headerfiles: */
|
|
||||||
#define __FINITE_MATH_ONLY__ 1
|
|
||||||
#define _FORTIFY_SOURCE 0
|
|
||||||
//#define __has_builtin(x) 0
|
|
||||||
|
|
||||||
#elif defined __ANDROID__
|
|
||||||
#define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD
|
|
||||||
|
|
||||||
#else
|
|
||||||
/* Linux */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Some derived integer types needed to get stdint.h to compile correctly on some platforms */
|
/* Some derived integer types needed to get stdint.h to compile correctly on some platforms */
|
||||||
#ifndef __NetBSD__
|
|
||||||
#define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__
|
#define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__
|
||||||
#define __INTPTR_TYPE__ __PTRDIFF_TYPE__
|
#define __INTPTR_TYPE__ __PTRDIFF_TYPE__
|
||||||
#endif
|
|
||||||
#define __INT32_TYPE__ int
|
#define __INT32_TYPE__ int
|
||||||
|
|
||||||
#if !defined _WIN32
|
|
||||||
/* glibc defines. We do not support __USER_NAME_PREFIX__ */
|
/* glibc defines. We do not support __USER_NAME_PREFIX__ */
|
||||||
#define __REDIRECT(name, proto, alias) name proto __asm__ (#alias)
|
#define __REDIRECT(name, proto, alias) name proto __asm__ (#alias)
|
||||||
#define __REDIRECT_NTH(name, proto, alias) name proto __asm__ (#alias) __THROW
|
#define __REDIRECT_NTH(name, proto, alias) name proto __asm__ (#alias) __THROW
|
||||||
#define __REDIRECT_NTHNL(name, proto, alias) name proto __asm__ (#alias) __THROWNL
|
#define __REDIRECT_NTHNL(name, proto, alias) name proto __asm__ (#alias) __THROWNL
|
||||||
#endif
|
|
||||||
|
|
||||||
/* not implemented */
|
/* not implemented */
|
||||||
#define __PRETTY_FUNCTION__ __FUNCTION__
|
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||||
#define __has_builtin(x) 0
|
#define __has_builtin(x) 0
|
||||||
#define __has_feature(x) 0
|
#define __has_feature(x) 0
|
||||||
#define __has_attribute(x) 0
|
#define __has_attribute(x) 0
|
||||||
|
|
||||||
/* C23 Keywords */
|
/* C23 Keywords */
|
||||||
#define _Nonnull
|
#define _Nonnull
|
||||||
#define _Nullable
|
#define _Nullable
|
||||||
|
@ -181,67 +113,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* __builtin_va_list */
|
/* __builtin_va_list */
|
||||||
#if defined __x86_64__
|
|
||||||
#if !defined _WIN32
|
|
||||||
/* GCC compatible definition of va_list. */
|
|
||||||
/* This should be in sync with the declaration in our lib/libtcc1.c */
|
|
||||||
typedef struct {
|
|
||||||
unsigned gp_offset, fp_offset;
|
|
||||||
union {
|
|
||||||
unsigned overflow_offset;
|
|
||||||
char *overflow_arg_area;
|
|
||||||
};
|
|
||||||
char *reg_save_area;
|
|
||||||
} __builtin_va_list[1];
|
|
||||||
|
|
||||||
void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align);
|
|
||||||
#define __builtin_va_start(ap, last) \
|
|
||||||
(*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24))
|
|
||||||
#define __builtin_va_arg(ap, t) \
|
|
||||||
(*(t *)(__va_arg(ap, __builtin_va_arg_types(t), sizeof(t), __alignof__(t))))
|
|
||||||
#define __builtin_va_copy(dest, src) (*(dest) = *(src))
|
|
||||||
|
|
||||||
#else /* _WIN64 */
|
|
||||||
typedef char *__builtin_va_list;
|
|
||||||
#define __builtin_va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \
|
|
||||||
? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined __arm__
|
|
||||||
typedef char *__builtin_va_list;
|
|
||||||
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
|
|
||||||
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
|
|
||||||
& ~(_tcc_alignof(type) - 1))
|
|
||||||
#define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
|
|
||||||
#define __builtin_va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
|
|
||||||
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
|
|
||||||
|
|
||||||
#elif defined __aarch64__
|
|
||||||
#if defined __APPLE__
|
|
||||||
typedef struct {
|
|
||||||
void *__stack;
|
|
||||||
} __builtin_va_list;
|
|
||||||
|
|
||||||
#else
|
|
||||||
typedef struct {
|
|
||||||
void *__stack, *__gr_top, *__vr_top;
|
|
||||||
int __gr_offs, __vr_offs;
|
|
||||||
} __builtin_va_list;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#elif defined __riscv
|
|
||||||
typedef char *__builtin_va_list;
|
|
||||||
#define __va_reg_size (__riscv_xlen >> 3)
|
|
||||||
#define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \
|
|
||||||
& -(__alignof__(type)))
|
|
||||||
#define __builtin_va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size)))))
|
|
||||||
|
|
||||||
#else /* __i386__ */
|
|
||||||
typedef char *__builtin_va_list;
|
typedef char *__builtin_va_list;
|
||||||
#define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
|
#define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
|
||||||
#define __builtin_va_arg(ap,t) (*(t*)((ap+=(sizeof(t)+3)&~3)-((sizeof(t)+3)&~3)))
|
#define __builtin_va_arg(ap,t) (*(t*)((ap+=(sizeof(t)+3)&~3)-((sizeof(t)+3)&~3)))
|
||||||
|
|
||||||
#endif
|
|
||||||
#define __builtin_va_end(ap) (void)(ap)
|
#define __builtin_va_end(ap) (void)(ap)
|
||||||
#ifndef __builtin_va_copy
|
#ifndef __builtin_va_copy
|
||||||
# define __builtin_va_copy(dest, src) (dest) = (src)
|
# define __builtin_va_copy(dest, src) (dest) = (src)
|
||||||
|
@ -283,13 +158,6 @@
|
||||||
__BOTH(char*, strchr, (const char*, int))
|
__BOTH(char*, strchr, (const char*, int))
|
||||||
__BOTH(char*, strrchr, (const char*, int))
|
__BOTH(char*, strrchr, (const char*, int))
|
||||||
__BOTH(char*, strdup, (const char*))
|
__BOTH(char*, strdup, (const char*))
|
||||||
#if defined __ARM_EABI__
|
|
||||||
__BOUND(void*,__aeabi_memcpy,(void*,const void*,__SIZE_TYPE__))
|
|
||||||
__BOUND(void*,__aeabi_memmove,(void*,const void*,__SIZE_TYPE__))
|
|
||||||
__BOUND(void*,__aeabi_memmove4,(void*,const void*,__SIZE_TYPE__))
|
|
||||||
__BOUND(void*,__aeabi_memmove8,(void*,const void*,__SIZE_TYPE__))
|
|
||||||
__BOUND(void*,__aeabi_memset,(void*,int,__SIZE_TYPE__))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined __linux__ || defined __APPLE__ // HAVE MALLOC_REDIR
|
#if defined __linux__ || defined __APPLE__ // HAVE MALLOC_REDIR
|
||||||
#define __MAYBE_REDIR __BUILTIN
|
#define __MAYBE_REDIR __BUILTIN
|
|
@ -1,677 +0,0 @@
|
||||||
/*
|
|
||||||
* TCC runtime library for arm64.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Edmund Grimley Evans
|
|
||||||
*
|
|
||||||
* Copying and distribution of this file, with or without modification,
|
|
||||||
* are permitted in any medium without royalty provided the copyright
|
|
||||||
* notice and this notice are preserved. This file is offered as-is,
|
|
||||||
* without any warranty.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __TINYC__
|
|
||||||
typedef signed char int8_t;
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
typedef short int16_t;
|
|
||||||
typedef unsigned short uint16_t;
|
|
||||||
typedef int int32_t;
|
|
||||||
typedef unsigned uint32_t;
|
|
||||||
typedef long long int64_t;
|
|
||||||
typedef unsigned long long uint64_t;
|
|
||||||
void *memcpy(void*,void*,__SIZE_TYPE__);
|
|
||||||
#else
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined __riscv && !defined __APPLE__
|
|
||||||
void __clear_cache(void *beg, void *end)
|
|
||||||
{
|
|
||||||
__arm64_clear_cache(beg, end);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_t x0, x1;
|
|
||||||
} u128_t;
|
|
||||||
|
|
||||||
static long double f3_zero(int sgn)
|
|
||||||
{
|
|
||||||
long double f;
|
|
||||||
u128_t x = { 0, (uint64_t)sgn << 63 };
|
|
||||||
memcpy(&f, &x, 16);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long double f3_infinity(int sgn)
|
|
||||||
{
|
|
||||||
long double f;
|
|
||||||
u128_t x = { 0, (uint64_t)sgn << 63 | 0x7fff000000000000 };
|
|
||||||
memcpy(&f, &x, 16);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long double f3_NaN(void)
|
|
||||||
{
|
|
||||||
long double f;
|
|
||||||
#if 0
|
|
||||||
// ARM's default NaN usually has just the top fraction bit set:
|
|
||||||
u128_t x = { 0, 0x7fff800000000000 };
|
|
||||||
#else
|
|
||||||
// GCC's library sets all fraction bits:
|
|
||||||
u128_t x = { -1, 0x7fffffffffffffff };
|
|
||||||
#endif
|
|
||||||
memcpy(&f, &x, 16);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fp3_convert_NaN(long double *f, int sgn, u128_t mnt)
|
|
||||||
{
|
|
||||||
u128_t x = { mnt.x0,
|
|
||||||
mnt.x1 | 0x7fff800000000000 | (uint64_t)sgn << 63 };
|
|
||||||
memcpy(f, &x, 16);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fp3_detect_NaNs(long double *f,
|
|
||||||
int a_sgn, int a_exp, u128_t a,
|
|
||||||
int b_sgn, int b_exp, u128_t b)
|
|
||||||
{
|
|
||||||
// Detect signalling NaNs:
|
|
||||||
if (a_exp == 32767 && (a.x0 | a.x1 << 16) && !(a.x1 >> 47 & 1))
|
|
||||||
return fp3_convert_NaN(f, a_sgn, a);
|
|
||||||
if (b_exp == 32767 && (b.x0 | b.x1 << 16) && !(b.x1 >> 47 & 1))
|
|
||||||
return fp3_convert_NaN(f, b_sgn, b);
|
|
||||||
|
|
||||||
// Detect quiet NaNs:
|
|
||||||
if (a_exp == 32767 && (a.x0 | a.x1 << 16))
|
|
||||||
return fp3_convert_NaN(f, a_sgn, a);
|
|
||||||
if (b_exp == 32767 && (b.x0 | b.x1 << 16))
|
|
||||||
return fp3_convert_NaN(f, b_sgn, b);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f)
|
|
||||||
{
|
|
||||||
u128_t x;
|
|
||||||
memcpy(&x, &f, 16);
|
|
||||||
*sgn = x.x1 >> 63;
|
|
||||||
*exp = x.x1 >> 48 & 32767;
|
|
||||||
x.x1 = x.x1 << 16 >> 16;
|
|
||||||
if (*exp)
|
|
||||||
x.x1 |= (uint64_t)1 << 48;
|
|
||||||
else
|
|
||||||
*exp = 1;
|
|
||||||
*mnt = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u128_t f3_normalise(int32_t *exp, u128_t mnt)
|
|
||||||
{
|
|
||||||
int sh;
|
|
||||||
if (!(mnt.x0 | mnt.x1))
|
|
||||||
return mnt;
|
|
||||||
if (!mnt.x1) {
|
|
||||||
mnt.x1 = mnt.x0;
|
|
||||||
mnt.x0 = 0;
|
|
||||||
*exp -= 64;
|
|
||||||
}
|
|
||||||
for (sh = 32; sh; sh >>= 1) {
|
|
||||||
if (!(mnt.x1 >> (64 - sh))) {
|
|
||||||
mnt.x1 = mnt.x1 << sh | mnt.x0 >> (64 - sh);
|
|
||||||
mnt.x0 = mnt.x0 << sh;
|
|
||||||
*exp -= sh;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u128_t f3_sticky_shift(int32_t sh, u128_t x)
|
|
||||||
{
|
|
||||||
if (sh >= 128) {
|
|
||||||
x.x0 = !!(x.x0 | x.x1);
|
|
||||||
x.x1 = 0;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
if (sh >= 64) {
|
|
||||||
x.x0 = x.x1 | !!x.x0;
|
|
||||||
x.x1 = 0;
|
|
||||||
sh -= 64;
|
|
||||||
}
|
|
||||||
if (sh > 0) {
|
|
||||||
x.x0 = x.x0 >> sh | x.x1 << (64 - sh) | !!(x.x0 << (64 - sh));
|
|
||||||
x.x1 = x.x1 >> sh;
|
|
||||||
}
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long double f3_round(int sgn, int32_t exp, u128_t x)
|
|
||||||
{
|
|
||||||
long double f;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if (exp > 0) {
|
|
||||||
x = f3_sticky_shift(13, x);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
x = f3_sticky_shift(14 - exp, x);
|
|
||||||
exp = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = x.x0 & 3;
|
|
||||||
x.x0 = x.x0 >> 2 | x.x1 << 62;
|
|
||||||
x.x1 = x.x1 >> 2;
|
|
||||||
|
|
||||||
if (error == 3 || ((error == 2) & (x.x0 & 1))) {
|
|
||||||
if (!++x.x0) {
|
|
||||||
++x.x1;
|
|
||||||
if (x.x1 == (uint64_t)1 << 48)
|
|
||||||
exp = 1;
|
|
||||||
else if (x.x1 == (uint64_t)1 << 49) {
|
|
||||||
++exp;
|
|
||||||
x.x0 = x.x0 >> 1 | x.x1 << 63;
|
|
||||||
x.x1 = x.x1 >> 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exp >= 32767)
|
|
||||||
return f3_infinity(sgn);
|
|
||||||
|
|
||||||
x.x1 = x.x1 << 16 >> 16 | (uint64_t)exp << 48 | (uint64_t)sgn << 63;
|
|
||||||
memcpy(&f, &x, 16);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long double f3_add(long double fa, long double fb, int neg)
|
|
||||||
{
|
|
||||||
u128_t a, b, x;
|
|
||||||
int32_t a_exp, b_exp, x_exp;
|
|
||||||
int a_sgn, b_sgn, x_sgn;
|
|
||||||
long double fx;
|
|
||||||
|
|
||||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
|
||||||
f3_unpack(&b_sgn, &b_exp, &b, fb);
|
|
||||||
|
|
||||||
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
|
|
||||||
return fx;
|
|
||||||
|
|
||||||
b_sgn ^= neg;
|
|
||||||
|
|
||||||
// Handle infinities and zeroes:
|
|
||||||
if (a_exp == 32767 && b_exp == 32767 && a_sgn != b_sgn)
|
|
||||||
return f3_NaN();
|
|
||||||
if (a_exp == 32767)
|
|
||||||
return f3_infinity(a_sgn);
|
|
||||||
if (b_exp == 32767)
|
|
||||||
return f3_infinity(b_sgn);
|
|
||||||
if (!(a.x0 | a.x1 | b.x0 | b.x1))
|
|
||||||
return f3_zero(a_sgn & b_sgn);
|
|
||||||
|
|
||||||
a.x1 = a.x1 << 3 | a.x0 >> 61;
|
|
||||||
a.x0 = a.x0 << 3;
|
|
||||||
b.x1 = b.x1 << 3 | b.x0 >> 61;
|
|
||||||
b.x0 = b.x0 << 3;
|
|
||||||
|
|
||||||
if (a_exp <= b_exp) {
|
|
||||||
a = f3_sticky_shift(b_exp - a_exp, a);
|
|
||||||
a_exp = b_exp;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
b = f3_sticky_shift(a_exp - b_exp, b);
|
|
||||||
b_exp = a_exp;
|
|
||||||
}
|
|
||||||
|
|
||||||
x_sgn = a_sgn;
|
|
||||||
x_exp = a_exp;
|
|
||||||
if (a_sgn == b_sgn) {
|
|
||||||
x.x0 = a.x0 + b.x0;
|
|
||||||
x.x1 = a.x1 + b.x1 + (x.x0 < a.x0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
x.x0 = a.x0 - b.x0;
|
|
||||||
x.x1 = a.x1 - b.x1 - (x.x0 > a.x0);
|
|
||||||
if (x.x1 >> 63) {
|
|
||||||
x_sgn ^= 1;
|
|
||||||
x.x0 = -x.x0;
|
|
||||||
x.x1 = -x.x1 - !!x.x0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(x.x0 | x.x1))
|
|
||||||
return f3_zero(0);
|
|
||||||
|
|
||||||
x = f3_normalise(&x_exp, x);
|
|
||||||
|
|
||||||
return f3_round(x_sgn, x_exp + 12, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
long double __addtf3(long double a, long double b)
|
|
||||||
{
|
|
||||||
return f3_add(a, b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
long double __subtf3(long double a, long double b)
|
|
||||||
{
|
|
||||||
return f3_add(a, b, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
long double __multf3(long double fa, long double fb)
|
|
||||||
{
|
|
||||||
u128_t a, b, x;
|
|
||||||
int32_t a_exp, b_exp, x_exp;
|
|
||||||
int a_sgn, b_sgn, x_sgn;
|
|
||||||
long double fx;
|
|
||||||
|
|
||||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
|
||||||
f3_unpack(&b_sgn, &b_exp, &b, fb);
|
|
||||||
|
|
||||||
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
|
|
||||||
return fx;
|
|
||||||
|
|
||||||
// Handle infinities and zeroes:
|
|
||||||
if ((a_exp == 32767 && !(b.x0 | b.x1)) ||
|
|
||||||
(b_exp == 32767 && !(a.x0 | a.x1)))
|
|
||||||
return f3_NaN();
|
|
||||||
if (a_exp == 32767 || b_exp == 32767)
|
|
||||||
return f3_infinity(a_sgn ^ b_sgn);
|
|
||||||
if (!(a.x0 | a.x1) || !(b.x0 | b.x1))
|
|
||||||
return f3_zero(a_sgn ^ b_sgn);
|
|
||||||
|
|
||||||
a = f3_normalise(&a_exp, a);
|
|
||||||
b = f3_normalise(&b_exp, b);
|
|
||||||
|
|
||||||
x_sgn = a_sgn ^ b_sgn;
|
|
||||||
x_exp = a_exp + b_exp - 16352;
|
|
||||||
|
|
||||||
{
|
|
||||||
// Convert to base (1 << 30), discarding bottom 6 bits, which are zero,
|
|
||||||
// so there are (32, 30, 30, 30) bits in (a3, a2, a1, a0):
|
|
||||||
uint64_t a0 = a.x0 << 28 >> 34;
|
|
||||||
uint64_t b0 = b.x0 << 28 >> 34;
|
|
||||||
uint64_t a1 = a.x0 >> 36 | a.x1 << 62 >> 34;
|
|
||||||
uint64_t b1 = b.x0 >> 36 | b.x1 << 62 >> 34;
|
|
||||||
uint64_t a2 = a.x1 << 32 >> 34;
|
|
||||||
uint64_t b2 = b.x1 << 32 >> 34;
|
|
||||||
uint64_t a3 = a.x1 >> 32;
|
|
||||||
uint64_t b3 = b.x1 >> 32;
|
|
||||||
// Use 16 small multiplications and additions that do not overflow:
|
|
||||||
uint64_t x0 = a0 * b0;
|
|
||||||
uint64_t x1 = (x0 >> 30) + a0 * b1 + a1 * b0;
|
|
||||||
uint64_t x2 = (x1 >> 30) + a0 * b2 + a1 * b1 + a2 * b0;
|
|
||||||
uint64_t x3 = (x2 >> 30) + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
|
|
||||||
uint64_t x4 = (x3 >> 30) + a1 * b3 + a2 * b2 + a3 * b1;
|
|
||||||
uint64_t x5 = (x4 >> 30) + a2 * b3 + a3 * b2;
|
|
||||||
uint64_t x6 = (x5 >> 30) + a3 * b3;
|
|
||||||
// We now have (64, 30, 30, ...) bits in (x6, x5, x4, ...).
|
|
||||||
// Take the top 128 bits, setting bottom bit if any lower bits were set:
|
|
||||||
uint64_t y0 = (x5 << 34 | x4 << 34 >> 30 | x3 << 34 >> 60 |
|
|
||||||
!!(x3 << 38 | (x2 | x1 | x0) << 34));
|
|
||||||
uint64_t y1 = x6;
|
|
||||||
// Top bit may be zero. Renormalise:
|
|
||||||
if (!(y1 >> 63)) {
|
|
||||||
y1 = y1 << 1 | y0 >> 63;
|
|
||||||
y0 = y0 << 1;
|
|
||||||
--x_exp;
|
|
||||||
}
|
|
||||||
x.x0 = y0;
|
|
||||||
x.x1 = y1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return f3_round(x_sgn, x_exp, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
long double __divtf3(long double fa, long double fb)
|
|
||||||
{
|
|
||||||
u128_t a, b, x;
|
|
||||||
int32_t a_exp, b_exp, x_exp;
|
|
||||||
int a_sgn, b_sgn, x_sgn, i;
|
|
||||||
long double fx;
|
|
||||||
|
|
||||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
|
||||||
f3_unpack(&b_sgn, &b_exp, &b, fb);
|
|
||||||
|
|
||||||
if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
|
|
||||||
return fx;
|
|
||||||
|
|
||||||
// Handle infinities and zeroes:
|
|
||||||
if ((a_exp == 32767 && b_exp == 32767) ||
|
|
||||||
(!(a.x0 | a.x1) && !(b.x0 | b.x1)))
|
|
||||||
return f3_NaN();
|
|
||||||
if (a_exp == 32767 || !(b.x0 | b.x1))
|
|
||||||
return f3_infinity(a_sgn ^ b_sgn);
|
|
||||||
if (!(a.x0 | a.x1) || b_exp == 32767)
|
|
||||||
return f3_zero(a_sgn ^ b_sgn);
|
|
||||||
|
|
||||||
a = f3_normalise(&a_exp, a);
|
|
||||||
b = f3_normalise(&b_exp, b);
|
|
||||||
|
|
||||||
x_sgn = a_sgn ^ b_sgn;
|
|
||||||
x_exp = a_exp - b_exp + 16395;
|
|
||||||
|
|
||||||
a.x0 = a.x0 >> 1 | a.x1 << 63;
|
|
||||||
a.x1 = a.x1 >> 1;
|
|
||||||
b.x0 = b.x0 >> 1 | b.x1 << 63;
|
|
||||||
b.x1 = b.x1 >> 1;
|
|
||||||
x.x0 = 0;
|
|
||||||
x.x1 = 0;
|
|
||||||
for (i = 0; i < 116; i++) {
|
|
||||||
x.x1 = x.x1 << 1 | x.x0 >> 63;
|
|
||||||
x.x0 = x.x0 << 1;
|
|
||||||
if (a.x1 > b.x1 || (a.x1 == b.x1 && a.x0 >= b.x0)) {
|
|
||||||
a.x1 = a.x1 - b.x1 - (a.x0 < b.x0);
|
|
||||||
a.x0 = a.x0 - b.x0;
|
|
||||||
x.x0 |= 1;
|
|
||||||
}
|
|
||||||
a.x1 = a.x1 << 1 | a.x0 >> 63;
|
|
||||||
a.x0 = a.x0 << 1;
|
|
||||||
}
|
|
||||||
x.x0 |= !!(a.x0 | a.x1);
|
|
||||||
|
|
||||||
x = f3_normalise(&x_exp, x);
|
|
||||||
|
|
||||||
return f3_round(x_sgn, x_exp, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
long double __extendsftf2(float f)
|
|
||||||
{
|
|
||||||
long double fx;
|
|
||||||
u128_t x;
|
|
||||||
uint32_t a;
|
|
||||||
uint64_t aa;
|
|
||||||
memcpy(&a, &f, 4);
|
|
||||||
aa = a;
|
|
||||||
x.x0 = 0;
|
|
||||||
if (!(a << 1))
|
|
||||||
x.x1 = aa << 32;
|
|
||||||
else if (a << 1 >> 24 == 255)
|
|
||||||
x.x1 = (0x7fff000000000000 | aa >> 31 << 63 | aa << 41 >> 16 |
|
|
||||||
(uint64_t)!!(a << 9) << 47);
|
|
||||||
else if (a << 1 >> 24 == 0) {
|
|
||||||
uint64_t adj = 0;
|
|
||||||
while (!(a << 1 >> 1 >> (23 - adj)))
|
|
||||||
adj++;
|
|
||||||
x.x1 = aa >> 31 << 63 | (16256 - adj + 1) << 48 | aa << adj << 41 >> 16;
|
|
||||||
} else
|
|
||||||
x.x1 = (aa >> 31 << 63 | ((aa >> 23 & 255) + 16256) << 48 |
|
|
||||||
aa << 41 >> 16);
|
|
||||||
memcpy(&fx, &x, 16);
|
|
||||||
return fx;
|
|
||||||
}
|
|
||||||
|
|
||||||
long double __extenddftf2(double f)
|
|
||||||
{
|
|
||||||
long double fx;
|
|
||||||
u128_t x;
|
|
||||||
uint64_t a;
|
|
||||||
memcpy(&a, &f, 8);
|
|
||||||
x.x0 = a << 60;
|
|
||||||
if (!(a << 1))
|
|
||||||
x.x1 = a;
|
|
||||||
else if (a << 1 >> 53 == 2047)
|
|
||||||
x.x1 = (0x7fff000000000000 | a >> 63 << 63 | a << 12 >> 16 |
|
|
||||||
(uint64_t)!!(a << 12) << 47);
|
|
||||||
else if (a << 1 >> 53 == 0) {
|
|
||||||
uint64_t adj = 0;
|
|
||||||
while (!(a << 1 >> 1 >> (52 - adj)))
|
|
||||||
adj++;
|
|
||||||
x.x0 <<= adj;
|
|
||||||
x.x1 = a >> 63 << 63 | (15360 - adj + 1) << 48 | a << adj << 12 >> 16;
|
|
||||||
} else
|
|
||||||
x.x1 = a >> 63 << 63 | ((a >> 52 & 2047) + 15360) << 48 | a << 12 >> 16;
|
|
||||||
memcpy(&fx, &x, 16);
|
|
||||||
return fx;
|
|
||||||
}
|
|
||||||
|
|
||||||
float __trunctfsf2(long double f)
|
|
||||||
{
|
|
||||||
u128_t mnt;
|
|
||||||
int32_t exp;
|
|
||||||
int sgn;
|
|
||||||
uint32_t x;
|
|
||||||
float fx;
|
|
||||||
|
|
||||||
f3_unpack(&sgn, &exp, &mnt, f);
|
|
||||||
|
|
||||||
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
|
|
||||||
x = 0x7fc00000 | (uint32_t)sgn << 31 | (mnt.x1 >> 25 & 0x007fffff);
|
|
||||||
else if (exp > 16510)
|
|
||||||
x = 0x7f800000 | (uint32_t)sgn << 31;
|
|
||||||
else if (exp < 16233)
|
|
||||||
x = (uint32_t)sgn << 31;
|
|
||||||
else {
|
|
||||||
exp -= 16257;
|
|
||||||
x = mnt.x1 >> 23 | !!(mnt.x0 | mnt.x1 << 41);
|
|
||||||
if (exp < 0) {
|
|
||||||
x = x >> -exp | !!(x << (32 + exp));
|
|
||||||
exp = 0;
|
|
||||||
}
|
|
||||||
if ((x & 3) == 3 || (x & 7) == 6)
|
|
||||||
x += 4;
|
|
||||||
x = ((x >> 2) + (exp << 23)) | (uint32_t)sgn << 31;
|
|
||||||
}
|
|
||||||
memcpy(&fx, &x, 4);
|
|
||||||
return fx;
|
|
||||||
}
|
|
||||||
|
|
||||||
double __trunctfdf2(long double f)
|
|
||||||
{
|
|
||||||
u128_t mnt;
|
|
||||||
int32_t exp;
|
|
||||||
int sgn;
|
|
||||||
uint64_t x;
|
|
||||||
double fx;
|
|
||||||
|
|
||||||
f3_unpack(&sgn, &exp, &mnt, f);
|
|
||||||
|
|
||||||
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
|
|
||||||
x = (0x7ff8000000000000 | (uint64_t)sgn << 63 |
|
|
||||||
mnt.x1 << 16 >> 12 | mnt.x0 >> 60);
|
|
||||||
else if (exp > 17406)
|
|
||||||
x = 0x7ff0000000000000 | (uint64_t)sgn << 63;
|
|
||||||
else if (exp < 15308)
|
|
||||||
x = (uint64_t)sgn << 63;
|
|
||||||
else {
|
|
||||||
exp -= 15361;
|
|
||||||
x = mnt.x1 << 6 | mnt.x0 >> 58 | !!(mnt.x0 << 6);
|
|
||||||
if (exp < 0) {
|
|
||||||
x = x >> -exp | !!(x << (64 + exp));
|
|
||||||
exp = 0;
|
|
||||||
}
|
|
||||||
if ((x & 3) == 3 || (x & 7) == 6)
|
|
||||||
x += 4;
|
|
||||||
x = ((x >> 2) + ((uint64_t)exp << 52)) | (uint64_t)sgn << 63;
|
|
||||||
}
|
|
||||||
memcpy(&fx, &x, 8);
|
|
||||||
return fx;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t __fixtfsi(long double fa)
|
|
||||||
{
|
|
||||||
u128_t a;
|
|
||||||
int32_t a_exp;
|
|
||||||
int a_sgn;
|
|
||||||
int32_t x;
|
|
||||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
|
||||||
if (a_exp < 16369)
|
|
||||||
return 0;
|
|
||||||
if (a_exp > 16413)
|
|
||||||
return a_sgn ? -0x80000000 : 0x7fffffff;
|
|
||||||
x = a.x1 >> (16431 - a_exp);
|
|
||||||
return a_sgn ? -x : x;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t __fixtfdi(long double fa)
|
|
||||||
{
|
|
||||||
u128_t a;
|
|
||||||
int32_t a_exp;
|
|
||||||
int a_sgn;
|
|
||||||
int64_t x;
|
|
||||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
|
||||||
if (a_exp < 16383)
|
|
||||||
return 0;
|
|
||||||
if (a_exp > 16445)
|
|
||||||
return a_sgn ? -0x8000000000000000 : 0x7fffffffffffffff;
|
|
||||||
x = (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp);
|
|
||||||
return a_sgn ? -x : x;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t __fixunstfsi(long double fa)
|
|
||||||
{
|
|
||||||
u128_t a;
|
|
||||||
int32_t a_exp;
|
|
||||||
int a_sgn;
|
|
||||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
|
||||||
if (a_sgn || a_exp < 16369)
|
|
||||||
return 0;
|
|
||||||
if (a_exp > 16414)
|
|
||||||
return -1;
|
|
||||||
return a.x1 >> (16431 - a_exp);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t __fixunstfdi(long double fa)
|
|
||||||
{
|
|
||||||
u128_t a;
|
|
||||||
int32_t a_exp;
|
|
||||||
int a_sgn;
|
|
||||||
f3_unpack(&a_sgn, &a_exp, &a, fa);
|
|
||||||
if (a_sgn || a_exp < 16383)
|
|
||||||
return 0;
|
|
||||||
if (a_exp > 16446)
|
|
||||||
return -1;
|
|
||||||
return (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp);
|
|
||||||
}
|
|
||||||
|
|
||||||
long double __floatsitf(int32_t a)
|
|
||||||
{
|
|
||||||
int sgn = 0;
|
|
||||||
int exp = 16414;
|
|
||||||
uint32_t mnt = a;
|
|
||||||
u128_t x = { 0, 0 };
|
|
||||||
long double f;
|
|
||||||
int i;
|
|
||||||
if (a) {
|
|
||||||
if (a < 0) {
|
|
||||||
sgn = 1;
|
|
||||||
mnt = -mnt;
|
|
||||||
}
|
|
||||||
for (i = 16; i; i >>= 1)
|
|
||||||
if (!(mnt >> (32 - i))) {
|
|
||||||
mnt <<= i;
|
|
||||||
exp -= i;
|
|
||||||
}
|
|
||||||
x.x1 = ((uint64_t)sgn << 63 | (uint64_t)exp << 48 |
|
|
||||||
(uint64_t)(mnt << 1) << 16);
|
|
||||||
}
|
|
||||||
memcpy(&f, &x, 16);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
long double __floatditf(int64_t a)
|
|
||||||
{
|
|
||||||
int sgn = 0;
|
|
||||||
int exp = 16446;
|
|
||||||
uint64_t mnt = a;
|
|
||||||
u128_t x = { 0, 0 };
|
|
||||||
long double f;
|
|
||||||
int i;
|
|
||||||
if (a) {
|
|
||||||
if (a < 0) {
|
|
||||||
sgn = 1;
|
|
||||||
mnt = -mnt;
|
|
||||||
}
|
|
||||||
for (i = 32; i; i >>= 1)
|
|
||||||
if (!(mnt >> (64 - i))) {
|
|
||||||
mnt <<= i;
|
|
||||||
exp -= i;
|
|
||||||
}
|
|
||||||
x.x0 = mnt << 49;
|
|
||||||
x.x1 = (uint64_t)sgn << 63 | (uint64_t)exp << 48 | mnt << 1 >> 16;
|
|
||||||
}
|
|
||||||
memcpy(&f, &x, 16);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
long double __floatunsitf(uint32_t a)
|
|
||||||
{
|
|
||||||
int exp = 16414;
|
|
||||||
uint32_t mnt = a;
|
|
||||||
u128_t x = { 0, 0 };
|
|
||||||
long double f;
|
|
||||||
int i;
|
|
||||||
if (a) {
|
|
||||||
for (i = 16; i; i >>= 1)
|
|
||||||
if (!(mnt >> (32 - i))) {
|
|
||||||
mnt <<= i;
|
|
||||||
exp -= i;
|
|
||||||
}
|
|
||||||
x.x1 = (uint64_t)exp << 48 | (uint64_t)(mnt << 1) << 16;
|
|
||||||
}
|
|
||||||
memcpy(&f, &x, 16);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
long double __floatunditf(uint64_t a)
|
|
||||||
{
|
|
||||||
int exp = 16446;
|
|
||||||
uint64_t mnt = a;
|
|
||||||
u128_t x = { 0, 0 };
|
|
||||||
long double f;
|
|
||||||
int i;
|
|
||||||
if (a) {
|
|
||||||
for (i = 32; i; i >>= 1)
|
|
||||||
if (!(mnt >> (64 - i))) {
|
|
||||||
mnt <<= i;
|
|
||||||
exp -= i;
|
|
||||||
}
|
|
||||||
x.x0 = mnt << 49;
|
|
||||||
x.x1 = (uint64_t)exp << 48 | mnt << 1 >> 16;
|
|
||||||
}
|
|
||||||
memcpy(&f, &x, 16);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f3_cmp(long double fa, long double fb)
|
|
||||||
{
|
|
||||||
u128_t a, b;
|
|
||||||
memcpy(&a, &fa, 16);
|
|
||||||
memcpy(&b, &fb, 16);
|
|
||||||
return (!(a.x0 | a.x1 << 1 | b.x0 | b.x1 << 1) ? 0 :
|
|
||||||
((a.x1 << 1 >> 49 == 0x7fff && (a.x0 | a.x1 << 16)) ||
|
|
||||||
(b.x1 << 1 >> 49 == 0x7fff && (b.x0 | b.x1 << 16))) ? 2 :
|
|
||||||
a.x1 >> 63 != b.x1 >> 63 ? (int)(b.x1 >> 63) - (int)(a.x1 >> 63) :
|
|
||||||
a.x1 < b.x1 ? (int)(a.x1 >> 63 << 1) - 1 :
|
|
||||||
a.x1 > b.x1 ? 1 - (int)(a.x1 >> 63 << 1) :
|
|
||||||
a.x0 < b.x0 ? (int)(a.x1 >> 63 << 1) - 1 :
|
|
||||||
b.x0 < a.x0 ? 1 - (int)(a.x1 >> 63 << 1) : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __eqtf2(long double a, long double b)
|
|
||||||
{
|
|
||||||
return !!f3_cmp(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __netf2(long double a, long double b)
|
|
||||||
{
|
|
||||||
return !!f3_cmp(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __lttf2(long double a, long double b)
|
|
||||||
{
|
|
||||||
return f3_cmp(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __letf2(long double a, long double b)
|
|
||||||
{
|
|
||||||
return f3_cmp(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __gttf2(long double a, long double b)
|
|
||||||
{
|
|
||||||
return -f3_cmp(b, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __getf2(long double a, long double b)
|
|
||||||
{
|
|
||||||
return -f3_cmp(b, a);
|
|
||||||
}
|
|
|
@ -106,11 +106,7 @@ union float_long {
|
||||||
unsigned int l;
|
unsigned int l;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* XXX: we don't support several builtin supports for now */
|
|
||||||
#if !defined __x86_64__ && !defined __arm__ && !defined __riscv
|
|
||||||
|
|
||||||
/* XXX: use gcc/tcc intrinsic ? */
|
/* XXX: use gcc/tcc intrinsic ? */
|
||||||
#if defined __i386__
|
|
||||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
||||||
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
|
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
|
||||||
: "=r" ((USItype) (sh)), \
|
: "=r" ((USItype) (sh)), \
|
||||||
|
@ -139,9 +135,6 @@ union float_long {
|
||||||
: "=r" (__cbtmp) : "rm" ((USItype) (x))); \
|
: "=r" (__cbtmp) : "rm" ((USItype) (x))); \
|
||||||
(count) = __cbtmp ^ 31; \
|
(count) = __cbtmp ^ 31; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
|
||||||
#error unsupported CPU type
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* most of this code is taken from libgcc2.c from gcc */
|
/* most of this code is taken from libgcc2.c from gcc */
|
||||||
|
|
||||||
|
@ -478,7 +471,6 @@ long long __ashldi3(long long a, int b)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !__x86_64__ */
|
|
||||||
|
|
||||||
/* XXX: fix tcc's code generator to do this instead */
|
/* XXX: fix tcc's code generator to do this instead */
|
||||||
float __floatundisf(unsigned long long a)
|
float __floatundisf(unsigned long long a)
|
||||||
|
@ -594,7 +586,6 @@ long long __fixdfdi (double a1)
|
||||||
return s ? ret : -ret;
|
return s ? ret : -ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __arm__
|
|
||||||
unsigned long long __fixunsxfdi (long double a1)
|
unsigned long long __fixunsxfdi (long double a1)
|
||||||
{
|
{
|
||||||
register union ldouble_long dl1;
|
register union ldouble_long dl1;
|
||||||
|
@ -624,18 +615,6 @@ long long __fixxfdi (long double a1)
|
||||||
ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1);
|
ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1);
|
||||||
return s ? ret : -ret;
|
return s ? ret : -ret;
|
||||||
}
|
}
|
||||||
#endif /* !ARM */
|
|
||||||
|
|
||||||
#if defined __x86_64__
|
|
||||||
/* float constants used for unary minus operation */
|
|
||||||
const float __mzerosf = -0.0;
|
|
||||||
const double __mzerodf = -0.0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined _WIN64
|
|
||||||
/* MSVC x64 intrinsic */
|
|
||||||
void __faststorefence(void)
|
|
||||||
{
|
|
||||||
__asm__("lock; orl $0,(%rsp)");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
/* ------------------------------------------------------------- */
|
|
||||||
/* support for tcc_run() */
|
|
||||||
|
|
||||||
#ifdef __leading_underscore
|
|
||||||
# define _(s) s
|
|
||||||
#else
|
|
||||||
# define _(s) _##s
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
extern void (*_(_init_array_start)[]) (int argc, char **argv, char **envp);
|
|
||||||
extern void (*_(_init_array_end)[]) (int argc, char **argv, char **envp);
|
|
||||||
static void run_ctors(int argc, char **argv, char **env)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
while (&_(_init_array_start)[i] != _(_init_array_end))
|
|
||||||
(*_(_init_array_start)[i++])(argc, argv, env);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void (*_(_fini_array_start)[]) (void);
|
|
||||||
extern void (*_(_fini_array_end)[]) (void);
|
|
||||||
static void run_dtors(void)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
while (&_(_fini_array_end)[i] != _(_fini_array_start))
|
|
||||||
(*_(_fini_array_end)[--i])();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *rt_exitfunc[32];
|
|
||||||
static void *rt_exitarg[32];
|
|
||||||
static int __rt_nr_exit;
|
|
||||||
|
|
||||||
void __run_on_exit(int ret)
|
|
||||||
{
|
|
||||||
int n = __rt_nr_exit;
|
|
||||||
while (n)
|
|
||||||
--n, ((void(*)(int,void*))rt_exitfunc[n])(ret, rt_exitarg[n]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int on_exit(void *function, void *arg)
|
|
||||||
{
|
|
||||||
int n = __rt_nr_exit;
|
|
||||||
if (n < 32) {
|
|
||||||
rt_exitfunc[n] = function;
|
|
||||||
rt_exitarg[n] = arg;
|
|
||||||
__rt_nr_exit = n + 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int atexit(void (*function)(void))
|
|
||||||
{
|
|
||||||
return on_exit(function, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct rt_frame {
|
|
||||||
void *ip, *fp, *sp;
|
|
||||||
} rt_frame;
|
|
||||||
|
|
||||||
__attribute__((noreturn)) void __rt_exit(rt_frame *, int);
|
|
||||||
|
|
||||||
void exit(int code)
|
|
||||||
{
|
|
||||||
rt_frame f;
|
|
||||||
run_dtors();
|
|
||||||
__run_on_exit(code);
|
|
||||||
f.fp = 0;
|
|
||||||
f.ip = exit;
|
|
||||||
__rt_exit(&f, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
int main(int, char**, char**);
|
|
||||||
|
|
||||||
int _runmain(int argc, char **argv, char **envp)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
run_ctors(argc, argv, envp);
|
|
||||||
ret = main(argc, argv, envp);
|
|
||||||
run_dtors();
|
|
||||||
__run_on_exit(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -18,7 +18,6 @@ typedef __SIZE_TYPE__ size_t;
|
||||||
void __atomic_thread_fence(int memorder);
|
void __atomic_thread_fence(int memorder);
|
||||||
#define MemoryBarrier(memorder) __atomic_thread_fence(memorder)
|
#define MemoryBarrier(memorder) __atomic_thread_fence(memorder)
|
||||||
|
|
||||||
#if defined __i386__ || defined __x86_64__
|
|
||||||
#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
|
#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
|
||||||
bool __atomic_compare_exchange_##MODE \
|
bool __atomic_compare_exchange_##MODE \
|
||||||
(volatile void *atom, void *ref, TYPE xchg, \
|
(volatile void *atom, void *ref, TYPE xchg, \
|
||||||
|
@ -35,12 +34,7 @@ void __atomic_thread_fence(int memorder);
|
||||||
*(TYPE *)ref = rv; \
|
*(TYPE *)ref = rv; \
|
||||||
return (rv == cmp); \
|
return (rv == cmp); \
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
|
|
||||||
extern bool __atomic_compare_exchange_##MODE \
|
|
||||||
(volatile void *atom, void *ref, TYPE xchg, \
|
|
||||||
bool weak, int success_memorder, int failure_memorder);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ATOMIC_LOAD(TYPE, MODE) \
|
#define ATOMIC_LOAD(TYPE, MODE) \
|
||||||
TYPE __atomic_load_##MODE(const volatile void *atom, int memorder) \
|
TYPE __atomic_load_##MODE(const volatile void *atom, int memorder) \
|
||||||
|
@ -116,9 +110,6 @@ void __atomic_thread_fence(int memorder);
|
||||||
ATOMIC_GEN(uint8_t, 1, "b")
|
ATOMIC_GEN(uint8_t, 1, "b")
|
||||||
ATOMIC_GEN(uint16_t, 2, "w")
|
ATOMIC_GEN(uint16_t, 2, "w")
|
||||||
ATOMIC_GEN(uint32_t, 4, "l")
|
ATOMIC_GEN(uint32_t, 4, "l")
|
||||||
#if defined __x86_64__ || defined __aarch64__ || defined __riscv
|
|
||||||
ATOMIC_GEN(uint64_t, 8, "q")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* uses alias to allow building with gcc/clang */
|
/* uses alias to allow building with gcc/clang */
|
||||||
#ifdef __TINYC__
|
#ifdef __TINYC__
|
||||||
|
@ -133,17 +124,7 @@ void ATOMIC(signal_fence) (int memorder)
|
||||||
|
|
||||||
void ATOMIC(thread_fence) (int memorder)
|
void ATOMIC(thread_fence) (int memorder)
|
||||||
{
|
{
|
||||||
#if defined __i386__
|
|
||||||
__asm__ volatile("lock orl $0, (%esp)");
|
__asm__ volatile("lock orl $0, (%esp)");
|
||||||
#elif defined __x86_64__
|
|
||||||
__asm__ volatile("lock orq $0, (%rsp)");
|
|
||||||
#elif defined __arm__
|
|
||||||
__asm__ volatile(".int 0xee070fba"); // mcr p15, 0, r0, c7, c10, 5
|
|
||||||
#elif defined __aarch64__
|
|
||||||
__asm__ volatile(".int 0xd5033bbf"); // dmb ish
|
|
||||||
#elif defined __riscv
|
|
||||||
__asm__ volatile(".int 0x0ff0000f"); // fence iorw,iorw
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr)
|
bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr)
|
||||||
|
@ -154,11 +135,7 @@ bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr)
|
||||||
case 1: ret = true; break;
|
case 1: ret = true; break;
|
||||||
case 2: ret = true; break;
|
case 2: ret = true; break;
|
||||||
case 4: ret = true; break;
|
case 4: ret = true; break;
|
||||||
#if defined __x86_64__ || defined __aarch64__ || defined __riscv
|
|
||||||
case 8: ret = true; break;
|
|
||||||
#else
|
|
||||||
case 8: ret = false; break;
|
case 8: ret = false; break;
|
||||||
#endif
|
|
||||||
default: ret = false; break;
|
default: ret = false; break;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
/* Simple libc header for TCC
|
|
||||||
*
|
|
||||||
* Add any function you want from the libc there. This file is here
|
|
||||||
* only for your convenience so that you do not need to put the whole
|
|
||||||
* glibc include files on your floppy disk
|
|
||||||
*/
|
|
||||||
#ifndef _TCCLIB_H
|
|
||||||
#define _TCCLIB_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
/* stdlib.h */
|
|
||||||
void *calloc(size_t nmemb, size_t size);
|
|
||||||
void *malloc(size_t size);
|
|
||||||
void free(void *ptr);
|
|
||||||
void *realloc(void *ptr, size_t size);
|
|
||||||
int atoi(const char *nptr);
|
|
||||||
long int strtol(const char *nptr, char **endptr, int base);
|
|
||||||
unsigned long int strtoul(const char *nptr, char **endptr, int base);
|
|
||||||
void exit(int);
|
|
||||||
|
|
||||||
/* stdio.h */
|
|
||||||
typedef struct __FILE FILE;
|
|
||||||
#define EOF (-1)
|
|
||||||
extern FILE *stdin;
|
|
||||||
extern FILE *stdout;
|
|
||||||
extern FILE *stderr;
|
|
||||||
FILE *fopen(const char *path, const char *mode);
|
|
||||||
FILE *fdopen(int fildes, const char *mode);
|
|
||||||
FILE *freopen(const char *path, const char *mode, FILE *stream);
|
|
||||||
int fclose(FILE *stream);
|
|
||||||
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
|
||||||
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
|
||||||
int fgetc(FILE *stream);
|
|
||||||
char *fgets(char *s, int size, FILE *stream);
|
|
||||||
int getc(FILE *stream);
|
|
||||||
int getchar(void);
|
|
||||||
char *gets(char *s);
|
|
||||||
int ungetc(int c, FILE *stream);
|
|
||||||
int fflush(FILE *stream);
|
|
||||||
int putchar (int c);
|
|
||||||
|
|
||||||
int printf(const char *format, ...);
|
|
||||||
int fprintf(FILE *stream, const char *format, ...);
|
|
||||||
int sprintf(char *str, const char *format, ...);
|
|
||||||
int snprintf(char *str, size_t size, const char *format, ...);
|
|
||||||
int asprintf(char **strp, const char *format, ...);
|
|
||||||
int dprintf(int fd, const char *format, ...);
|
|
||||||
int vprintf(const char *format, va_list ap);
|
|
||||||
int vfprintf(FILE *stream, const char *format, va_list ap);
|
|
||||||
int vsprintf(char *str, const char *format, va_list ap);
|
|
||||||
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
|
||||||
int vasprintf(char **strp, const char *format, va_list ap);
|
|
||||||
int vdprintf(int fd, const char *format, va_list ap);
|
|
||||||
|
|
||||||
void perror(const char *s);
|
|
||||||
|
|
||||||
/* string.h */
|
|
||||||
char *strcat(char *dest, const char *src);
|
|
||||||
char *strchr(const char *s, int c);
|
|
||||||
char *strrchr(const char *s, int c);
|
|
||||||
char *strcpy(char *dest, const char *src);
|
|
||||||
void *memcpy(void *dest, const void *src, size_t n);
|
|
||||||
void *memmove(void *dest, const void *src, size_t n);
|
|
||||||
void *memset(void *s, int c, size_t n);
|
|
||||||
char *strdup(const char *s);
|
|
||||||
size_t strlen(const char *s);
|
|
||||||
|
|
||||||
/* dlfcn.h */
|
|
||||||
#define RTLD_LAZY 0x001
|
|
||||||
#define RTLD_NOW 0x002
|
|
||||||
#define RTLD_GLOBAL 0x100
|
|
||||||
|
|
||||||
void *dlopen(const char *filename, int flag);
|
|
||||||
const char *dlerror(void);
|
|
||||||
void *dlsym(void *handle, char *symbol);
|
|
||||||
int dlclose(void *handle);
|
|
||||||
|
|
||||||
#endif /* _TCCLIB_H */
|
|
428
libtcc1/tcov.c
428
libtcc1/tcov.c
|
@ -1,428 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#else
|
|
||||||
#include <windows.h>
|
|
||||||
#include <io.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* section layout (all little endian):
|
|
||||||
32bit offset to executable/so file name
|
|
||||||
filename \0
|
|
||||||
function name \0
|
|
||||||
align to 64 bits
|
|
||||||
64bit function start line
|
|
||||||
64bits end_line(28bits) / start_line(28bits) / flag=0xff(8bits)
|
|
||||||
64bits counter
|
|
||||||
\0
|
|
||||||
\0
|
|
||||||
\0
|
|
||||||
executable/so file name \0
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct tcov_line {
|
|
||||||
unsigned int fline;
|
|
||||||
unsigned int lline;
|
|
||||||
unsigned long long count;
|
|
||||||
} tcov_line;
|
|
||||||
|
|
||||||
typedef struct tcov_function {
|
|
||||||
char *function;
|
|
||||||
unsigned int first_line;
|
|
||||||
unsigned int n_line;
|
|
||||||
unsigned int m_line;
|
|
||||||
tcov_line *line;
|
|
||||||
} tcov_function;
|
|
||||||
|
|
||||||
typedef struct tcov_file {
|
|
||||||
char *filename;
|
|
||||||
unsigned int n_func;
|
|
||||||
unsigned int m_func;
|
|
||||||
tcov_function *func;
|
|
||||||
struct tcov_file *next;
|
|
||||||
} tcov_file;
|
|
||||||
|
|
||||||
static FILE *open_tcov_file (char *cov_filename)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
#ifndef _WIN32
|
|
||||||
struct flock lock;
|
|
||||||
|
|
||||||
lock.l_type = F_WRLCK;
|
|
||||||
lock.l_whence = SEEK_SET;
|
|
||||||
lock.l_start = 0;
|
|
||||||
lock.l_len = 0; /* Until EOF. */
|
|
||||||
lock.l_pid = getpid ();
|
|
||||||
#endif
|
|
||||||
fd = open (cov_filename, O_RDWR | O_CREAT, 0666);
|
|
||||||
if (fd < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
while (fcntl (fd, F_SETLKW, &lock) && errno == EINTR)
|
|
||||||
continue;
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
OVERLAPPED overlapped = { 0 };
|
|
||||||
LockFileEx((HANDLE)_get_osfhandle(fd), LOCKFILE_EXCLUSIVE_LOCK,
|
|
||||||
0, 1, 0, &overlapped);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return fdopen (fd, "r+");
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long long get_value(unsigned char *p, int size)
|
|
||||||
{
|
|
||||||
unsigned long long value = 0;
|
|
||||||
|
|
||||||
p += size;
|
|
||||||
while (size--)
|
|
||||||
value = (value << 8) | *--p;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sort_func (const void *p, const void *q)
|
|
||||||
{
|
|
||||||
const tcov_function *pp = (const tcov_function *) p;
|
|
||||||
const tcov_function *pq = (const tcov_function *) q;
|
|
||||||
|
|
||||||
return pp->first_line > pq->first_line ? 1 :
|
|
||||||
pp->first_line < pq->first_line ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sort_line (const void *p, const void *q)
|
|
||||||
{
|
|
||||||
const tcov_line *pp = (const tcov_line *) p;
|
|
||||||
const tcov_line *pq = (const tcov_line *) q;
|
|
||||||
|
|
||||||
return pp->fline > pq->fline ? 1 :
|
|
||||||
pp->fline < pq->fline ? -1 :
|
|
||||||
pp->count < pq->count ? 1 :
|
|
||||||
pp->count > pq->count ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* sort to let inline functions work */
|
|
||||||
static tcov_file *sort_test_coverage (unsigned char *p)
|
|
||||||
{
|
|
||||||
int i, j, k;
|
|
||||||
unsigned char *start = p;
|
|
||||||
tcov_file *file = NULL;
|
|
||||||
tcov_file *nfile;
|
|
||||||
|
|
||||||
p += 4;
|
|
||||||
while (*p) {
|
|
||||||
char *filename = (char *)p;
|
|
||||||
size_t len = strlen (filename);
|
|
||||||
|
|
||||||
nfile = file;
|
|
||||||
while (nfile) {
|
|
||||||
if (strcmp (nfile->filename, filename) == 0)
|
|
||||||
break;
|
|
||||||
nfile = nfile->next;
|
|
||||||
}
|
|
||||||
if (nfile == NULL) {
|
|
||||||
nfile = malloc (sizeof(tcov_file));
|
|
||||||
if (nfile == NULL) {
|
|
||||||
fprintf (stderr, "Malloc error test_coverage\n");
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
nfile->filename = filename;
|
|
||||||
nfile->n_func = 0;
|
|
||||||
nfile->m_func = 0;
|
|
||||||
nfile->func = NULL;
|
|
||||||
nfile->next = NULL;
|
|
||||||
if (file == NULL)
|
|
||||||
file = nfile;
|
|
||||||
else {
|
|
||||||
tcov_file *lfile = file;
|
|
||||||
|
|
||||||
while (lfile->next)
|
|
||||||
lfile = lfile->next;
|
|
||||||
lfile->next = nfile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p += len + 1;
|
|
||||||
while (*p) {
|
|
||||||
int i;
|
|
||||||
char *function = (char *)p;
|
|
||||||
tcov_function *func;
|
|
||||||
|
|
||||||
p += strlen (function) + 1;
|
|
||||||
p += -(p - start) & 7;
|
|
||||||
for (i = 0; i < nfile->n_func; i++) {
|
|
||||||
func = &nfile->func[i];
|
|
||||||
if (strcmp (func->function, function) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == nfile->n_func) {
|
|
||||||
if (nfile->n_func >= nfile->m_func) {
|
|
||||||
nfile->m_func = nfile->m_func == 0 ? 4 : nfile->m_func * 2;
|
|
||||||
nfile->func = realloc (nfile->func,
|
|
||||||
nfile->m_func *
|
|
||||||
sizeof (tcov_function));
|
|
||||||
if (nfile->func == NULL) {
|
|
||||||
fprintf (stderr, "Realloc error test_coverage\n");
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func = &nfile->func[nfile->n_func++];
|
|
||||||
func->function = function;
|
|
||||||
func->first_line = get_value (p, 8);
|
|
||||||
func->n_line = 0;
|
|
||||||
func->m_line = 0;
|
|
||||||
func->line = NULL;
|
|
||||||
}
|
|
||||||
p += 8;
|
|
||||||
while (*p) {
|
|
||||||
tcov_line *line;
|
|
||||||
unsigned long long val;
|
|
||||||
|
|
||||||
if (func->n_line >= func->m_line) {
|
|
||||||
func->m_line = func->m_line == 0 ? 4 : func->m_line * 2;
|
|
||||||
func->line = realloc (func->line,
|
|
||||||
func->m_line * sizeof (tcov_line));
|
|
||||||
if (func->line == NULL) {
|
|
||||||
fprintf (stderr, "Realloc error test_coverage\n");
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
line = &func->line[func->n_line++];
|
|
||||||
val = get_value (p, 8);
|
|
||||||
line->fline = (val >> 8) & 0xfffffffULL;
|
|
||||||
line->lline = val >> 36;
|
|
||||||
line->count = get_value (p + 8, 8);
|
|
||||||
p += 16;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
nfile = file;
|
|
||||||
while (nfile) {
|
|
||||||
qsort (nfile->func, nfile->n_func, sizeof (tcov_function), sort_func);
|
|
||||||
for (i = 0; i < nfile->n_func; i++) {
|
|
||||||
tcov_function *func = &nfile->func[i];
|
|
||||||
qsort (func->line, func->n_line, sizeof (tcov_line), sort_line);
|
|
||||||
}
|
|
||||||
nfile = nfile->next;
|
|
||||||
}
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* merge with previous tcov file */
|
|
||||||
static void merge_test_coverage (tcov_file *file, FILE *fp,
|
|
||||||
unsigned int *pruns)
|
|
||||||
{
|
|
||||||
unsigned int runs;
|
|
||||||
char *p;
|
|
||||||
char str[10000];
|
|
||||||
|
|
||||||
*pruns = 1;
|
|
||||||
if (fp == NULL)
|
|
||||||
return;
|
|
||||||
if (fgets(str, sizeof(str), fp) &&
|
|
||||||
(p = strrchr (str, ':')) &&
|
|
||||||
(sscanf (p + 1, "%u", &runs) == 1))
|
|
||||||
*pruns = runs + 1;
|
|
||||||
while (file) {
|
|
||||||
int i;
|
|
||||||
size_t len = strlen (file->filename);
|
|
||||||
|
|
||||||
while (fgets(str, sizeof(str), fp) &&
|
|
||||||
(p = strstr(str, "0:File:")) == NULL) {}
|
|
||||||
if ((p = strstr(str, "0:File:")) == NULL ||
|
|
||||||
strncmp (p + strlen("0:File:"), file->filename, len) != 0 ||
|
|
||||||
p[strlen("0:File:") + len] != ' ')
|
|
||||||
break;
|
|
||||||
for (i = 0; i < file->n_func; i++) {
|
|
||||||
int j;
|
|
||||||
tcov_function *func = &file->func[i];
|
|
||||||
unsigned int next_zero = 0;
|
|
||||||
unsigned int curline = 0;
|
|
||||||
|
|
||||||
for (j = 0; j < func->n_line; j++) {
|
|
||||||
tcov_line *line = &func->line[j];
|
|
||||||
unsigned int fline = line->fline;
|
|
||||||
unsigned long long count;
|
|
||||||
unsigned int tmp;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
while (curline < fline &&
|
|
||||||
fgets(str, sizeof(str), fp))
|
|
||||||
if ((p = strchr(str, ':')) &&
|
|
||||||
sscanf (p + 1, "%u", &tmp) == 1)
|
|
||||||
curline = tmp;
|
|
||||||
if (sscanf (str, "%llu%c\n", &count, &c) == 2) {
|
|
||||||
if (next_zero == 0)
|
|
||||||
line->count += count;
|
|
||||||
next_zero = c == '*';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file = file->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* store tcov data in file */
|
|
||||||
void __store_test_coverage (unsigned char * p)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
unsigned int files;
|
|
||||||
unsigned int funcs;
|
|
||||||
unsigned int blocks;
|
|
||||||
unsigned int blocks_run;
|
|
||||||
unsigned int runs;
|
|
||||||
char *cov_filename = (char *)p + get_value (p, 4);
|
|
||||||
FILE *fp;
|
|
||||||
char *q;
|
|
||||||
tcov_file *file;
|
|
||||||
tcov_file *nfile;
|
|
||||||
tcov_function *func;
|
|
||||||
|
|
||||||
fp = open_tcov_file (cov_filename);
|
|
||||||
if (fp == NULL) {
|
|
||||||
fprintf (stderr, "Cannot create coverage file: %s\n", cov_filename);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
file = sort_test_coverage (p);
|
|
||||||
merge_test_coverage (file, fp, &runs);
|
|
||||||
fseek (fp, 0, SEEK_SET);
|
|
||||||
fprintf (fp, " -: 0:Runs:%u\n", runs);
|
|
||||||
files = 0;
|
|
||||||
funcs = 0;
|
|
||||||
blocks = 0;
|
|
||||||
blocks_run = 0;
|
|
||||||
nfile = file;
|
|
||||||
while (nfile) {
|
|
||||||
files++;
|
|
||||||
for (i = 0; i < nfile->n_func; i++) {
|
|
||||||
func = &nfile->func[i];
|
|
||||||
funcs++;
|
|
||||||
for (j = 0; j < func->n_line; j++) {
|
|
||||||
blocks++;
|
|
||||||
blocks_run += func->line[j].count != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nfile = nfile->next;
|
|
||||||
}
|
|
||||||
if (blocks == 0)
|
|
||||||
blocks = 1;
|
|
||||||
fprintf (fp, " -: 0:All:%s Files:%u Functions:%u %.02f%%\n",
|
|
||||||
cov_filename, files, funcs, 100.0 * (double) blocks_run / blocks);
|
|
||||||
nfile = file;
|
|
||||||
while (nfile) {
|
|
||||||
FILE *src = fopen (nfile->filename, "r");
|
|
||||||
unsigned int curline = 1;
|
|
||||||
char str[10000];
|
|
||||||
|
|
||||||
if (src == NULL)
|
|
||||||
goto next;
|
|
||||||
funcs = 0;
|
|
||||||
blocks = 0;
|
|
||||||
blocks_run = 0;
|
|
||||||
for (i = 0; i < nfile->n_func; i++) {
|
|
||||||
func = &nfile->func[i];
|
|
||||||
funcs++;
|
|
||||||
for (j = 0; j < func->n_line; j++) {
|
|
||||||
blocks++;
|
|
||||||
blocks_run += func->line[j].count != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (blocks == 0)
|
|
||||||
blocks = 1;
|
|
||||||
fprintf (fp, " -: 0:File:%s Functions:%u %.02f%%\n",
|
|
||||||
nfile->filename, funcs, 100.0 * (double) blocks_run / blocks);
|
|
||||||
for (i = 0; i < nfile->n_func; i++) {
|
|
||||||
func = &nfile->func[i];
|
|
||||||
|
|
||||||
while (curline < func->first_line &&
|
|
||||||
fgets(str, sizeof(str), src))
|
|
||||||
fprintf (fp, " -:%5u:%s", curline++, str);
|
|
||||||
blocks = 0;
|
|
||||||
blocks_run = 0;
|
|
||||||
for (j = 0; j < func->n_line; j++) {
|
|
||||||
blocks++;
|
|
||||||
blocks_run += func->line[j].count != 0;
|
|
||||||
}
|
|
||||||
if (blocks == 0)
|
|
||||||
blocks = 1;
|
|
||||||
fprintf (fp, " -: 0:Function:%s %.02f%%\n",
|
|
||||||
func->function, 100.0 * (double) blocks_run / blocks);
|
|
||||||
#if 0
|
|
||||||
for (j = 0; j < func->n_line; j++) {
|
|
||||||
unsigned int fline = func->line[j].fline;
|
|
||||||
unsigned int lline = func->line[j].lline;
|
|
||||||
unsigned long long count = func->line[j].count;
|
|
||||||
|
|
||||||
fprintf (fp, "%u %u %llu\n", fline, lline, count);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
for (j = 0; j < func->n_line;) {
|
|
||||||
unsigned int fline = func->line[j].fline;
|
|
||||||
unsigned int lline = func->line[j].lline;
|
|
||||||
unsigned long long count = func->line[j].count;
|
|
||||||
unsigned int has_zero = 0;
|
|
||||||
unsigned int same_line = fline == lline;
|
|
||||||
|
|
||||||
j++;
|
|
||||||
while (j < func->n_line) {
|
|
||||||
unsigned int nfline = func->line[j].fline;
|
|
||||||
unsigned int nlline = func->line[j].lline;
|
|
||||||
unsigned long long ncount = func->line[j].count;
|
|
||||||
|
|
||||||
if (fline == nfline) {
|
|
||||||
if (ncount == 0)
|
|
||||||
has_zero = 1;
|
|
||||||
else if (ncount > count)
|
|
||||||
count = ncount;
|
|
||||||
same_line = nfline == nlline;
|
|
||||||
lline = nlline;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (same_line)
|
|
||||||
lline++;
|
|
||||||
|
|
||||||
while (curline < fline &&
|
|
||||||
fgets(str, sizeof(str), src))
|
|
||||||
fprintf (fp, " -:%5u:%s", curline++, str);
|
|
||||||
while (curline < lline &&
|
|
||||||
fgets(str, sizeof(str), src)) {
|
|
||||||
if (count == 0)
|
|
||||||
fprintf (fp, " #####:%5u:%s",
|
|
||||||
curline, str);
|
|
||||||
else if (has_zero)
|
|
||||||
fprintf (fp, "%8llu*:%5u:%s",
|
|
||||||
count, curline, str);
|
|
||||||
else
|
|
||||||
fprintf (fp, "%9llu:%5u:%s",
|
|
||||||
count, curline, str);
|
|
||||||
curline++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (fgets(str, sizeof(str), src))
|
|
||||||
fprintf (fp, " -:%5u:%s", curline++, str);
|
|
||||||
fclose (src);
|
|
||||||
next:
|
|
||||||
nfile = nfile->next;
|
|
||||||
}
|
|
||||||
while (file) {
|
|
||||||
for (i = 0; i < file->n_func; i++) {
|
|
||||||
func = &file->func[i];
|
|
||||||
free (func->line);
|
|
||||||
}
|
|
||||||
free (file->func);
|
|
||||||
nfile = file;
|
|
||||||
file = file->next;
|
|
||||||
free (nfile);
|
|
||||||
}
|
|
||||||
fclose (fp);
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
/* va_list.c - tinycc support for va_list on X86_64 */
|
|
||||||
|
|
||||||
#if defined __x86_64__
|
|
||||||
|
|
||||||
/* Avoid include files, they may not be available when cross compiling */
|
|
||||||
extern void abort(void);
|
|
||||||
|
|
||||||
/* This should be in sync with our include/stdarg.h */
|
|
||||||
enum __va_arg_type {
|
|
||||||
__va_gen_reg, __va_float_reg, __va_stack
|
|
||||||
};
|
|
||||||
|
|
||||||
/* GCC compatible definition of va_list. */
|
|
||||||
/*predefined by TCC (tcc_predefs.h):
|
|
||||||
typedef struct {
|
|
||||||
unsigned int gp_offset;
|
|
||||||
unsigned int fp_offset;
|
|
||||||
union {
|
|
||||||
unsigned int overflow_offset;
|
|
||||||
char *overflow_arg_area;
|
|
||||||
};
|
|
||||||
char *reg_save_area;
|
|
||||||
} __builtin_va_list[1];
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern void *memcpy(void *dest, const void *src, unsigned long n);
|
|
||||||
|
|
||||||
void *__va_arg(__builtin_va_list ap,
|
|
||||||
int arg_type,
|
|
||||||
int size, int align)
|
|
||||||
{
|
|
||||||
size = (size + 7) & ~7;
|
|
||||||
align = (align + 7) & ~7;
|
|
||||||
switch ((enum __va_arg_type)arg_type) {
|
|
||||||
case __va_gen_reg:
|
|
||||||
if (ap->gp_offset + size <= 48) {
|
|
||||||
ap->gp_offset += size;
|
|
||||||
return ap->reg_save_area + ap->gp_offset - size;
|
|
||||||
}
|
|
||||||
goto use_overflow_area;
|
|
||||||
|
|
||||||
case __va_float_reg:
|
|
||||||
if (ap->fp_offset < 128 + 48) {
|
|
||||||
ap->fp_offset += 16;
|
|
||||||
if (size == 8)
|
|
||||||
return ap->reg_save_area + ap->fp_offset - 16;
|
|
||||||
if (ap->fp_offset < 128 + 48) {
|
|
||||||
memcpy(ap->reg_save_area + ap->fp_offset - 8,
|
|
||||||
ap->reg_save_area + ap->fp_offset, 8);
|
|
||||||
ap->fp_offset += 16;
|
|
||||||
return ap->reg_save_area + ap->fp_offset - 32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goto use_overflow_area;
|
|
||||||
|
|
||||||
case __va_stack:
|
|
||||||
use_overflow_area:
|
|
||||||
ap->overflow_arg_area += size;
|
|
||||||
ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align);
|
|
||||||
return ap->overflow_arg_area - size;
|
|
||||||
|
|
||||||
default: /* should never happen */
|
|
||||||
abort();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -2,4 +2,4 @@ bin_PROGRAMS = tcc
|
||||||
|
|
||||||
tcc_SOURCES = tcc.c tcctools.c
|
tcc_SOURCES = tcc.c tcctools.c
|
||||||
tcc_LDADD = ../libtcc/libtcc.a
|
tcc_LDADD = ../libtcc/libtcc.a
|
||||||
tcc_CPPFLAGS = -I$(top_srcdir)
|
tcc_CPPFLAGS = -I$(top_srcdir)/libtcc/include -I$(top_srcdir)/libtcc
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "libtcc/tcc.h"
|
#include <tcc.h>
|
||||||
#include "tcctools.h"
|
#include "tcctools.h"
|
||||||
|
|
||||||
static const char HELP_STR[] =
|
static const char HELP_STR[] =
|
||||||
|
@ -136,7 +136,6 @@ static void print_search_dirs(TCCState *s)
|
||||||
print_dirs("libraries", s->library_paths, s->nb_library_paths);
|
print_dirs("libraries", s->library_paths, s->nb_library_paths);
|
||||||
printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1);
|
printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1);
|
||||||
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
|
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
|
||||||
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_environment(TCCState *s)
|
static void set_environment(TCCState *s)
|
||||||
|
@ -215,8 +214,6 @@ redo:
|
||||||
fputs(HELP_MORE_STR, stdout);
|
fputs(HELP_MORE_STR, stdout);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (opt == OPT_M32 || opt == OPT_M64)
|
|
||||||
return tcc_tool_cross(s, argv, opt);
|
|
||||||
if (s->verbose)
|
if (s->verbose)
|
||||||
printf("%s", VERSION_STR);
|
printf("%s", VERSION_STR);
|
||||||
if (opt == OPT_AR)
|
if (opt == OPT_AR)
|
||||||
|
|
|
@ -33,7 +33,6 @@ static const char help_str[] =
|
||||||
"General options:\n"
|
"General options:\n"
|
||||||
" -c compile only - generate an object file\n"
|
" -c compile only - generate an object file\n"
|
||||||
" -o outfile set output filename\n"
|
" -o outfile set output filename\n"
|
||||||
" -run run compiled source\n"
|
|
||||||
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
|
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
|
||||||
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
|
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
|
||||||
" -w disable all warnings\n"
|
" -w disable all warnings\n"
|
||||||
|
@ -52,12 +51,7 @@ static const char help_str[] =
|
||||||
" -Ldir add library path 'dir'\n"
|
" -Ldir add library path 'dir'\n"
|
||||||
" -llib link with dynamic or static library 'lib'\n"
|
" -llib link with dynamic or static library 'lib'\n"
|
||||||
" -r generate (relocatable) object file\n"
|
" -r generate (relocatable) object file\n"
|
||||||
" -rdynamic export all global symbols to dynamic linker\n"
|
|
||||||
" -soname set name for shared library to be used at runtime\n"
|
|
||||||
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
||||||
"Debugger options:\n"
|
|
||||||
" -g generate stab runtime debug info\n"
|
|
||||||
" -gdwarf[-x] generate dwarf runtime debug info\n"
|
|
||||||
"Misc. options:\n"
|
"Misc. options:\n"
|
||||||
" -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n"
|
" -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n"
|
||||||
" -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"
|
" -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"
|
||||||
|
@ -81,12 +75,10 @@ static const char help_more_str[] =
|
||||||
" -Wp,-opt same as -opt\n"
|
" -Wp,-opt same as -opt\n"
|
||||||
" -include file include 'file' above each input file\n"
|
" -include file include 'file' above each input file\n"
|
||||||
" -isystem dir add 'dir' to system include path\n"
|
" -isystem dir add 'dir' to system include path\n"
|
||||||
" -static link to static libraries (not recommended)\n"
|
|
||||||
" -dumpversion print version\n"
|
" -dumpversion print version\n"
|
||||||
" -print-search-dirs print search paths\n"
|
" -print-search-dirs print search paths\n"
|
||||||
" -dt with -run/-E: auto-define 'test_...' macros\n"
|
|
||||||
"Ignored options:\n"
|
"Ignored options:\n"
|
||||||
" -arch -C --param -pedantic -pipe -s -traditional\n"
|
" -arch -C --param -pedantic -pipe -s -traditional -g -static -shared\n"
|
||||||
"-W[no-]... warnings:\n"
|
"-W[no-]... warnings:\n"
|
||||||
" all turn on some (*) warnings\n"
|
" all turn on some (*) warnings\n"
|
||||||
" error[=warning] stop after warning (any or specified)\n"
|
" error[=warning] stop after warning (any or specified)\n"
|
||||||
|
@ -104,20 +96,14 @@ static const char help_more_str[] =
|
||||||
" reverse-funcargs evaluate function arguments right to left\n"
|
" reverse-funcargs evaluate function arguments right to left\n"
|
||||||
" gnu89-inline 'extern inline' is like 'static inline'\n"
|
" gnu89-inline 'extern inline' is like 'static inline'\n"
|
||||||
" asynchronous-unwind-tables create eh_frame section [on]\n"
|
" asynchronous-unwind-tables create eh_frame section [on]\n"
|
||||||
" test-coverage create code coverage code\n"
|
|
||||||
"-m... target specific options:\n"
|
"-m... target specific options:\n"
|
||||||
" ms-bitfields use MSVC bitfield layout\n"
|
" ms-bitfields use MSVC bitfield layout\n"
|
||||||
"-Wl,... linker options:\n"
|
"-Wl,... linker options:\n"
|
||||||
" -nostdlib do not link with standard crt/libs\n"
|
" -nostdlib do not link with standard crt/libs\n"
|
||||||
" -[no-]whole-archive load lib(s) fully/only as needed\n"
|
" -[no-]whole-archive load lib(s) fully/only as needed\n"
|
||||||
" -export-all-symbols same as -rdynamic\n"
|
|
||||||
" -export-dynamic same as -rdynamic\n"
|
|
||||||
" -image-base= -Ttext= set base address of executable\n"
|
" -image-base= -Ttext= set base address of executable\n"
|
||||||
" -section-alignment= set section alignment in executable\n"
|
" -section-alignment= set section alignment in executable\n"
|
||||||
" -rpath= set dynamic library search path\n"
|
|
||||||
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
|
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
|
||||||
" -soname= set DT_SONAME elf tag\n"
|
|
||||||
" -Bsymbolic set DT_SYMBOLIC elf tag\n"
|
|
||||||
" -oformat=[coff,binary] set executable output format\n"
|
" -oformat=[coff,binary] set executable output format\n"
|
||||||
" -init= -fini= -Map= -as-needed -O (ignored)\n"
|
" -init= -fini= -Map= -as-needed -O (ignored)\n"
|
||||||
"Predefined macros:\n"
|
"Predefined macros:\n"
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libtcc/tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
//#define ARMAG "!<arch>\n"
|
//#define ARMAG "!<arch>\n"
|
||||||
#define ARFMAG "`\n"
|
#define ARFMAG "`\n"
|
||||||
|
@ -54,7 +54,7 @@ static int ar_usage(int ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
||||||
{
|
{
|
||||||
static const ArHdr arhdr_init = {
|
static const ArHdr arhdr_init = {
|
||||||
"/ ",
|
"/ ",
|
||||||
|
@ -357,93 +357,6 @@ the_end:
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
|
|
||||||
|
|
||||||
#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
|
|
||||||
|
|
||||||
ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int option)
|
|
||||||
{
|
|
||||||
tcc_error_noabort("-m%d not implemented.", option);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <process.h>
|
|
||||||
|
|
||||||
/* - Empty argument or with space/tab (not newline) requires quoting.
|
|
||||||
* - Double-quotes at the value require '\'-escape, regardless of quoting.
|
|
||||||
* - Consecutive (or 1) backslashes at the value all need '\'-escape only if
|
|
||||||
* followed by [escaped] double quote, else taken literally, e.g. <x\\y\>
|
|
||||||
* remains literal without quoting or esc, but <x\\"y\> becomes <x\\\\\"y\>.
|
|
||||||
* - This "before double quote" rule applies also before delimiting quoting,
|
|
||||||
* e.g. <x\y \"z\> becomes <"x\y \\\"z\\"> (quoting required because space).
|
|
||||||
*
|
|
||||||
* https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments
|
|
||||||
*/
|
|
||||||
static char *quote_win32(const char *s)
|
|
||||||
{
|
|
||||||
char *o, *r = tcc_malloc(2 * strlen(s) + 3); /* max-esc, quotes, \0 */
|
|
||||||
int cbs = 0, quoted = !*s; /* consecutive backslashes before current */
|
|
||||||
|
|
||||||
for (o = r; *s; *o++ = *s++) {
|
|
||||||
quoted |= *s == ' ' || *s == '\t';
|
|
||||||
if (*s == '\\' || *s == '"')
|
|
||||||
*o++ = '\\';
|
|
||||||
else
|
|
||||||
o -= cbs; /* undo cbs escapes, if any (not followed by DQ) */
|
|
||||||
cbs = *s == '\\' ? cbs + 1 : 0;
|
|
||||||
}
|
|
||||||
if (quoted) {
|
|
||||||
memmove(r + 1, r, o++ - r);
|
|
||||||
*r = *o++ = '"';
|
|
||||||
} else {
|
|
||||||
o -= cbs;
|
|
||||||
}
|
|
||||||
|
|
||||||
*o = 0;
|
|
||||||
return r; /* don't bother with realloc(r, o-r+1) */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int execvp_win32(const char *prog, char **argv)
|
|
||||||
{
|
|
||||||
int ret; char **p;
|
|
||||||
/* replace all " by \" */
|
|
||||||
for (p = argv; *p; ++p)
|
|
||||||
*p = quote_win32(*p);
|
|
||||||
ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
|
|
||||||
if (-1 == ret)
|
|
||||||
return ret;
|
|
||||||
_cwait(&ret, ret, WAIT_CHILD);
|
|
||||||
exit(ret);
|
|
||||||
}
|
|
||||||
#define execvp execvp_win32
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int target)
|
|
||||||
{
|
|
||||||
char program[4096];
|
|
||||||
char *a0 = argv[0];
|
|
||||||
int prefix = tcc_basename(a0) - a0;
|
|
||||||
|
|
||||||
snprintf(program, sizeof program,
|
|
||||||
"%.*s%s"
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
"-win32"
|
|
||||||
#endif
|
|
||||||
"-tcc"
|
|
||||||
#ifdef _WIN32
|
|
||||||
".exe"
|
|
||||||
#endif
|
|
||||||
, prefix, a0, target == 64 ? "x86_64" : "i386");
|
|
||||||
|
|
||||||
if (strcmp(a0, program))
|
|
||||||
execvp(argv[0] = program, argv);
|
|
||||||
tcc_error_noabort("could not run '%s'", program);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
|
|
||||||
/* -------------------------------------------------------------- */
|
/* -------------------------------------------------------------- */
|
||||||
/* enable commandline wildcard expansion (tcc -o x.exe *.c) */
|
/* enable commandline wildcard expansion (tcc -o x.exe *.c) */
|
||||||
|
|
||||||
|
@ -470,7 +383,7 @@ static char *escape_target_dep(const char *s) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int gen_makedeps(TCCState *s1, const char *target, const char *filename)
|
int gen_makedeps(TCCState *s1, const char *target, const char *filename)
|
||||||
{
|
{
|
||||||
FILE *depout;
|
FILE *depout;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#ifndef TCC_TCCTOOLS_H
|
#ifndef TCC_TCCTOOLS_H
|
||||||
# define TCC_TCCTOOLS_H 1
|
# define TCC_TCCTOOLS_H 1
|
||||||
|
|
||||||
# include "libtcc/libtcc.h"
|
# include "libtcc.h"
|
||||||
|
|
||||||
int tcc_tool_ar(TCCState *s1, int argc, char **argv);
|
int tcc_tool_ar(TCCState *s1, int argc, char **argv);
|
||||||
int tcc_tool_cross(TCCState *s1, char **argv, int target);
|
|
||||||
int gen_makedeps(TCCState *s1, const char *target, const char *filename);
|
int gen_makedeps(TCCState *s1, const char *target, const char *filename);
|
||||||
|
|
||||||
#endif /* !TCC_TCCTOOLS_H */
|
#endif /* !TCC_TCCTOOLS_H */
|
Loading…
Add table
Reference in a new issue