@ -54,33 +54,10 @@ ST_DATA int const_wanted; /* true if constant wanted */
ST_DATA int nocode_wanted ; /* no code generation wanted */
# define unevalmask 0xffff /* unevaluated subexpression */
# define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */
# define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */
/* Automagical code suppression ----> */
# define DATA_ONLY_WANTED 0x80000000 /* ON outside of functions and for static initializers */
# define CODE_OFF() (nocode_wanted |= 0x20000000)
# define CODE_ON() (nocode_wanted &= ~0x20000000)
/* Clear 'nocode_wanted' at label if it was used */
ST_FUNC void gsym ( int t ) { if ( t ) { gsym_addr ( t , ind ) ; CODE_ON ( ) ; } }
static int gind ( int known_unreachable )
{
int t = ind ;
if ( ! known_unreachable )
CODE_ON ( ) ;
if ( debug_modes )
tcc_tcov_block_begin ( tcc_state ) ;
return t ;
}
/* Set 'nocode_wanted' after unconditional jumps */
static void gjmp_addr_acs ( int t ) { gjmp_addr ( t ) ; CODE_OFF ( ) ; }
static int gjmp_acs ( int t ) { t = gjmp ( t ) ; CODE_OFF ( ) ; return t ; }
/* These are #undef'd at the end of this file */
# define gjmp_addr gjmp_addr_acs
# define gjmp gjmp_acs
/* <---- */
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) */
@ -170,6 +147,46 @@ static int get_temp_local_var(int size,int align);
static void clear_temp_local_var_list ( ) ;
static void cast_error ( CType * st , CType * dt ) ;
/* ------------------------------------------------------------------------- */
/* Automagical code suppression */
/* Clear 'nocode_wanted' at forward label if it was used */
ST_FUNC void gsym ( int t )
{
if ( t ) {
gsym_addr ( t , ind ) ;
CODE_ON ( ) ;
}
}
/* Clear 'nocode_wanted' if current pc is a label */
static int gind ( )
{
int t = ind ;
CODE_ON ( ) ;
if ( debug_modes )
tcc_tcov_block_begin ( tcc_state ) ;
return t ;
}
/* Set 'nocode_wanted' after unconditional (backwards) jump */
static void gjmp_addr_acs ( int t )
{
gjmp_addr ( t ) ;
CODE_OFF ( ) ;
}
/* Set 'nocode_wanted' after unconditional (forwards) jump */
static int gjmp_acs ( int t )
{
t = gjmp ( t ) ;
CODE_OFF ( ) ;
return t ;
}
/* These are #undef'd at the end of this file */
# define gjmp_addr gjmp_addr_acs
# define gjmp gjmp_acs
/* ------------------------------------------------------------------------- */
ST_INLN int is_float ( int t )
@ -358,7 +375,7 @@ ST_FUNC int tccgen_compile(TCCState *s1)
func_ind = - 1 ;
anon_sym = SYM_FIRST_ANOM ;
const_wanted = 0 ;
nocode_wanted = 0x80000000 ;
nocode_wanted = DATA_ONLY_WANTED ; /* no code outside of functions */
local_scope = 0 ;
debug_modes = ( s1 - > do_debug ? 1 : 0 ) | s1 - > test_coverage < < 1 ;
@ -3126,7 +3143,7 @@ error:
}
/* cannot generate code for global or static initializers */
if ( STATIC_DATA _WANTED)
if ( nocode_wanted & DATA_ONLY _WANTED)
goto done ;
/* non constant case: generate code */
@ -4728,7 +4745,7 @@ static int asm_label_instr(void)
static int post_type ( CType * type , AttributeDef * ad , int storage , int td )
{
int n , l , t1 , arg_size , align , unused_align ;
int n , l , t1 , arg_size , align ;
Sym * * plast , * s , * first ;
AttributeDef ad1 ;
CType pt ;
@ -4775,7 +4792,10 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td)
expect ( " identifier " ) ;
convert_parameter_type ( & pt ) ;
arg_size + = ( type_size ( & pt , & align ) + PTR_SIZE - 1 ) / PTR_SIZE ;
s = sym_push ( n , & pt , 0 , 0 ) ;
/* these symbols may be evaluated for VLArrays (see below, under
nocode_wanted ) which is why we push them here as normal symbols
temporarily . Example : int func ( int a , int b [ + + a ] ) ; */
s = sym_push ( n , & pt , VT_LOCAL | VT_LVAL , 0 ) ;
* plast = s ;
plast = & s - > next ;
if ( tok = = ' ) ' )
@ -4842,26 +4862,11 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td)
break ;
}
if ( tok ! = ' ] ' ) {
int nest = 1 ;
/* Code generation is not done now but has to be done
at start of function . Save code here for later use . */
nocode_wanted = 1 ;
vla_array_tok = tok_str_alloc ( ) ;
for ( ; ; ) {
if ( tok = = ' ] ' ) {
nest - - ;
if ( nest = = 0 )
break ;
}
if ( tok = = ' [ ' )
nest + + ;
tok_str_add_tok ( vla_array_tok ) ;
next ( ) ;
}
skip_or_save_block ( & vla_array_tok ) ;
unget_tok ( 0 ) ;
tok_str_add ( vla_array_tok , - 1 ) ;
tok_str_add ( vla_array_tok , 0 ) ;
vla_array_str = vla_array_tok - > str ;
begin_macro ( vla_array_tok , 2 ) ;
next ( ) ;
@ -4902,7 +4907,7 @@ check:
if ( ( type - > t & VT_BTYPE ) = = VT_FUNC )
tcc_error ( " declaration of an array of functions " ) ;
if ( ( type - > t & VT_BTYPE ) = = VT_VOID
| | type_size ( type , & unused_ align) < 0 )
| | type_size ( type , & align ) < 0 )
tcc_error ( " declaration of an array of incomplete type elements " ) ;
t1 | = type - > t & VT_VLA ;
@ -4933,7 +4938,8 @@ check:
s = sym_push ( SYM_FIELD , type , 0 , n ) ;
type - > t = ( t1 ? VT_VLA : VT_ARRAY ) | VT_PTR ;
type - > ref = s ;
if ( vla_array_str ) {
if ( vla_array_str ) {
if ( t1 & VT_VLA )
s - > vla_array_str = vla_array_str ;
else
@ -6783,7 +6789,7 @@ again:
}
} else if ( t = = TOK_WHILE ) {
d = gind ( 0 ) ;
d = gind ( ) ;
skip ( ' ( ' ) ;
gexpr ( ) ;
skip ( ' ) ' ) ;
@ -6883,7 +6889,7 @@ again:
}
skip ( ' ; ' ) ;
a = b = 0 ;
c = d = gind ( 0 ) ;
c = d = gind ( ) ;
if ( tok ! = ' ; ' ) {
gexpr ( ) ;
a = gvtst ( 1 , 0 ) ;
@ -6891,7 +6897,7 @@ again:
skip ( ' ; ' ) ;
if ( tok ! = ' ) ' ) {
e = gjmp ( 0 ) ;
d = gind ( 0 ) ;
d = gind ( ) ;
gexpr ( ) ;
vpop ( ) ;
gjmp_addr ( c ) ;
@ -6906,7 +6912,7 @@ again:
} else if ( t = = TOK_DO ) {
a = b = 0 ;
d = gind ( 0 ) ;
d = gind ( ) ;
lblock ( & a , & b ) ;
gsym ( b ) ;
skip ( TOK_WHILE ) ;
@ -6940,17 +6946,17 @@ again:
/* case lookup */
gsym ( b ) ;
if ( sw - > nocode_wanted )
goto skip_switch ;
if ( sw - > sv . type . t & VT_UNSIGNED )
qsort ( sw - > p , sw - > n , sizeof ( void * ) , case_cmpu ) ;
else
qsort ( sw - > p , sw - > n , sizeof ( void * ) , case_cmpi ) ;
for ( b = 1 ; b < sw - > n ; b + + )
if ( sw - > sv . type . t & VT_UNSIGNED
? ( uint64_t ) sw - > p [ b - 1 ] - > v2 > = ( uint64_t ) sw - > p [ b ] - > v1
: sw - > p [ b - 1 ] - > v2 > = sw - > p [ b ] - > v1 )
tcc_error ( " duplicate case value " ) ;
vpushv ( & sw - > sv ) ;
gv ( RC_INT ) ;
d = 0 , gcase ( sw - > p , sw - > n , & d ) ;
@ -6959,6 +6965,7 @@ again:
gsym_addr ( d , sw - > def_sym ) ;
else
gsym ( d ) ;
skip_switch :
/* break label */
gsym ( a ) ;
@ -6978,9 +6985,9 @@ again:
| | ( cur_switch - > sv . type . t & VT_UNSIGNED & & ( uint64_t ) cr - > v2 < ( uint64_t ) cr - > v1 ) )
tcc_warning ( " empty case range " ) ;
}
if ( debug_modes )
tcc_tcov_reset_ind ( tcc_state ) ;
cr - > sym = gind ( cur_switch - > nocode_wanted ) ;
/* case and default are unreachable from a switch under nocode_wanted */
if ( ! cur_switch - > nocode_wanted )
cr - > sym = gind ( ) ;
dynarray_add ( & cur_switch - > p , & cur_switch - > n , cr ) ;
skip ( ' : ' ) ;
is_expr = 0 ;
@ -6991,9 +6998,7 @@ again:
expect ( " switch " ) ;
if ( cur_switch - > def_sym )
tcc_error ( " too many 'default' " ) ;
if ( debug_modes )
tcc_tcov_reset_ind ( tcc_state ) ;
cur_switch - > def_sym = gind ( cur_switch - > nocode_wanted ) ;
cur_switch - > def_sym = cur_switch - > nocode_wanted ? 1 : gind ( ) ;
skip ( ' : ' ) ;
is_expr = 0 ;
goto block_after_label ;
@ -7059,7 +7064,7 @@ again:
} else {
s = label_push ( & global_label_stack , t , LABEL_DEFINED ) ;
}
s - > jnext = gind ( 0 ) ;
s - > jnext = gind ( ) ;
s - > cleanupstate = cur_scope - > cl . s ;
block_after_label :
@ -7068,6 +7073,8 @@ again:
AttributeDef ad_tmp ;
parse_attribute ( & ad_tmp ) ;
}
if ( debug_modes )
tcc_tcov_reset_ind ( tcc_state ) ;
vla_restore ( cur_scope - > vla . loc ) ;
if ( tok ! = ' } ' )
goto again ;
@ -7107,9 +7114,16 @@ static void skip_or_save_block(TokenString **str)
if ( str )
* str = tok_str_alloc ( ) ;
while ( ( level > 0 | | ( tok ! = ' } ' & & tok ! = ' , ' & & tok ! = ' ; ' & & tok ! = ' ) ' ) ) ) {
int t ;
if ( tok = = TOK_EOF ) {
while ( 1 ) {
int t = tok ;
if ( level = = 0
& & ( t = = ' , '
| | t = = ' ; '
| | t = = ' } '
| | t = = ' ) '
| | t = = ' ] ' ) )
break ;
if ( t = = TOK_EOF ) {
if ( str | | level > 0 )
tcc_error ( " unexpected end of file " ) ;
else
@ -7117,11 +7131,10 @@ static void skip_or_save_block(TokenString **str)
}
if ( str )
tok_str_add_tok ( * str ) ;
t = tok ;
next ( ) ;
if ( t = = ' { ' | | t = = ' ( ' ) {
if ( t = = ' { ' | | t = = ' ( ' | | t = = ' [ ' ) {
level + + ;
} else if ( t = = ' } ' | | t = = ' ) ' ) {
} else if ( t = = ' } ' | | t = = ' ) ' | | t = = ' ] ' ) {
level - - ;
if ( level = = 0 & & braces & & t = = ' } ' )
break ;
@ -7798,7 +7811,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
/* Always allocate static or global variables */
if ( v & & ( r & VT_VALMASK ) = = VT_CONST )
nocode_wanted | = 0x80000000 ;
nocode_wanted | = DATA_ONLY_WANTED ;
flexible_array = NULL ;
size = type_size ( type , & align ) ;
@ -8136,7 +8149,7 @@ static void gen_function(Sym *sym)
func_var = 0 ; /* for safety */
ind = 0 ; /* for safety */
func_ind = - 1 ;
nocode_wanted = 0x80000000 ;
nocode_wanted = DATA_ONLY_WANTED ;
check_vstack ( ) ;
/* do this after funcend debug info */
next ( ) ;