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
					
				
					 3 changed files with 37 additions and 7 deletions
				
			
		
							
								
								
									
										15
									
								
								tccgen.c
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,7 +73,7 @@ libtcc_test$(EXESUF): libtcc_test.c ../$(LIBTCC)
 | 
			
		|||
# copy only tcclib.h so GCC's stddef and stdarg will be used
 | 
			
		||||
test.ref: tcctest.c
 | 
			
		||||
	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 > $@
 | 
			
		||||
 | 
			
		||||
# auto test
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,6 +89,7 @@ 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);
 | 
			
		||||
| 
						 | 
				
			
			@ -598,6 +599,7 @@ int main(int argc, char **argv)
 | 
			
		|||
    cmp_comparison_test();
 | 
			
		||||
    math_cmp_test();
 | 
			
		||||
    callsave_test();
 | 
			
		||||
    builtin_frame_address_test();
 | 
			
		||||
    return 0; 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2680,3 +2682,28 @@ void callsave_test(void)
 | 
			
		|||
  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)
 | 
			
		||||
{
 | 
			
		||||
    char str[] = "__builtin_frame_address";
 | 
			
		||||
    char *fp0 = __builtin_frame_address(0);
 | 
			
		||||
 | 
			
		||||
    printf("str: %s\n", str);
 | 
			
		||||
    bfa1(str-fp0);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue