view release on metacpan or search on metacpan
src/Changelog view on Meta::CPAN
- work around a wine cmd bug when building tcc on Windows (Austin English)
- reenable some bound check tests (grischka)
- boundtest.c lookup honors VPATH (grischka)
- diff compared to CC in test[123]b? are now errors (grischka)
- fix test3 on Windows (grischka)
- prevent gcc from building (non functional) libtcc.a (grischka)
- fix warning related to PE file generation on x86-64 (grischka)
- stop mixing ordinary and implicit rule in Makefile (Iavael)
- fix integer to double conversion on ARM (Thomas Preud'homme)
- fix parameter passing of structure < 4 bytes on ARM (Thomas Preud'homme)
- disable builtin_frame_address test on ARM due to gcc bug (Thomas Preud'homme)
- fix initialization of struct on ARM (Thomas Preud'homme)
- fix parameter passing of (unsigned) long long bitfield (Thomas Preud'homme)
- improve float to integer tests (Thomas Preud'homme)
- fix relocation of Thumb branch to ARM function (Thomas Preud'homme)
- fix char wrong compatibility with [un]signed char (Thomas Preud'homme)
- choose the code to compile based on target in libtcc1 (Thomas Preud'homme)
- fix various clang warnings (Thomas Preud'homme)
- don't hardcode tcc in Makefile for tests (Thomas Preud'homme)
- fix relocation of __bound_init bound checking code (Thomas Preud'homme)
- accept only one basic type for a given variable (Thomas Preud'homme)
src/arm64-gen.c view on Meta::CPAN
gv(RC_FRET);
break;
default:
assert(0);
}
}
ST_FUNC void gfunc_epilog(void)
{
if (loc) {
// Insert instructions to subtract size of stack frame from SP.
unsigned char *ptr = cur_text_section->data + arm64_func_sub_sp_offset;
uint64_t diff = (-loc + 15) & ~15;
if (!(diff >> 24)) {
if (diff & 0xfff) // sub sp,sp,#(diff & 0xfff)
write32le(ptr, 0xd10003ff | (diff & 0xfff) << 10);
if (diff >> 12) // sub sp,sp,#(diff >> 12),lsl #12
write32le(ptr + 4, 0xd14003ff | (diff >> 12) << 10);
}
else {
// In this case we may subtract more than necessary,
#define PT_NULL 0 /* Program header table entry unused */
#define PT_LOAD 1 /* Loadable program segment */
#define PT_DYNAMIC 2 /* Dynamic linking information */
#define PT_INTERP 3 /* Program interpreter */
#define PT_NOTE 4 /* Auxiliary information */
#define PT_SHLIB 5 /* Reserved */
#define PT_PHDR 6 /* Entry for header table itself */
#define PT_TLS 7 /* Thread-local storage segment */
#define PT_NUM 8 /* Number of defined types */
#define PT_LOOS 0x60000000 /* Start of OS-specific */
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
#define PT_LOSUNW 0x6ffffffa
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
#define PT_HISUNW 0x6fffffff
#define PT_HIOS 0x6fffffff /* End of OS-specific */
#define PT_LOPROC 0x70000000 /* Start of processor-specific */
#define PT_HIPROC 0x7fffffff /* End of processor-specific */
src/i386-gen.c view on Meta::CPAN
g(func_ret_sub >> 8);
}
/* align local size to word & save local variables */
v = (-loc + 3) & -4;
saved_ind = ind;
ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
#ifdef TCC_TARGET_PE
if (v >= 4096) {
oad(0xb8, v); /* mov stacksize, %eax */
gen_static_call(TOK___chkstk); /* call __chkstk, (does the stackframe too) */
} else
#endif
{
o(0xe58955); /* push %ebp, mov %esp, %ebp */
o(0xec81); /* sub esp, stacksize */
gen_le32(v);
#ifdef TCC_TARGET_PE
o(0x90); /* adjust to FUNC_PROLOG_SIZE */
#endif
}
src/include/stdarg.h view on Meta::CPAN
char *overflow_arg_area;
};
char *reg_save_area;
} __va_list_struct;
typedef __va_list_struct va_list[1];
void __va_start(__va_list_struct *ap, void *fp);
void *__va_arg(__va_list_struct *ap, int arg_type, int size, int align);
#define va_start(ap, last) __va_start(ap, __builtin_frame_address(0))
#define va_arg(ap, type) \
(*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type), __alignof__(type))))
#define va_copy(dest, src) (*(dest) = *(src))
#define va_end(ap)
/* avoid conflicting definition for va_list on Macs. */
#define _VA_LIST_T
#else /* _WIN64 */
typedef char *va_list;
src/lib/bcheck.c view on Meta::CPAN
return p + offset; \
}
BOUND_PTR_INDIR(1)
BOUND_PTR_INDIR(2)
BOUND_PTR_INDIR(4)
BOUND_PTR_INDIR(8)
BOUND_PTR_INDIR(12)
BOUND_PTR_INDIR(16)
/* return the frame pointer of the caller */
#define GET_CALLER_FP(fp)\
{\
fp = (size_t)__builtin_frame_address(1);\
}
/* called when entering a function to add all the local regions */
void FASTCALL __bound_local_new(void *p1)
{
size_t addr, size, fp, *p = p1;
dprintf(stderr, "%s, %s start p1=%p\n", __FILE__, __FUNCTION__, p);
GET_CALLER_FP(fp);
for(;;) {
src/stab.def view on Meta::CPAN
here. */
__define_stab (N_CATCH, 0x54, "CATCH")
/* Structure or union element. Value is offset in the structure. */
__define_stab (N_SSYM, 0x60, "SSYM")
/* Name of main source file.
Value is starting text address of the compilation. */
__define_stab (N_SO, 0x64, "SO")
/* Automatic variable in the stack. Value is offset from frame pointer.
Also used for type descriptions. */
__define_stab (N_LSYM, 0x80, "LSYM")
/* Beginning of an include file. Only Sun uses this.
In an object file, only the name is significant.
The Sun linker puts data into some of the other fields. */
__define_stab (N_BINCL, 0x82, "BINCL")
/* Name of sub-source file (#include file).
Value is starting text address of the compilation. */
__define_stab (N_SOL, 0x84, "SOL")
/* Parameter variable. Value is offset from argument pointer.
(On most machines the argument pointer is the same as the frame pointer. */
__define_stab (N_PSYM, 0xa0, "PSYM")
/* End of an include file. No name.
This and N_BINCL act as brackets around the file's output.
In an object file, there is no significant data in this entry.
The Sun linker puts data into some of the fields. */
__define_stab (N_EINCL, 0xa2, "EINCL")
/* Alternate entry point. Value is its address. */
__define_stab (N_ENTRY, 0xa4, "ENTRY")
src/tcccoff.c view on Meta::CPAN
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;
src/tcccoff.c view on Meta::CPAN
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;
src/tccgen.c view on Meta::CPAN
saved_nocode_wanted = nocode_wanted;
nocode_wanted = 1;
gexpr();
res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
vpop();
nocode_wanted = saved_nocode_wanted;
skip(')');
vpushi(res);
}
break;
case TOK_builtin_frame_address:
case TOK_builtin_return_address:
{
int tok1 = tok;
int level;
CType type;
next();
skip('(');
if (tok != TOK_CINT) {
tcc_error("%s only takes positive integers",
tok1 == TOK_builtin_return_address ?
"__builtin_return_address" :
"__builtin_frame_address");
}
level = (uint32_t)tokc.i;
next();
skip(')');
type.t = VT_VOID;
mk_pointer(&type);
vset(&type, VT_LOCAL, 0); /* local frame */
while (level--) {
mk_pointer(&vtop->type);
indir(); /* -> parent frame */
}
if (tok1 == TOK_builtin_return_address) {
// assume return address is just above frame pointer on stack
vpushi(PTR_SIZE);
gen_op('+');
mk_pointer(&vtop->type);
indir();
}
}
break;
#ifdef TCC_TARGET_X86_64
#ifdef TCC_TARGET_PE
case TOK_builtin_va_start:
src/tccgen.c view on Meta::CPAN
case VT_FUNC:
for(p=vtop->type.ref;p;p=p->prev)
if(p->prev==s)
tcc_error("unsupported expression type");
}
}
/* pop locally defined symbols */
--local_scope;
sym_pop(&local_stack, s);
/* Pop VLA frames and restore stack pointer if required */
if (vlas_in_scope > saved_vlas_in_scope) {
vla_sp_loc = saved_vlas_in_scope ? block_vla_sp_loc : vla_sp_root_loc;
vla_sp_restore();
}
vlas_in_scope = saved_vlas_in_scope;
next();
} else if (tok == TOK_RETURN) {
next();
if (tok != ';') {
src/tccpe.c view on Meta::CPAN
#ifdef TCC_TARGET_X86_64
static unsigned pe_add_uwwind_info(TCCState *s1)
{
if (NULL == s1->uw_pdata) {
s1->uw_pdata = find_section(tcc_state, ".pdata");
s1->uw_pdata->sh_addralign = 4;
s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, NULL);
}
if (0 == s1->uw_offs) {
/* As our functions all have the same stackframe, we use one entry for all */
static const unsigned char uw_info[] = {
0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
0x04, // UBYTE Size of prolog
0x02, // UBYTE Count of unwind codes
0x05, // UBYTE: 4 Frame Register (rbp), UBYTE: 4 Frame Register offset (scaled)
// USHORT * n Unwind codes array
// 0x0b, 0x01, 0xff, 0xff, // stack size
0x04, 0x03, // set frame ptr (mov rsp -> rbp)
0x01, 0x50 // push reg (rbp)
};
Section *s = text_section;
unsigned char *p;
section_ptr_add(s, -s->data_offset & 3); /* align */
s1->uw_offs = s->data_offset;
p = section_ptr_add(s, sizeof uw_info);
memcpy(p, uw_info, sizeof uw_info);
src/tccrun.c view on Meta::CPAN
/* ------------------------------------------------------------- */
#ifdef __i386__
/* fix for glibc 2.1 */
#ifndef REG_EIP
#define REG_EIP EIP
#define REG_EBP EBP
#endif
/* return the PC at frame level 'level'. Return negative if not found */
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
{
addr_t fp;
int i;
if (level == 0) {
#if defined(__APPLE__)
*paddr = uc->uc_mcontext->__ss.__eip;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
*paddr = uc->uc_mcontext.mc_eip;
src/tccrun.c view on Meta::CPAN
fp = ((addr_t *)fp)[0];
}
*paddr = ((addr_t *)fp)[1];
return 0;
}
}
/* ------------------------------------------------------------- */
#elif defined(__x86_64__)
/* return the PC at frame level 'level'. Return negative if not found */
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
{
addr_t fp;
int i;
if (level == 0) {
/* XXX: only support linux */
#if defined(__APPLE__)
*paddr = uc->uc_mcontext->__ss.__rip;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
src/tccrun.c view on Meta::CPAN
fp = ((addr_t *)fp)[0];
}
*paddr = ((addr_t *)fp)[1];
return 0;
}
}
/* ------------------------------------------------------------- */
#elif defined(__arm__)
/* return the PC at frame level 'level'. Return negative if not found */
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
{
addr_t fp, sp;
int i;
if (level == 0) {
/* XXX: only supports linux */
#if defined(__linux__)
*paddr = uc->uc_mcontext.arm_pc;
#else
src/tccrun.c view on Meta::CPAN
return 0;
} else {
#if defined(__linux__)
fp = uc->uc_mcontext.arm_fp;
sp = uc->uc_mcontext.arm_sp;
if (sp < 0x1000)
sp = 0x1000;
#else
return -1;
#endif
/* XXX: specific to tinycc stack frames */
if (fp < sp + 12 || fp & 3)
return -1;
for(i = 1; i < level; i++) {
sp = ((addr_t *)fp)[-2];
if (sp < fp || sp - fp > 16 || sp & 3)
return -1;
fp = ((addr_t *)fp)[-3];
if (fp <= sp || fp - sp < 12 || fp & 3)
return -1;
}
src/tccrun.c view on Meta::CPAN
}
return EXCEPTION_EXECUTE_HANDLER;
}
/* Generate a stack backtrace when a CPU exception occurs. */
static void set_exception_handler(void)
{
SetUnhandledExceptionFilter(cpu_exception_handler);
}
/* return the PC at frame level 'level'. Return non zero if not found */
static int rt_get_caller_pc(addr_t *paddr, CONTEXT *uc, int level)
{
addr_t fp, pc;
int i;
#ifdef _WIN64
pc = uc->Rip;
fp = uc->Rbp;
#else
pc = uc->Eip;
fp = uc->Ebp;
src/tcctok.h view on Meta::CPAN
DEF(TOK_MODE_word, "__word__")
DEF(TOK_DLLEXPORT, "dllexport")
DEF(TOK_DLLIMPORT, "dllimport")
DEF(TOK_NORETURN1, "noreturn")
DEF(TOK_NORETURN2, "__noreturn__")
DEF(TOK_VISIBILITY1, "visibility")
DEF(TOK_VISIBILITY2, "__visibility__")
DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
DEF(TOK_builtin_constant_p, "__builtin_constant_p")
DEF(TOK_builtin_frame_address, "__builtin_frame_address")
DEF(TOK_builtin_return_address, "__builtin_return_address")
DEF(TOK_builtin_expect, "__builtin_expect")
#ifdef TCC_TARGET_X86_64
#ifdef TCC_TARGET_PE
DEF(TOK_builtin_va_start, "__builtin_va_start")
#else
DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types")
#endif
#endif
DEF(TOK_REGPARM1, "regparm")
src/tests/tcctest.c view on Meta::CPAN
void typeof_test(void);
void local_label_test(void);
void statement_expr_test(void);
void asm_test(void);
void builtin_test(void);
void weak_test(void);
void global_data_test(void);
void cmp_comparison_test(void);
void math_cmp_test(void);
void callsave_test(void);
void builtin_frame_address_test(void);
int fib(int n);
void num(int n);
void forward_ref(void);
int isid(int c);
/* Line joining happens before tokenization, so the following
must be parsed as ellipsis. */
void funny_line_continuation (int, ..\
. );
src/tests/tcctest.c view on Meta::CPAN
local_label_test();
asm_test();
builtin_test();
#ifndef _WIN32
weak_test();
#endif
global_data_test();
cmp_comparison_test();
math_cmp_test();
callsave_test();
builtin_frame_address_test();
intdiv_test();
if (via_volatile (42) != 42)
printf ("via_volatile broken\n");
return 0;
}
int tab[3];
int tab2[3][2];
int g;
src/tests/tcctest.c view on Meta::CPAN
with the high 32 bit set (which is likely on x86-64) the access
generates a segfault. */
i = d[0] > get100 ();
printf ("%d\n", i);
#endif
}
void bfa3(ptrdiff_t str_offset)
{
printf("bfa3: %s\n", (char *)__builtin_frame_address(3) + str_offset);
}
void bfa2(ptrdiff_t str_offset)
{
printf("bfa2: %s\n", (char *)__builtin_frame_address(2) + str_offset);
bfa3(str_offset);
}
void bfa1(ptrdiff_t str_offset)
{
printf("bfa1: %s\n", (char *)__builtin_frame_address(1) + str_offset);
bfa2(str_offset);
}
void builtin_frame_address_test(void)
{
/* builtin_frame_address fails on ARM with gcc which make test3 fail */
#ifndef __arm__
char str[] = "__builtin_frame_address";
char *fp0 = __builtin_frame_address(0);
printf("str: %s\n", str);
bfa1(str-fp0);
#endif
}
char via_volatile (char i)
{
char volatile vi;
vi = i;
src/win32/lib/chkstk.S view on Meta::CPAN
/* ---------------------------------------------- */
#ifndef TCC_TARGET_X86_64
/* ---------------------------------------------- */
.globl __chkstk
__chkstk:
xchg (%esp),%ebp /* store ebp, get ret.addr */
push %ebp /* push ret.addr */
lea 4(%esp),%ebp /* setup frame ptr */
push %ecx /* save ecx */
mov %ebp,%ecx
P0:
sub $4096,%ecx
test %eax,(%ecx)
sub $4096,%eax
cmp $4096,%eax
jge P0
sub %eax,%ecx
test %eax,(%ecx)
src/win32/lib/chkstk.S view on Meta::CPAN
/* ---------------------------------------------- */
#else
/* ---------------------------------------------- */
.globl __chkstk
__chkstk:
xchg (%rsp),%rbp /* store ebp, get ret.addr */
push %rbp /* push ret.addr */
lea 8(%rsp),%rbp /* setup frame ptr */
push %rcx /* save ecx */
mov %rbp,%rcx
movslq %eax,%rax
P0:
sub $4096,%rcx
test %rax,(%rcx)
sub $4096,%rax
cmp $4096,%rax
jge P0
sub %rax,%rcx
src/x86_64-gen.c view on Meta::CPAN
}
saved_ind = ind;
ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
/* align local size to word & save local variables */
v = (func_scratch + -loc + 15) & -16;
if (v >= 4096) {
Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
oad(0xb8, v); /* mov stacksize, %eax */
oad(0xe8, 0); /* call __chkstk, (does the stackframe too) */
greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4);
o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */
} else {
o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
o(0xec8148); /* sub rsp, stacksize */
gen_le32(v);
}
cur_text_section->data_offset = saved_ind;
pe_add_unwind_data(ind, saved_ind, v);
src/x86_64-gen.c view on Meta::CPAN
sym = func_type->ref;
addr = PTR_SIZE * 2;
loc = 0;
ind += FUNC_PROLOG_SIZE;
func_sub_sp_offset = ind;
func_ret_sub = 0;
if (func_type->ref->c == FUNC_ELLIPSIS) {
int seen_reg_num, seen_sse_num, seen_stack_size;
seen_reg_num = seen_sse_num = 0;
/* frame pointer and return address */
seen_stack_size = PTR_SIZE * 2;
/* count the number of seen parameters */
sym = func_type->ref;
while ((sym = sym->next) != NULL) {
type = &sym->type;
mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count);
switch (mode) {
default:
stack_arg:
seen_stack_size = ((seen_stack_size + align - 1) & -align) + size;