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
|
||||
SUBDIRS = libtcc tcc libtcc1
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
-I.
|
||||
-DHAVE_CONFIG_H
|
||||
-Ilibtcc/include
|
||||
-Ilibtcc
|
|
@ -10,7 +10,8 @@ AC_CONFIG_HEADERS([config.h])
|
|||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
libtcc/Makefile
|
||||
tcc/Makefile])
|
||||
tcc/Makefile
|
||||
libtcc1/Makefile])
|
||||
|
||||
AC_LANG([C])
|
||||
AC_PROG_CC
|
||||
|
@ -18,6 +19,7 @@ AC_PROG_CPP
|
|||
AC_PROG_CC_C_O
|
||||
AC_PROG_RANLIB
|
||||
AM_PROG_AR
|
||||
AM_PROG_AS
|
||||
|
||||
AC_CHECK_INCLUDES_DEFAULT
|
||||
AC_C_CONST
|
||||
|
|
|
@ -3,4 +3,4 @@ libtcc_a_SOURCES = libtcc.c tccpp.c tccgen.c \
|
|||
tccasm.c tccelf.c \
|
||||
i386/gen.c i386/link.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
|
||||
#include "tcc.h"
|
||||
#include "token.h"
|
||||
|
||||
#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_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 */
|
||||
{ 0, },
|
||||
};
|
||||
|
@ -213,7 +214,7 @@ static const uint16_t op0_codes[] = {
|
|||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||
#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)
|
||||
|
@ -382,7 +383,7 @@ static void parse_operand(TCCState *s1, Operand *op)
|
|||
}
|
||||
|
||||
/* XXX: unify with C code output ? */
|
||||
ST_FUNC void gen_expr32(ExprValue *pe)
|
||||
void gen_expr32(ExprValue *pe)
|
||||
{
|
||||
if (pe->pcrel)
|
||||
/* 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;
|
||||
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
|
||||
number and type, otherwise return -1. */
|
||||
ST_FUNC int asm_parse_regvar (int t)
|
||||
int asm_parse_regvar (int t)
|
||||
{
|
||||
const char *s;
|
||||
Operand op;
|
||||
|
@ -987,7 +988,7 @@ ST_FUNC int asm_parse_regvar (int t)
|
|||
|
||||
#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,
|
||||
const uint8_t *clobber_regs,
|
||||
int *pout_reg)
|
||||
|
@ -1239,7 +1240,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||
#endif
|
||||
}
|
||||
|
||||
ST_FUNC void subst_asm_operand(CString *add_str,
|
||||
void subst_asm_operand(CString *add_str,
|
||||
SValue *sv, int modifier)
|
||||
{
|
||||
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 */
|
||||
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,
|
||||
uint8_t *clobber_regs,
|
||||
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;
|
||||
|
||||
|
|
|
@ -18,70 +18,11 @@
|
|||
* 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
|
||||
#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"
|
||||
;
|
||||
|
@ -89,7 +30,7 @@ ST_DATA const char * const target_machine_defs =
|
|||
/* define to 1/0 to [not] have EBX as 4th register */
|
||||
#define USE_EBX 0
|
||||
|
||||
ST_DATA const int reg_classes[NB_REGS] = {
|
||||
const int reg_classes[NB_REGS] = {
|
||||
/* eax */ RC_INT | RC_EAX,
|
||||
/* ecx */ RC_INT | RC_ECX,
|
||||
/* edx */ RC_INT | RC_EDX,
|
||||
|
@ -101,7 +42,7 @@ static unsigned long func_sub_sp_offset;
|
|||
static int func_ret_sub;
|
||||
|
||||
/* XXX: make it faster ? */
|
||||
ST_FUNC void g(int c)
|
||||
void g(int c)
|
||||
{
|
||||
int ind1;
|
||||
if (nocode_wanted)
|
||||
|
@ -113,7 +54,7 @@ ST_FUNC void g(int c)
|
|||
ind = ind1;
|
||||
}
|
||||
|
||||
ST_FUNC void o(unsigned int c)
|
||||
void o(unsigned int c)
|
||||
{
|
||||
while (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 >> 8);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_le32(int c)
|
||||
void gen_le32(int c)
|
||||
{
|
||||
g(c);
|
||||
g(c >> 8);
|
||||
|
@ -136,7 +77,7 @@ ST_FUNC void gen_le32(int c)
|
|||
}
|
||||
|
||||
/* 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) {
|
||||
unsigned char *ptr = cur_text_section->data + t;
|
||||
|
@ -158,7 +99,7 @@ static int oad(int c, int s)
|
|||
return t;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_fill_nops(int bytes)
|
||||
void gen_fill_nops(int bytes)
|
||||
{
|
||||
while (bytes--)
|
||||
g(0x90);
|
||||
|
@ -168,14 +109,14 @@ ST_FUNC void gen_fill_nops(int bytes)
|
|||
#define gjmp2(instr,lbl) oad(instr,lbl)
|
||||
|
||||
/* 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)
|
||||
greloc(cur_text_section, sym, ind, R_386_32);
|
||||
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)
|
||||
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' */
|
||||
ST_FUNC void load(int r, SValue *sv)
|
||||
void load(int r, SValue *sv)
|
||||
{
|
||||
int v, t, ft, fc, fr;
|
||||
SValue v1;
|
||||
|
@ -281,7 +222,7 @@ ST_FUNC void load(int r, SValue *sv)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
|
@ -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
|
||||
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
|
||||
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;
|
||||
return nregs;
|
||||
#else
|
||||
(void)vt;
|
||||
(void)variadic;
|
||||
(void)ret;
|
||||
(void)regsize;
|
||||
*ret_align = 1; // Never have to re-align return values for x86
|
||||
return 0;
|
||||
#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
|
||||
all the parameters in call order. This functions pops all the
|
||||
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;
|
||||
Sym *func_sym;
|
||||
|
@ -488,7 +433,7 @@ ST_FUNC void gfunc_call(int nb_args)
|
|||
#endif
|
||||
|
||||
/* 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;
|
||||
int addr, align, size, func_call, fastcall_nb_regs;
|
||||
|
@ -571,7 +516,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
|||
}
|
||||
|
||||
/* generate function epilog */
|
||||
ST_FUNC void gfunc_epilog(void)
|
||||
void gfunc_epilog(void)
|
||||
{
|
||||
addr_t v, saved_ind;
|
||||
|
||||
|
@ -612,13 +557,13 @@ ST_FUNC void gfunc_epilog(void)
|
|||
}
|
||||
|
||||
/* generate a jump to a label */
|
||||
ST_FUNC int gjmp(int t)
|
||||
int gjmp(int t)
|
||||
{
|
||||
return gjmp2(0xe9, t);
|
||||
}
|
||||
|
||||
/* generate a jump to a fixed address */
|
||||
ST_FUNC void gjmp_addr(int a)
|
||||
void gjmp_addr(int a)
|
||||
{
|
||||
int r;
|
||||
r = a - ind - 2;
|
||||
|
@ -632,7 +577,7 @@ ST_FUNC void gjmp_addr(int a)
|
|||
|
||||
#if 0
|
||||
/* 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;
|
||||
if (r == (char)r)
|
||||
|
@ -642,7 +587,7 @@ ST_FUNC void gjmp_cond_addr(int a, int op)
|
|||
}
|
||||
#endif
|
||||
|
||||
ST_FUNC int gjmp_append(int n, int t)
|
||||
int gjmp_append(int n, int t)
|
||||
{
|
||||
void *p;
|
||||
/* insert vtop->c jump list in t */
|
||||
|
@ -656,14 +601,14 @@ ST_FUNC int gjmp_append(int n, int t)
|
|||
return t;
|
||||
}
|
||||
|
||||
ST_FUNC int gjmp_cond(int op, int t)
|
||||
int gjmp_cond(int op, int t)
|
||||
{
|
||||
g(0x0f);
|
||||
t = gjmp2(op - 16, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
ST_FUNC void gen_opi(int op)
|
||||
void gen_opi(int op)
|
||||
{
|
||||
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
|
||||
two operands are guaranteed to have the same floating point type */
|
||||
/* XXX: need to use ST1 too */
|
||||
ST_FUNC void gen_opf(int op)
|
||||
void gen_opf(int op)
|
||||
{
|
||||
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'
|
||||
and 'long long' cases. */
|
||||
ST_FUNC void gen_cvt_itof(int t)
|
||||
void gen_cvt_itof(void)
|
||||
{
|
||||
save_reg(TREG_ST0);
|
||||
gv(RC_INT);
|
||||
|
@ -954,7 +899,7 @@ ST_FUNC void gen_cvt_itof(int t)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
if (bt == VT_FLOAT)
|
||||
|
@ -972,14 +917,14 @@ ST_FUNC void gen_cvt_ftoi(int t)
|
|||
}
|
||||
|
||||
/* 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 */
|
||||
gv(RC_FLOAT);
|
||||
}
|
||||
|
||||
/* char/short to int conversion */
|
||||
ST_FUNC void gen_cvt_csti(int t)
|
||||
void gen_cvt_csti(int t)
|
||||
{
|
||||
int r, sz, xl;
|
||||
r = gv(RC_INT);
|
||||
|
@ -992,7 +937,7 @@ ST_FUNC void gen_cvt_csti(int t)
|
|||
}
|
||||
|
||||
/* increment tcov counter */
|
||||
ST_FUNC void gen_increment_tcov (SValue *sv)
|
||||
void gen_increment_tcov (SValue *sv)
|
||||
{
|
||||
o(0x0583); /* addl $1, xxx */
|
||||
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 */
|
||||
ST_FUNC void ggoto(void)
|
||||
void ggoto(void)
|
||||
{
|
||||
gcall_or_jmp(1);
|
||||
vtop--;
|
||||
}
|
||||
|
||||
/* 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)*/
|
||||
o(0x89);
|
||||
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
#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 */
|
||||
/*************************************************************/
|
||||
#endif
|
||||
/*************************************************************/
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
#ifdef TARGET_DEFS_ONLY
|
||||
|
||||
#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"
|
||||
#include <tcc.h>
|
||||
|
||||
#ifdef NEED_RELOC_TYPE
|
||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||
relocations, returns -1. */
|
||||
ST_FUNC int code_reloc (int reloc_type)
|
||||
int code_reloc (int reloc_type)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
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
|
||||
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||
different values. */
|
||||
ST_FUNC int gotplt_entry_type (int reloc_type)
|
||||
int gotplt_entry_type (int reloc_type)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_386_RELATIVE:
|
||||
|
@ -92,7 +70,7 @@ ST_FUNC int gotplt_entry_type (int reloc_type)
|
|||
}
|
||||
|
||||
#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;
|
||||
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
|
||||
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;
|
||||
|
||||
|
@ -167,9 +145,9 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||
#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);
|
||||
|
||||
|
@ -295,5 +273,3 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !TARGET_DEFS_ONLY */
|
||||
|
|
|
@ -266,7 +266,7 @@
|
|||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||
#include "asm.h"
|
||||
#include "asm.inc"
|
||||
|
||||
#define ALT(x)
|
||||
#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_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)
|
||||
#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 */
|
||||
|
||||
/* 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);
|
||||
/* an array of pointers to memory to be free'd after errors */
|
||||
ST_DATA void** stk_data;
|
||||
ST_DATA int nb_stk_data;
|
||||
void** stk_data;
|
||||
int nb_stk_data;
|
||||
|
||||
/********************************************************/
|
||||
#ifdef _WIN32
|
||||
ST_FUNC char *normalize_slashes(char *path)
|
||||
char *normalize_slashes(char *path)
|
||||
{
|
||||
char *p;
|
||||
for (p = path; *p; ++p)
|
||||
|
@ -99,7 +99,7 @@ PUB_FUNC char *tcc_fileextension (const char *name)
|
|||
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);
|
||||
char *buf = load_data(fd, 0, len + 1);
|
||||
|
@ -111,10 +111,6 @@ ST_FUNC char *tcc_load_text(int fd)
|
|||
/********************************************************/
|
||||
/* memory management */
|
||||
|
||||
/* we'll need the actual versions for a minute */
|
||||
#undef free
|
||||
#undef realloc
|
||||
|
||||
static void *default_reallocator(void *ptr, unsigned long size)
|
||||
{
|
||||
void *ptr1;
|
||||
|
@ -132,14 +128,6 @@ static void *default_reallocator(void *ptr, unsigned long size)
|
|||
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 */
|
||||
static void *(*reallocator)(void*, unsigned long) = default_reallocator;
|
||||
|
||||
|
@ -208,7 +196,7 @@ struct mem_debug_header {
|
|||
int line_num;
|
||||
char file_name[MEM_DEBUG_FILE_LEN + 1];
|
||||
unsigned magic2;
|
||||
ALIGNED(16) unsigned char magic3[4];
|
||||
__attribute__((aligned(16))) unsigned char magic3[4];
|
||||
};
|
||||
|
||||
typedef struct mem_debug_header mem_debug_header_t;
|
||||
|
@ -369,16 +357,16 @@ PUB_FUNC void tcc_memcheck(int d)
|
|||
#endif
|
||||
|
||||
/* 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;
|
||||
int ret = 1;
|
||||
if (!!(p1 = realpath(f1, NULL))) {
|
||||
if (!!(p2 = realpath(f2, NULL))) {
|
||||
ret = PATHCMP(p1, p2);
|
||||
libc_free(p2); /* realpath() requirement */
|
||||
free(p2); /* realpath() requirement */
|
||||
}
|
||||
libc_free(p1);
|
||||
free(p1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -386,7 +374,7 @@ ST_FUNC int normalized_PATHCMP(const char *f1, const char *f2)
|
|||
/********************************************************/
|
||||
/* 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;
|
||||
void **pp;
|
||||
|
@ -406,7 +394,7 @@ ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data)
|
|||
*nb_ptr = nb;
|
||||
}
|
||||
|
||||
ST_FUNC void dynarray_reset(void *pp, int *n)
|
||||
void dynarray_reset(void *pp, int *n)
|
||||
{
|
||||
void **p;
|
||||
for (p = *(void***)pp; *n; ++p, --*n)
|
||||
|
@ -575,7 +563,7 @@ PUB_FUNC void _tcc_warning(const char *fmt, ...)
|
|||
/********************************************************/
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
|
||||
ST_FUNC void tcc_close(void)
|
||||
void tcc_close(void)
|
||||
{
|
||||
TCCState *s1 = tcc_state;
|
||||
BufferedFile *bf = file;
|
||||
|
@ -626,7 +614,7 @@ static int _tcc_open(TCCState *s1, const char *filename)
|
|||
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);
|
||||
if (fd < 0)
|
||||
|
@ -755,8 +743,7 @@ void tcc_delete(TCCState *s1)
|
|||
dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
|
||||
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
|
||||
|
||||
tcc_free(s1->tcc_lib_path);
|
||||
tcc_free(s1->soname);
|
||||
tcc_free(s1->tcc_lib_path);;
|
||||
tcc_free(s1->rpath);
|
||||
tcc_free(s1->elf_entryname);
|
||||
tcc_free(s1->init_symbol);
|
||||
|
@ -771,8 +758,6 @@ void tcc_delete(TCCState *s1)
|
|||
cstr_free(&s1->cmdline_defs);
|
||||
cstr_free(&s1->cmdline_incl);
|
||||
cstr_free(&s1->linker_arg);
|
||||
/* free loaded dlls array */
|
||||
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
|
||||
tcc_free(s1);
|
||||
#ifdef MEM_DEBUG
|
||||
tcc_memcheck(-1);
|
||||
|
@ -823,35 +808,9 @@ int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
|
|||
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);
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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);
|
||||
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:
|
||||
/* as GNU ld, consider it is an ld script if not recognized */
|
||||
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 */
|
||||
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,
|
||||
s->library_paths, s->nb_library_paths);
|
||||
}
|
||||
|
||||
/* 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];
|
||||
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);
|
||||
}
|
||||
|
||||
#if !defined TCC_TARGET_PE
|
||||
ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
|
||||
int tcc_add_crt(TCCState *s1, const char *filename)
|
||||
{
|
||||
return tcc_add_library_internal(s1, "%s/%s",
|
||||
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 */
|
||||
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,) */
|
||||
ST_FUNC void tcc_add_pragma_libs(TCCState *s1)
|
||||
void tcc_add_pragma_libs(TCCState *s1)
|
||||
{
|
||||
int 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;
|
||||
} else if (link_option(option, "O", &p)) {
|
||||
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)) {
|
||||
copy_linker_arg(&s->rpath, p, ':');
|
||||
} else if (link_option(option, "enable-new-dtags", &p)) {
|
||||
s->enable_new_dtags = 1;
|
||||
} else if (link_option(option, "section-alignment=", &p)) {
|
||||
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) {
|
||||
if (ret > 0)
|
||||
s->filetype |= AFF_WHOLE_ARCHIVE;
|
||||
|
@ -1308,10 +1251,7 @@ static const TCCOption tcc_options[] = {
|
|||
{ "dumpmachine", TCC_OPTION_dumpmachine, 0},
|
||||
{ "dumpversion", TCC_OPTION_dumpversion, 0},
|
||||
{ "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 },
|
||||
{ "shared", TCC_OPTION_shared, 0 },
|
||||
{ "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
|
||||
{ "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
|
||||
{ "pthread", TCC_OPTION_pthread, 0},
|
||||
{ "rdynamic", TCC_OPTION_rdynamic, 0 },
|
||||
|
@ -1346,6 +1286,9 @@ static const TCCOption tcc_options[] = {
|
|||
{ "pipe", 0, 0 },
|
||||
{ "s", 0, 0 },
|
||||
{ "traditional", 0, 0 },
|
||||
{ "static", 0, 0},
|
||||
{ "shared", 0, 0},
|
||||
{ "soname", 0, 0},
|
||||
{ NULL, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -1591,21 +1534,13 @@ dorun:
|
|||
s->dflag = 3;
|
||||
else if (*optarg == 'M')
|
||||
s->dflag = 7;
|
||||
else if (isnum(*optarg))
|
||||
s->g_debug |= atoi(optarg);
|
||||
else
|
||||
goto unsupported_option;
|
||||
break;
|
||||
case TCC_OPTION_static:
|
||||
s->static_link = 1;
|
||||
break;
|
||||
case TCC_OPTION_std:
|
||||
if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0)
|
||||
s->cversion = 201112;
|
||||
break;
|
||||
case TCC_OPTION_soname:
|
||||
s->soname = tcc_strdup(optarg);
|
||||
break;
|
||||
case TCC_OPTION_o:
|
||||
if (s->outfile) {
|
||||
tcc_warning("multiple -o option");
|
||||
|
@ -1655,9 +1590,6 @@ dorun:
|
|||
case TCC_OPTION_w:
|
||||
s->warn_none = 1;
|
||||
break;
|
||||
case TCC_OPTION_rdynamic:
|
||||
s->rdynamic = 1;
|
||||
break;
|
||||
case TCC_OPTION_Wl:
|
||||
if (s->linker_arg.size)
|
||||
((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);
|
||||
#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
|
||||
#include "tcc.h"
|
||||
#include "utils/string.h"
|
||||
#ifdef CONFIG_TCC_ASM
|
||||
#include "token.h"
|
||||
|
||||
static Section *last_text_section; /* to handle .previous asm directive */
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ static Sym *asm_label_push(int v)
|
|||
are anonymous in C, in this case CSYM can be used to transfer
|
||||
all information from that symbol to the (possibly newly created)
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
ST_FUNC int asm_int_expr(TCCState *s1)
|
||||
int asm_int_expr(TCCState *s1)
|
||||
{
|
||||
ExprValue 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 */
|
||||
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||
int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||
{
|
||||
int ret;
|
||||
/* 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
|
||||
syntax). return -1 if not found. Return in *pp in char after the
|
||||
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)
|
||||
{
|
||||
int index;
|
||||
|
@ -1182,7 +1182,7 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
|||
}
|
||||
|
||||
/* parse the GCC asm() instruction */
|
||||
ST_FUNC void asm_instr(void)
|
||||
void asm_instr(void)
|
||||
{
|
||||
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;
|
||||
int saved_nocode_wanted = nocode_wanted;
|
||||
|
@ -1361,21 +1361,3 @@ ST_FUNC void asm_global_instr(void)
|
|||
|
||||
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"
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
781
libtcc/tccelf.c
781
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
|
||||
#include "tcc.h"
|
||||
#include "utils/string.h"
|
||||
#include "token.h"
|
||||
|
||||
/********************************************************/
|
||||
/* global variables */
|
||||
|
@ -30,13 +31,13 @@
|
|||
rsym: return symbol
|
||||
anon_sym: anonymous symbol index
|
||||
*/
|
||||
ST_DATA int rsym, anon_sym, ind, loc;
|
||||
int rsym, anon_sym, ind, loc;
|
||||
|
||||
ST_DATA Sym *global_stack;
|
||||
ST_DATA Sym *local_stack;
|
||||
ST_DATA Sym *define_stack;
|
||||
ST_DATA Sym *global_label_stack;
|
||||
ST_DATA Sym *local_label_stack;
|
||||
Sym *global_stack;
|
||||
Sym *local_stack;
|
||||
Sym *define_stack;
|
||||
Sym *global_label_stack;
|
||||
Sym *local_label_stack;
|
||||
|
||||
static Sym *sym_free_first;
|
||||
static void **sym_pools;
|
||||
|
@ -45,11 +46,11 @@ static int nb_sym_pools;
|
|||
static Sym *all_cleanups, *pending_gotos;
|
||||
static int local_scope;
|
||||
|
||||
ST_DATA SValue *vtop;
|
||||
SValue *vtop;
|
||||
static SValue _vstack[1 + VSTACK_SIZE];
|
||||
#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 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 (nocode_wanted & CONST_WANTED_MASK)
|
||||
|
||||
ST_DATA 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) */
|
||||
ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */
|
||||
ST_DATA int func_vc;
|
||||
ST_DATA int func_ind;
|
||||
ST_DATA const char *funcname;
|
||||
ST_DATA CType int_type, func_old_type, char_type, char_pointer_type;
|
||||
int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
||||
CType func_vt; /* current function return type (used by return instruction) */
|
||||
int func_var; /* true if current function is variadic (used by return instruction) */
|
||||
int func_vc;
|
||||
int func_ind;
|
||||
const char *funcname;
|
||||
CType int_type, func_old_type, char_type, char_pointer_type;
|
||||
static CString initstr;
|
||||
|
||||
#if PTR_SIZE == 4
|
||||
|
@ -163,7 +164,7 @@ static void do_Static_assert(void);
|
|||
/* Automagical code suppression */
|
||||
|
||||
/* Clear 'nocode_wanted' at forward label if it was used */
|
||||
ST_FUNC void gsym(int t)
|
||||
void gsym(int t)
|
||||
{
|
||||
if (t) {
|
||||
gsym_addr(t, ind);
|
||||
|
@ -199,7 +200,7 @@ static int gjmp_acs(int t)
|
|||
#define gjmp gjmp_acs
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
ST_INLN int is_float(int t)
|
||||
int is_float(int t)
|
||||
{
|
||||
int bt = t & VT_BTYPE;
|
||||
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
|
||||
non standard math libs */
|
||||
/* XXX: endianness dependent */
|
||||
ST_FUNC int ieee_finite(double d)
|
||||
int ieee_finite(double d)
|
||||
{
|
||||
int p[4];
|
||||
memcpy(p, &d, sizeof(double));
|
||||
|
@ -299,13 +300,13 @@ ST_FUNC int ieee_finite(double d)
|
|||
/* compiling intel long double natively */
|
||||
# define TCC_IS_NATIVE_387
|
||||
|
||||
ST_FUNC void test_lvalue(void)
|
||||
void test_lvalue(void)
|
||||
{
|
||||
if (!(vtop->r & VT_LVAL))
|
||||
expect("lvalue");
|
||||
}
|
||||
|
||||
ST_FUNC void check_vstack(void)
|
||||
void check_vstack(void)
|
||||
{
|
||||
if (vtop != vstack - 1)
|
||||
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 */
|
||||
ST_FUNC void tccgen_init(TCCState *s1)
|
||||
void tccgen_init(TCCState *s1)
|
||||
{
|
||||
vtop = vstack - 1;
|
||||
memset(vtop, 0, sizeof *vtop);
|
||||
|
@ -351,7 +352,7 @@ ST_FUNC void tccgen_init(TCCState *s1)
|
|||
cstr_new(&initstr);
|
||||
}
|
||||
|
||||
ST_FUNC int tccgen_compile(TCCState *s1)
|
||||
int tccgen_compile(TCCState *s1)
|
||||
{
|
||||
funcname = "";
|
||||
func_ind = -1;
|
||||
|
@ -371,7 +372,7 @@ ST_FUNC int tccgen_compile(TCCState *s1)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ST_FUNC void tccgen_finish(TCCState *s1)
|
||||
void tccgen_finish(TCCState *s1)
|
||||
{
|
||||
free_inline_functions(s1);
|
||||
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)
|
||||
return NULL;
|
||||
|
@ -404,7 +405,7 @@ ST_FUNC ElfSym *elfsym(Sym *s)
|
|||
}
|
||||
|
||||
/* apply storage attributes to Elf symbol */
|
||||
ST_FUNC void update_storage(Sym *sym)
|
||||
void update_storage(Sym *sym)
|
||||
{
|
||||
ElfSym *esym;
|
||||
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
|
||||
'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,
|
||||
int can_add_underscore)
|
||||
{
|
||||
|
@ -515,7 +516,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
|
|||
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)))
|
||||
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' */
|
||||
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)
|
||||
{
|
||||
int c = 0;
|
||||
|
@ -542,7 +543,7 @@ ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type,
|
|||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
|
@ -584,7 +585,7 @@ static inline Sym *sym_malloc(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
ST_INLN void sym_free(Sym *sym)
|
||||
void sym_free(Sym *sym)
|
||||
{
|
||||
#ifndef SYM_DEBUG
|
||||
sym->next = sym_free_first;
|
||||
|
@ -595,7 +596,7 @@ ST_INLN void sym_free(Sym *sym)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
|
@ -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
|
||||
of the symbol stack */
|
||||
ST_FUNC Sym *sym_find2(Sym *s, int v)
|
||||
Sym *sym_find2(Sym *s, int v)
|
||||
{
|
||||
while (s) {
|
||||
if (s->v == v)
|
||||
|
@ -623,7 +624,7 @@ ST_FUNC Sym *sym_find2(Sym *s, int v)
|
|||
}
|
||||
|
||||
/* structure lookup */
|
||||
ST_INLN Sym *struct_find(int v)
|
||||
Sym *struct_find(int v)
|
||||
{
|
||||
v -= TOK_IDENT;
|
||||
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
|
||||
|
@ -632,7 +633,7 @@ ST_INLN Sym *struct_find(int v)
|
|||
}
|
||||
|
||||
/* find an identifier */
|
||||
ST_INLN Sym *sym_find(int v)
|
||||
Sym *sym_find(int v)
|
||||
{
|
||||
v -= 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 */
|
||||
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;
|
||||
TokenSym *ts;
|
||||
|
@ -681,7 +682,7 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
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 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;
|
||||
TokenSym *ts;
|
||||
|
@ -730,7 +731,7 @@ ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep)
|
|||
}
|
||||
|
||||
/* label lookup */
|
||||
ST_FUNC Sym *label_find(int v)
|
||||
Sym *label_find(int v)
|
||||
{
|
||||
v -= 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;
|
||||
}
|
||||
|
||||
ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
|
||||
Sym *label_push(Sym **ptop, int v, int flags)
|
||||
{
|
||||
Sym *s, **ps;
|
||||
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
|
||||
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;
|
||||
for(s = *ptop; s != slast; s = s1) {
|
||||
|
@ -824,7 +825,7 @@ static void vsetc(CType *type, int r, CValue *vc)
|
|||
vtop->sym = NULL;
|
||||
}
|
||||
|
||||
ST_FUNC void vswap(void)
|
||||
void vswap(void)
|
||||
{
|
||||
SValue tmp;
|
||||
|
||||
|
@ -835,7 +836,7 @@ ST_FUNC void vswap(void)
|
|||
}
|
||||
|
||||
/* pop stack value */
|
||||
ST_FUNC void vpop(void)
|
||||
void vpop(void)
|
||||
{
|
||||
int v;
|
||||
v = vtop->r & VT_VALMASK;
|
||||
|
@ -868,7 +869,7 @@ static void vpush64(int ty, unsigned long long v)
|
|||
}
|
||||
|
||||
/* push integer constant */
|
||||
ST_FUNC void vpushi(int v)
|
||||
void vpushi(int v)
|
||||
{
|
||||
vpush64(VT_INT, v);
|
||||
}
|
||||
|
@ -885,7 +886,7 @@ static inline void vpushll(long long 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;
|
||||
cval.i = v;
|
||||
|
@ -900,7 +901,7 @@ static void vseti(int r, int v)
|
|||
vset(&type, r, v);
|
||||
}
|
||||
|
||||
ST_FUNC void vpushv(SValue *v)
|
||||
void vpushv(SValue *v)
|
||||
{
|
||||
if (vtop >= vstack + (VSTACK_SIZE - 1))
|
||||
tcc_error("memory full (vstack)");
|
||||
|
@ -914,7 +915,7 @@ static void vdup(void)
|
|||
}
|
||||
|
||||
/* rotate the stack element at position n-1 to the top */
|
||||
ST_FUNC void vrotb(int n)
|
||||
void vrotb(int n)
|
||||
{
|
||||
SValue tmp;
|
||||
if (--n < 1)
|
||||
|
@ -926,7 +927,7 @@ ST_FUNC void vrotb(int n)
|
|||
}
|
||||
|
||||
/* rotate the top stack element into position n-1 */
|
||||
ST_FUNC void vrott(int n)
|
||||
void vrott(int n)
|
||||
{
|
||||
SValue tmp;
|
||||
if (--n < 1)
|
||||
|
@ -938,7 +939,7 @@ ST_FUNC void vrott(int n)
|
|||
}
|
||||
|
||||
/* reverse order of the the first n stack elements */
|
||||
ST_FUNC void vrev(int n)
|
||||
void vrev(int n)
|
||||
{
|
||||
int i;
|
||||
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. */
|
||||
|
||||
/* 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->cmp_op = op;
|
||||
|
@ -1038,7 +1039,7 @@ static void gen_test_zero(int op)
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* push a symbol value of TYPE */
|
||||
ST_FUNC void vpushsym(CType *type, Sym *sym)
|
||||
void vpushsym(CType *type, Sym *sym)
|
||||
{
|
||||
CValue cval;
|
||||
cval.i = 0;
|
||||
|
@ -1047,7 +1048,7 @@ ST_FUNC void vpushsym(CType *type, Sym *sym)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
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' */
|
||||
ST_FUNC Sym *external_global_sym(int v, CType *type)
|
||||
Sym *external_global_sym(int v, CType *type)
|
||||
{
|
||||
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.
|
||||
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 };
|
||||
return external_global_sym(v, &ct);
|
||||
}
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
@ -1289,7 +1290,7 @@ static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad)
|
|||
}
|
||||
|
||||
/* save registers up to (vtop - n) stack entry */
|
||||
ST_FUNC void save_regs(int n)
|
||||
void save_regs(int n)
|
||||
{
|
||||
SValue *p, *p1;
|
||||
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 */
|
||||
ST_FUNC void save_reg(int r)
|
||||
void save_reg(int r)
|
||||
{
|
||||
save_reg_upstack(r, 0);
|
||||
}
|
||||
|
||||
/* save r to the memory stack, and mark it as being free,
|
||||
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;
|
||||
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 */
|
||||
ST_FUNC int get_reg(int rc)
|
||||
int get_reg(int rc)
|
||||
{
|
||||
int r;
|
||||
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) */
|
||||
ST_FUNC void gaddrof(void)
|
||||
void gaddrof(void)
|
||||
{
|
||||
vtop->r &= ~VT_LVAL;
|
||||
/* 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();
|
||||
}
|
||||
|
||||
static int adjust_bf(SValue *sv, int bit_pos, int bit_size)
|
||||
static int adjust_bf(SValue *sv)
|
||||
{
|
||||
int t;
|
||||
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
|
||||
converted to values. Cannot be used if cannot be converted to
|
||||
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 bit_pos, bit_size, size, align;
|
||||
|
@ -1590,7 +1591,7 @@ ST_FUNC int gv(int rc)
|
|||
if ((vtop->type.t & VT_BTYPE) == VT_BOOL)
|
||||
type.t |= VT_UNSIGNED;
|
||||
|
||||
r = adjust_bf(vtop, bit_pos, bit_size);
|
||||
r = adjust_bf(vtop);
|
||||
|
||||
if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
|
||||
type.t |= VT_LLONG;
|
||||
|
@ -1616,7 +1617,7 @@ ST_FUNC int gv(int rc)
|
|||
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
||||
/* CPUs usually cannot use float constants, so we store them
|
||||
generically in data segment */
|
||||
init_params p = { rodata_section };
|
||||
init_params p = { rodata_section, 0, NULL };
|
||||
unsigned long offset;
|
||||
size = type_size(&vtop->type, &align);
|
||||
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 */
|
||||
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
|
||||
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
|
||||
/* expand 64bit on stack in two ints */
|
||||
ST_FUNC void lexpand(void)
|
||||
void lexpand(void)
|
||||
{
|
||||
int u, v;
|
||||
u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED);
|
||||
|
@ -2031,10 +2032,6 @@ static void gen_opl(int op)
|
|||
else if (op1 == TOK_GE)
|
||||
op1 = TOK_UGE;
|
||||
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(0, b);
|
||||
break;
|
||||
|
@ -2216,10 +2213,6 @@ static void gen_opif(int op)
|
|||
{
|
||||
int c1, c2, i, bt;
|
||||
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;
|
||||
|
||||
v1 = vtop - 1;
|
||||
|
@ -2389,6 +2382,7 @@ static void type_to_str(char *buf, int buf_size,
|
|||
tstr = "double";
|
||||
if (!(t & VT_LONG))
|
||||
goto add_tstr;
|
||||
// fall through
|
||||
case VT_LDOUBLE:
|
||||
tstr = "long double";
|
||||
add_tstr:
|
||||
|
@ -2703,7 +2697,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op)
|
|||
}
|
||||
|
||||
/* generic gen_op: handles types problems */
|
||||
ST_FUNC void gen_op(int op)
|
||||
void gen_op(int op)
|
||||
{
|
||||
int t1, t2, bt1, bt2, t;
|
||||
CType type1, combtype;
|
||||
|
@ -2845,7 +2839,7 @@ static void gen_cvt_itof1(int t)
|
|||
vpushi(0);
|
||||
PUT_R_RET(vtop, t);
|
||||
} else {
|
||||
gen_cvt_itof(t);
|
||||
gen_cvt_itof();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3012,7 +3006,7 @@ error:
|
|||
if (sf || df) {
|
||||
if (sf && df) {
|
||||
/* convert from fp to fp */
|
||||
gen_cvt_ftof(dbt);
|
||||
gen_cvt_ftof();
|
||||
} else if (df) {
|
||||
/* convert int to fp */
|
||||
gen_cvt_itof1(dbt);
|
||||
|
@ -3122,7 +3116,7 @@ done:
|
|||
}
|
||||
|
||||
/* 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;
|
||||
int bt;
|
||||
|
@ -3152,11 +3146,7 @@ ST_FUNC int type_size(CType *type, int *a)
|
|||
*a = LDOUBLE_ALIGN;
|
||||
return LDOUBLE_SIZE;
|
||||
} else if (bt == VT_DOUBLE || bt == VT_LLONG) {
|
||||
#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE)
|
||||
*a = 4;
|
||||
#else
|
||||
*a = 8;
|
||||
#endif
|
||||
return 8;
|
||||
} else if (bt == VT_INT || bt == VT_FLOAT) {
|
||||
*a = 4;
|
||||
|
@ -3196,7 +3186,7 @@ static inline CType *pointed_type(CType *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;
|
||||
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 */
|
||||
ST_FUNC void vstore(void)
|
||||
void vstore(void)
|
||||
{
|
||||
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);
|
||||
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) {
|
||||
gen_cast(&vtop[-1].type);
|
||||
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 -- */
|
||||
ST_FUNC void inc(int post, int c)
|
||||
void inc(int post, int c)
|
||||
{
|
||||
test_lvalue();
|
||||
vdup(); /* save lvalue */
|
||||
|
@ -3480,7 +3470,7 @@ ST_FUNC void inc(int post, int c)
|
|||
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 */
|
||||
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 0 returns 0. */
|
||||
ST_FUNC int exact_log2p1(int i)
|
||||
int exact_log2p1(int i)
|
||||
{
|
||||
int ret;
|
||||
if (!i)
|
||||
|
@ -3638,7 +3628,6 @@ redo:
|
|||
case TOK_STDCALL3:
|
||||
ad->f.func_call = FUNC_STDCALL;
|
||||
break;
|
||||
#ifdef TCC_TARGET_I386
|
||||
case TOK_REGPARM1:
|
||||
case TOK_REGPARM2:
|
||||
skip('(');
|
||||
|
@ -3661,7 +3650,6 @@ redo:
|
|||
case TOK_THISCALL3:
|
||||
ad->f.func_call = FUNC_THISCALL;
|
||||
break;
|
||||
#endif
|
||||
case TOK_MODE:
|
||||
skip('(');
|
||||
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('(');
|
||||
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 */
|
||||
ST_FUNC void indir(void)
|
||||
void indir(void)
|
||||
{
|
||||
if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
|
||||
if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
|
||||
|
@ -4972,12 +4960,14 @@ static void parse_builtin_params(int nc, const char *args)
|
|||
continue;
|
||||
case 'V':
|
||||
type.t = VT_CONSTANT;
|
||||
// fall through
|
||||
case 'v':
|
||||
type.t |= VT_VOID;
|
||||
mk_pointer (&type);
|
||||
break;
|
||||
case 'S':
|
||||
type.t = VT_CONSTANT;
|
||||
// fall through
|
||||
case 's':
|
||||
type.t |= char_type.t;
|
||||
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;
|
||||
CType type;
|
||||
|
@ -6176,7 +6166,7 @@ static void expr_eq(void)
|
|||
}
|
||||
}
|
||||
|
||||
ST_FUNC void gexpr(void)
|
||||
void gexpr(void)
|
||||
{
|
||||
expr_eq();
|
||||
if (tok == ',') {
|
||||
|
@ -6217,7 +6207,7 @@ static inline int64_t expr_const64(void)
|
|||
|
||||
/* parse an integer constant and return its value.
|
||||
Complain if it doesn't fit 32bit (signed or unsigned). */
|
||||
ST_FUNC int expr_const(void)
|
||||
int expr_const(void)
|
||||
{
|
||||
int c;
|
||||
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;
|
||||
if (v) {
|
||||
/* local variable */
|
||||
#ifdef CONFIG_TCC_ASM
|
||||
if (ad->asm_label) {
|
||||
int reg = asm_parse_regvar(ad->asm_label);
|
||||
if (reg >= 0)
|
||||
r = (r & ~VT_VALMASK) | reg;
|
||||
}
|
||||
#endif
|
||||
sym = sym_push(v, type, r, addr);
|
||||
if (ad->cleanup_func) {
|
||||
Sym *cls = sym_push2(&all_cleanups,
|
||||
|
@ -7733,8 +7721,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||
sec = rodata_section;
|
||||
} else if (has_init) {
|
||||
sec = data_section;
|
||||
/*if (tcc_state->g_debug & 4)
|
||||
tcc_warning("rw data: %s", get_tok_str(v, 0));*/
|
||||
} else if (tcc_state->nocommon)
|
||||
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
|
||||
#include "tcc.h"
|
||||
#include "utils/string.h"
|
||||
#include "token.h"
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* #define to 1 to enable (see parse_pp_string()) */
|
||||
#define ACCEPT_LF_IN_STRINGS 0
|
||||
|
@ -28,19 +31,19 @@
|
|||
/********************************************************/
|
||||
/* global variables */
|
||||
|
||||
ST_DATA int tok_flags;
|
||||
ST_DATA int parse_flags;
|
||||
int tok_flags;
|
||||
int parse_flags;
|
||||
|
||||
ST_DATA struct BufferedFile *file;
|
||||
ST_DATA int tok;
|
||||
ST_DATA CValue tokc;
|
||||
ST_DATA const int *macro_ptr;
|
||||
ST_DATA CString tokcstr; /* current parsed string, if any */
|
||||
struct BufferedFile *file;
|
||||
int tok;
|
||||
CValue tokc;
|
||||
const int *macro_ptr;
|
||||
CString tokcstr; /* current parsed string, if any */
|
||||
|
||||
/* display benchmark infos */
|
||||
ST_DATA int tok_ident;
|
||||
ST_DATA TokenSym **table_ident;
|
||||
ST_DATA int pp_expr;
|
||||
int tok_ident;
|
||||
TokenSym **table_ident;
|
||||
int pp_expr;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -64,7 +67,7 @@ static TokenString *macro_stack;
|
|||
|
||||
static const char tcc_keywords[] =
|
||||
#define DEF(id, str) str "\0"
|
||||
#include "tcctok.h"
|
||||
#include "token.inc"
|
||||
#undef DEF
|
||||
;
|
||||
|
||||
|
@ -98,7 +101,7 @@ static const unsigned char tok_two_chars[] =
|
|||
0
|
||||
};
|
||||
|
||||
ST_FUNC void skip(int c)
|
||||
void skip(int c)
|
||||
{
|
||||
if (tok != c) {
|
||||
char tmp[40];
|
||||
|
@ -108,7 +111,7 @@ ST_FUNC void skip(int c)
|
|||
next();
|
||||
}
|
||||
|
||||
ST_FUNC void expect(const char *msg)
|
||||
void expect(const char *msg)
|
||||
{
|
||||
tcc_error("%s expected", msg);
|
||||
}
|
||||
|
@ -339,7 +342,7 @@ static void cstr_realloc(CString *cstr, int new_size)
|
|||
}
|
||||
|
||||
/* add a byte */
|
||||
ST_INLN void cstr_ccat(CString *cstr, int ch)
|
||||
void cstr_ccat(CString *cstr, int ch)
|
||||
{
|
||||
int size;
|
||||
size = cstr->size + 1;
|
||||
|
@ -349,7 +352,7 @@ ST_INLN void cstr_ccat(CString *cstr, int ch)
|
|||
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;
|
||||
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 */
|
||||
ST_INLN void cstr_u8cat(CString *cstr, int ch)
|
||||
void cstr_u8cat(CString *cstr, int ch)
|
||||
{
|
||||
char buf[4], *e;
|
||||
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 */
|
||||
ST_FUNC void cstr_cat(CString *cstr, const char *str, int len)
|
||||
void cstr_cat(CString *cstr, const char *str, int len)
|
||||
{
|
||||
int size;
|
||||
if (len <= 0)
|
||||
|
@ -382,7 +385,7 @@ ST_FUNC void cstr_cat(CString *cstr, const char *str, int len)
|
|||
}
|
||||
|
||||
/* add a wide char */
|
||||
ST_FUNC void cstr_wccat(CString *cstr, int ch)
|
||||
void cstr_wccat(CString *cstr, int ch)
|
||||
{
|
||||
int size;
|
||||
size = cstr->size + sizeof(nwchar_t);
|
||||
|
@ -392,24 +395,24 @@ ST_FUNC void cstr_wccat(CString *cstr, int ch)
|
|||
cstr->size = size;
|
||||
}
|
||||
|
||||
ST_FUNC void cstr_new(CString *cstr)
|
||||
void cstr_new(CString *cstr)
|
||||
{
|
||||
memset(cstr, 0, sizeof(CString));
|
||||
}
|
||||
|
||||
/* free string and reset it to NULL */
|
||||
ST_FUNC void cstr_free(CString *cstr)
|
||||
void cstr_free(CString *cstr)
|
||||
{
|
||||
tcc_free(cstr->data);
|
||||
}
|
||||
|
||||
/* reset string to empty */
|
||||
ST_FUNC void cstr_reset(CString *cstr)
|
||||
void cstr_reset(CString *cstr)
|
||||
{
|
||||
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;
|
||||
int len, size = 80;
|
||||
|
@ -429,7 +432,7 @@ ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap)
|
|||
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_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 */
|
||||
ST_FUNC TokenSym *tok_alloc(const char *str, int len)
|
||||
TokenSym *tok_alloc(const char *str, int len)
|
||||
{
|
||||
TokenSym *ts, **pts;
|
||||
int i;
|
||||
|
@ -519,7 +522,7 @@ ST_FUNC TokenSym *tok_alloc(const char *str, int 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;
|
||||
}
|
||||
|
@ -527,7 +530,7 @@ ST_FUNC int tok_alloc_const(const char *str)
|
|||
|
||||
/* XXX: buffer overflow */
|
||||
/* 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;
|
||||
int i, len;
|
||||
|
@ -551,6 +554,7 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv)
|
|||
break;
|
||||
case TOK_LCHAR:
|
||||
cstr_ccat(&cstr_buf, 'L');
|
||||
// fall through
|
||||
case TOK_CCHAR:
|
||||
cstr_ccat(&cstr_buf, '\'');
|
||||
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;
|
||||
case TOK_LSTR:
|
||||
cstr_ccat(&cstr_buf, 'L');
|
||||
// fall through
|
||||
case TOK_STR:
|
||||
cstr_ccat(&cstr_buf, '\"');
|
||||
if (v == TOK_STR) {
|
||||
|
@ -1000,7 +1005,7 @@ static inline int tok_size(const int *p)
|
|||
#endif
|
||||
|
||||
/* token string handling */
|
||||
ST_INLN void tok_str_new(TokenString *s)
|
||||
void tok_str_new(TokenString *s)
|
||||
{
|
||||
s->str = NULL;
|
||||
s->len = s->need_spc = 0;
|
||||
|
@ -1008,25 +1013,25 @@ ST_INLN void tok_str_new(TokenString *s)
|
|||
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);
|
||||
tok_str_new(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
ST_FUNC void tok_str_free_str(int *str)
|
||||
void tok_str_free_str(int *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);
|
||||
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;
|
||||
|
||||
|
@ -1043,7 +1048,7 @@ ST_FUNC int *tok_str_realloc(TokenString *s, int new_size)
|
|||
return s->str;
|
||||
}
|
||||
|
||||
ST_FUNC void tok_str_add(TokenString *s, int t)
|
||||
void tok_str_add(TokenString *s, int t)
|
||||
{
|
||||
int len, *str;
|
||||
|
||||
|
@ -1055,7 +1060,7 @@ ST_FUNC void tok_str_add(TokenString *s, int t)
|
|||
s->len = len;
|
||||
}
|
||||
|
||||
ST_FUNC void begin_macro(TokenString *str, int alloc)
|
||||
void begin_macro(TokenString *str, int alloc)
|
||||
{
|
||||
str->alloc = alloc;
|
||||
str->prev = macro_stack;
|
||||
|
@ -1065,7 +1070,7 @@ ST_FUNC void begin_macro(TokenString *str, int alloc)
|
|||
macro_stack = str;
|
||||
}
|
||||
|
||||
ST_FUNC void end_macro(void)
|
||||
void end_macro(void)
|
||||
{
|
||||
TokenString *str = macro_stack;
|
||||
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' */
|
||||
ST_FUNC void tok_str_add_tok(TokenString *s)
|
||||
void tok_str_add_tok(TokenString *s)
|
||||
{
|
||||
CValue cval;
|
||||
|
||||
|
@ -1272,7 +1277,7 @@ static int macro_is_equal(const int *a, const int *b)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
|
@ -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 */
|
||||
ST_FUNC void define_undef(Sym *s)
|
||||
void define_undef(Sym *s)
|
||||
{
|
||||
int v = s->v;
|
||||
if (v >= TOK_IDENT && v < tok_ident)
|
||||
table_ident[v - TOK_IDENT]->sym_define = NULL;
|
||||
}
|
||||
|
||||
ST_INLN Sym *define_find(int v)
|
||||
Sym *define_find(int v)
|
||||
{
|
||||
v -= 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' */
|
||||
ST_FUNC void free_defines(Sym *b)
|
||||
void free_defines(Sym *b)
|
||||
{
|
||||
while (define_stack != b) {
|
||||
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 */
|
||||
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)
|
||||
void skip_to_eol(int warn)
|
||||
{
|
||||
if (tok == TOK_LINEFEED)
|
||||
return;
|
||||
|
@ -1521,7 +1511,7 @@ static int expr_preprocess(TCCState *s1)
|
|||
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));
|
||||
macro_ptr = macro_stack->str;
|
||||
|
@ -1530,7 +1520,7 @@ ST_FUNC void pp_error(CString *cs)
|
|||
}
|
||||
|
||||
/* parse after #define */
|
||||
ST_FUNC void parse_define(void)
|
||||
void parse_define(void)
|
||||
{
|
||||
Sym *s, *first, **ps;
|
||||
int v, t, varg, is_vaargs, t0;
|
||||
|
@ -1780,7 +1770,7 @@ pragma_err:
|
|||
}
|
||||
|
||||
/* put alternative filename */
|
||||
ST_FUNC void tccpp_putfile(const char *filename)
|
||||
void tccpp_putfile(const char *filename)
|
||||
{
|
||||
char buf[1024];
|
||||
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 */
|
||||
ST_FUNC void preprocess(int is_bof)
|
||||
void preprocess(int is_bof)
|
||||
{
|
||||
TCCState *s1 = tcc_state;
|
||||
int c, n, saved_parse_flags;
|
||||
|
@ -2659,7 +2649,7 @@ maybe_newline:
|
|||
if (!(isidnum_table['$' - CH_EOF] & IS_ID)
|
||||
|| (parse_flags & PARSE_FLAG_ASM_FILE))
|
||||
goto parse_simple;
|
||||
|
||||
// fall through
|
||||
case 'a': case 'b': case 'c': case 'd':
|
||||
case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l':
|
||||
|
@ -3465,7 +3455,7 @@ static int macro_subst(
|
|||
}
|
||||
|
||||
/* return next token with macro substitution */
|
||||
ST_FUNC void next(void)
|
||||
void next(void)
|
||||
{
|
||||
int t;
|
||||
while (macro_ptr) {
|
||||
|
@ -3524,7 +3514,7 @@ convert:
|
|||
|
||||
/* push back current token and set current token to 'last_tok'. Only
|
||||
identifier case handled for labels. */
|
||||
ST_INLN void unget_tok(int last_tok)
|
||||
void unget_tok(int last_tok)
|
||||
{
|
||||
TokenString *str = &unget_buf;
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
|
@ -3631,7 +3621,7 @@ ST_FUNC void preprocess_start(TCCState *s1, int filetype)
|
|||
}
|
||||
|
||||
/* cleanup from error/setjmp */
|
||||
ST_FUNC void preprocess_end(TCCState *s1)
|
||||
void preprocess_end(TCCState *s1)
|
||||
{
|
||||
while (macro_stack)
|
||||
end_macro();
|
||||
|
@ -3641,14 +3631,14 @@ ST_FUNC void preprocess_end(TCCState *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];
|
||||
isidnum_table[c - CH_EOF] = val;
|
||||
return prev;
|
||||
}
|
||||
|
||||
ST_FUNC void tccpp_new(TCCState *s)
|
||||
void tccpp_new(TCCState *s)
|
||||
{
|
||||
int i, c;
|
||||
const char *p, *r;
|
||||
|
@ -3700,7 +3690,7 @@ ST_FUNC void tccpp_new(TCCState *s)
|
|||
define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL);
|
||||
}
|
||||
|
||||
ST_FUNC void tccpp_delete(TCCState *s)
|
||||
void tccpp_delete(TCCState *s)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
|
@ -3852,7 +3842,7 @@ static int pp_check_he0xE(int t, const char *p)
|
|||
}
|
||||
|
||||
/* Preprocess the current file */
|
||||
ST_FUNC int tcc_preprocess(TCCState *s1)
|
||||
int tcc_preprocess(TCCState *s1)
|
||||
{
|
||||
BufferedFile **iptr;
|
||||
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(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
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------- */
|
||||
#if defined __i386__
|
||||
|
||||
.globl _(alloca), _(__alloca)
|
||||
_(alloca):
|
||||
_(__alloca):
|
||||
|
@ -35,51 +32,3 @@ p2:
|
|||
push %eax
|
||||
lea 8(%esp),%eax
|
||||
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
|
||||
#endif
|
||||
|
||||
#if defined __i386__
|
||||
.text
|
||||
.align 2
|
||||
|
||||
|
@ -33,826 +32,3 @@ _(__atomic_clear):
|
|||
xchgb (%edx), %al
|
||||
ret
|
||||
.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_BIG_ENDIAN__ 4321
|
||||
#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 __WINT_TYPE__ int
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
# define __STDC_NO_ATOMICS__ 1
|
||||
# define __STDC_NO_COMPLEX__ 1
|
||||
# define __STDC_NO_THREADS__ 1
|
||||
#if !defined _WIN32
|
||||
# define __STDC_UTF_16__ 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
|
||||
|
||||
/* Some derived integer types needed to get stdint.h to compile correctly on some platforms */
|
||||
#ifndef __NetBSD__
|
||||
#define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__
|
||||
#define __INTPTR_TYPE__ __PTRDIFF_TYPE__
|
||||
#endif
|
||||
#define __INT32_TYPE__ int
|
||||
|
||||
#if !defined _WIN32
|
||||
/* glibc defines. We do not support __USER_NAME_PREFIX__ */
|
||||
#define __REDIRECT(name, proto, alias) name proto __asm__ (#alias)
|
||||
#define __REDIRECT_NTH(name, proto, alias) name proto __asm__ (#alias) __THROW
|
||||
#define __REDIRECT_NTHNL(name, proto, alias) name proto __asm__ (#alias) __THROWNL
|
||||
#endif
|
||||
|
||||
/* not implemented */
|
||||
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||
#define __has_builtin(x) 0
|
||||
#define __has_feature(x) 0
|
||||
#define __has_attribute(x) 0
|
||||
|
||||
/* C23 Keywords */
|
||||
#define _Nonnull
|
||||
#define _Nullable
|
||||
|
@ -181,67 +113,10 @@
|
|||
#endif
|
||||
|
||||
/* __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;
|
||||
#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)))
|
||||
|
||||
#endif
|
||||
#define __builtin_va_end(ap) (void)(ap)
|
||||
#ifndef __builtin_va_copy
|
||||
# define __builtin_va_copy(dest, src) (dest) = (src)
|
||||
|
@ -283,13 +158,6 @@
|
|||
__BOTH(char*, strchr, (const char*, int))
|
||||
__BOTH(char*, strrchr, (const char*, int))
|
||||
__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
|
||||
#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;
|
||||
};
|
||||
|
||||
/* XXX: we don't support several builtin supports for now */
|
||||
#if !defined __x86_64__ && !defined __arm__ && !defined __riscv
|
||||
|
||||
/* XXX: use gcc/tcc intrinsic ? */
|
||||
#if defined __i386__
|
||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
||||
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
|
||||
: "=r" ((USItype) (sh)), \
|
||||
|
@ -139,9 +135,6 @@ union float_long {
|
|||
: "=r" (__cbtmp) : "rm" ((USItype) (x))); \
|
||||
(count) = __cbtmp ^ 31; \
|
||||
} while (0)
|
||||
#else
|
||||
#error unsupported CPU type
|
||||
#endif
|
||||
|
||||
/* 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 /* !__x86_64__ */
|
||||
|
||||
/* XXX: fix tcc's code generator to do this instead */
|
||||
float __floatundisf(unsigned long long a)
|
||||
|
@ -594,7 +586,6 @@ long long __fixdfdi (double a1)
|
|||
return s ? ret : -ret;
|
||||
}
|
||||
|
||||
#ifndef __arm__
|
||||
unsigned long long __fixunsxfdi (long double a1)
|
||||
{
|
||||
register union ldouble_long dl1;
|
||||
|
@ -624,18 +615,6 @@ long long __fixxfdi (long double a1)
|
|||
ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1);
|
||||
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);
|
||||
#define MemoryBarrier(memorder) __atomic_thread_fence(memorder)
|
||||
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
|
||||
bool __atomic_compare_exchange_##MODE \
|
||||
(volatile void *atom, void *ref, TYPE xchg, \
|
||||
|
@ -35,12 +34,7 @@ void __atomic_thread_fence(int memorder);
|
|||
*(TYPE *)ref = rv; \
|
||||
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) \
|
||||
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(uint16_t, 2, "w")
|
||||
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 */
|
||||
#ifdef __TINYC__
|
||||
|
@ -133,17 +124,7 @@ void ATOMIC(signal_fence) (int memorder)
|
|||
|
||||
void ATOMIC(thread_fence) (int memorder)
|
||||
{
|
||||
#if defined __i386__
|
||||
__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)
|
||||
|
@ -154,11 +135,7 @@ bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr)
|
|||
case 1: ret = true; break;
|
||||
case 2: 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;
|
||||
#endif
|
||||
default: ret = false; break;
|
||||
}
|
||||
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_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 "libtcc/tcc.h"
|
||||
#include <tcc.h>
|
||||
#include "tcctools.h"
|
||||
|
||||
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);
|
||||
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);
|
||||
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
|
||||
}
|
||||
|
||||
static void set_environment(TCCState *s)
|
||||
|
@ -215,8 +214,6 @@ redo:
|
|||
fputs(HELP_MORE_STR, stdout);
|
||||
return 0;
|
||||
}
|
||||
if (opt == OPT_M32 || opt == OPT_M64)
|
||||
return tcc_tool_cross(s, argv, opt);
|
||||
if (s->verbose)
|
||||
printf("%s", VERSION_STR);
|
||||
if (opt == OPT_AR)
|
||||
|
|
|
@ -33,7 +33,6 @@ static const char help_str[] =
|
|||
"General options:\n"
|
||||
" -c compile only - generate an object file\n"
|
||||
" -o outfile set output filename\n"
|
||||
" -run run compiled source\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"
|
||||
" -w disable all warnings\n"
|
||||
|
@ -52,12 +51,7 @@ static const char help_str[] =
|
|||
" -Ldir add library path 'dir'\n"
|
||||
" -llib link with dynamic or static library 'lib'\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"
|
||||
"Debugger options:\n"
|
||||
" -g generate stab runtime debug info\n"
|
||||
" -gdwarf[-x] generate dwarf runtime debug info\n"
|
||||
"Misc. options:\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"
|
||||
|
@ -81,12 +75,10 @@ static const char help_more_str[] =
|
|||
" -Wp,-opt same as -opt\n"
|
||||
" -include file include 'file' above each input file\n"
|
||||
" -isystem dir add 'dir' to system include path\n"
|
||||
" -static link to static libraries (not recommended)\n"
|
||||
" -dumpversion print version\n"
|
||||
" -print-search-dirs print search paths\n"
|
||||
" -dt with -run/-E: auto-define 'test_...' macros\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"
|
||||
" all turn on some (*) warnings\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"
|
||||
" gnu89-inline 'extern inline' is like 'static inline'\n"
|
||||
" asynchronous-unwind-tables create eh_frame section [on]\n"
|
||||
" test-coverage create code coverage code\n"
|
||||
"-m... target specific options:\n"
|
||||
" ms-bitfields use MSVC bitfield layout\n"
|
||||
"-Wl,... linker options:\n"
|
||||
" -nostdlib do not link with standard crt/libs\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"
|
||||
" -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"
|
||||
" -soname= set DT_SONAME elf tag\n"
|
||||
" -Bsymbolic set DT_SYMBOLIC elf tag\n"
|
||||
" -oformat=[coff,binary] set executable output format\n"
|
||||
" -init= -fini= -Map= -as-needed -O (ignored)\n"
|
||||
"Predefined macros:\n"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "libtcc/tcc.h"
|
||||
#include "tcc.h"
|
||||
|
||||
//#define ARMAG "!<arch>\n"
|
||||
#define ARFMAG "`\n"
|
||||
|
@ -54,7 +54,7 @@ static int ar_usage(int 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 = {
|
||||
"/ ",
|
||||
|
@ -357,93 +357,6 @@ the_end:
|
|||
* 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) */
|
||||
|
||||
|
@ -470,7 +383,7 @@ static char *escape_target_dep(const char *s) {
|
|||
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;
|
||||
char buf[1024];
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#ifndef TCC_TCCTOOLS_H
|
||||
# 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_cross(TCCState *s1, char **argv, int target);
|
||||
int gen_makedeps(TCCState *s1, const char *target, const char *filename);
|
||||
|
||||
#endif /* !TCC_TCCTOOLS_H */
|
Loading…
Add table
Reference in a new issue