mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-27 06:10:06 +08:00
Add support for __builtin_frame_address(level)
Continuingd6072d37
(Add __builtin_frame_address(0)) implement __builtin_frame_address for levels greater than zero, in order for tinycc to be able to compile its own lib/bcheck.c aftercffb7af9
(lib/bcheck: Prevent __bound_local_new / __bound_local_delete from being miscompiled). I'm new to the internals, and used the most simple way to do it. Generated code is not very good for levels >= 2, compare gcc tcc level=0 mov %ebp,%eax lea 0x0(%ebp),%eax level=1 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax level=2 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax mov (%eax),%eax mov %eax,-0x10(%ebp) mov -0x10(%ebp),%eax mov (%eax),%eax level=3 mov 0x0(%ebp),%eax mov 0x0(%ebp),%eax mov (%eax),%eax mov (%eax),%ecx mov (%eax),%eax mov (%ecx),%eax But this is still an improvement and for bcheck we need level=1 for which the code is good. For the tests I had to force gcc use -O0 to not inline the functions. And -fno-omit-frame-pointer just in case. If someone knows how to improve the generated code - help is appreciated. Thanks, Kirill Cc: Michael Matz <matz@suse.de> Cc: Shinichiro Hamaji <shinichiro.hamaji@gmail.com>
This commit is contained in:
parent
e79c3533ec
commit
b2a02961b4
15
tccgen.c
15
tccgen.c
@ -3665,20 +3665,23 @@ ST_FUNC void unary(void)
|
|||||||
break;
|
break;
|
||||||
case TOK_builtin_frame_address:
|
case TOK_builtin_frame_address:
|
||||||
{
|
{
|
||||||
|
int level;
|
||||||
CType type;
|
CType type;
|
||||||
next();
|
next();
|
||||||
skip('(');
|
skip('(');
|
||||||
if (tok != TOK_CINT) {
|
if (tok != TOK_CINT || tokc.i < 0) {
|
||||||
tcc_error("__builtin_frame_address only takes integers");
|
tcc_error("__builtin_frame_address only takes positive integers");
|
||||||
}
|
|
||||||
if (tokc.i != 0) {
|
|
||||||
tcc_error("TCC only supports __builtin_frame_address(0)");
|
|
||||||
}
|
}
|
||||||
|
level = tokc.i;
|
||||||
next();
|
next();
|
||||||
skip(')');
|
skip(')');
|
||||||
type.t = VT_VOID;
|
type.t = VT_VOID;
|
||||||
mk_pointer(&type);
|
mk_pointer(&type);
|
||||||
vset(&type, VT_LOCAL, 0);
|
vset(&type, VT_LOCAL, 0); /* local frame */
|
||||||
|
while (level--) {
|
||||||
|
mk_pointer(&vtop->type);
|
||||||
|
indir(); /* -> parent frame */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
@ -73,7 +73,7 @@ libtcc_test$(EXESUF): libtcc_test.c ../$(LIBTCC)
|
|||||||
# copy only tcclib.h so GCC's stddef and stdarg will be used
|
# copy only tcclib.h so GCC's stddef and stdarg will be used
|
||||||
test.ref: tcctest.c
|
test.ref: tcctest.c
|
||||||
cp ../include/tcclib.h .
|
cp ../include/tcclib.h .
|
||||||
$(CC) -o tcctest.gcc $< -I. $(CPPFLAGS) -w $(CFLAGS) $(NATIVE_DEFINES) -std=gnu99 $(LDFLAGS)
|
$(CC) -o tcctest.gcc $< -I. $(CPPFLAGS) -w $(CFLAGS) $(NATIVE_DEFINES) -std=gnu99 -O0 -fno-omit-frame-pointer $(LDFLAGS)
|
||||||
./tcctest.gcc > $@
|
./tcctest.gcc > $@
|
||||||
|
|
||||||
# auto test
|
# auto test
|
||||||
|
@ -89,6 +89,7 @@ void global_data_test(void);
|
|||||||
void cmp_comparison_test(void);
|
void cmp_comparison_test(void);
|
||||||
void math_cmp_test(void);
|
void math_cmp_test(void);
|
||||||
void callsave_test(void);
|
void callsave_test(void);
|
||||||
|
void builtin_frame_address_test(void);
|
||||||
|
|
||||||
int fib(int n);
|
int fib(int n);
|
||||||
void num(int n);
|
void num(int n);
|
||||||
@ -598,6 +599,7 @@ int main(int argc, char **argv)
|
|||||||
cmp_comparison_test();
|
cmp_comparison_test();
|
||||||
math_cmp_test();
|
math_cmp_test();
|
||||||
callsave_test();
|
callsave_test();
|
||||||
|
builtin_frame_address_test();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2680,3 +2682,28 @@ void callsave_test(void)
|
|||||||
printf ("%d\n", i);
|
printf ("%d\n", i);
|
||||||
#endif
|
#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)
|
||||||
|
{
|
||||||
|
char str[] = "__builtin_frame_address";
|
||||||
|
char *fp0 = __builtin_frame_address(0);
|
||||||
|
|
||||||
|
printf("str: %s\n", str);
|
||||||
|
bfa1(str-fp0);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user