From b2a02961b4407ca76db5a66ca5ae855cbfba4e8e Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Thu, 15 Nov 2012 03:31:49 +0400 Subject: Add support for __builtin_frame_address(level) Continuing d6072d37 (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 after cffb7af9 (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 Cc: Shinichiro Hamaji --- tccgen.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'tccgen.c') diff --git a/tccgen.c b/tccgen.c index f183913..f79da36 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3665,20 +3665,23 @@ ST_FUNC void unary(void) break; case TOK_builtin_frame_address: { + int level; CType type; next(); skip('('); - if (tok != TOK_CINT) { - tcc_error("__builtin_frame_address only takes integers"); - } - if (tokc.i != 0) { - tcc_error("TCC only supports __builtin_frame_address(0)"); + if (tok != TOK_CINT || tokc.i < 0) { + tcc_error("__builtin_frame_address only takes positive integers"); } + level = tokc.i; next(); skip(')'); type.t = VT_VOID; 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; #ifdef TCC_TARGET_X86_64 -- cgit v1.3.1