X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCC.y;h=c986486087d90b7750307d6c5c1dbb1154c41bec;hb=1f6bc72d8c57790f692bbc3ffa9451993e6a51c5;hp=44b19d5ffcbef959e58258443429802acb9fe562;hpb=217472c41ba2d2400067b42dac22d2efee618d3d;p=fw%2Fsdcc diff --git a/src/SDCC.y b/src/SDCC.y index 44b19d5f..c9864860 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -31,10 +31,12 @@ #include "SDCCval.h" #include "SDCCmem.h" #include "SDCCast.h" +#include "port.h" +#include "newalloc.h" +#include "SDCCerr.h" extern int yyerror (char *); extern FILE *yyin; -extern char srcLstFname[]; int NestLevel = 0 ; /* current NestLevel */ int stackPtr = 1 ; /* stack pointer */ int xstackPtr = 0 ; /* xstack pointer */ @@ -56,15 +58,17 @@ STACK_DCL(blockNum,int,MAX_NEST_LEVEL*3) value *cenum = NULL ; /* current enumeration type chain*/ %} +%expect 6 + %union { symbol *sym ; /* symbol table pointer */ structdef *sdef; /* structure definition */ char yychar[SDCC_NAME_MAX+1]; - link *lnk ; /* declarator or specifier */ + sym_link *lnk ; /* declarator or specifier */ int yyint; /* integer value returned */ value *val ; /* for integer constant */ initList *ilist; /* initial list */ - char yyinline[MAX_INLINEASM]; /* inlined assembler code */ + char *yyinline; /* inlined assembler code */ ast *asts; /* expression tree */ } @@ -79,13 +83,14 @@ value *cenum = NULL ; /* current enumeration type chain*/ %token TYPEDEF EXTERN STATIC AUTO REGISTER CODE EEPROM INTERRUPT SFR AT SBIT %token REENTRANT USING XDATA DATA IDATA PDATA VAR_ARGS CRITICAL NONBANKED BANKED %token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID BIT -%token STRUCT UNION ENUM ELIPSIS RANGE FAR _XDATA _CODE _GENERIC _NEAR _PDATA _IDATA _EEPROM -%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN +%token STRUCT UNION ENUM ELIPSIS RANGE FAR +%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN +%token NAKED %token INLINEASM %token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL ENDFUNCTION JUMPTABLE %token RRC RLC -%token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND +%token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT %type Interrupt_storage %type identifier declarator declarator2 enumerator_list enumerator @@ -98,7 +103,7 @@ value *cenum = NULL ; /* current enumeration type chain*/ %type storage_class_specifier struct_or_union_specifier %type declaration_specifiers sfr_reg_bit type_specifier2 %type using_reentrant using_reentrant_interrupt enum_specifier -%type abstract_declarator abstract_declarator2 far_near_pointer far_near +%type abstract_declarator abstract_declarator2 unqualified_pointer %type parameter_type_list parameter_list parameter_declaration opt_assign_expr %type stag opt_stag %type primary_expr @@ -125,6 +130,23 @@ file external_definition : function_definition { blockNo=0;} | declaration { + if ($1 && $1->type + && IS_FUNC($1->type)) + { + /* The only legal storage classes for + * a function prototype (declaration) + * are extern and static. extern is the + * default. Thus, if this function isn't + * explicitly marked static, mark it + * extern. + */ + if ($1->etype + && IS_SPEC($1->etype) + && !SPEC_STAT($1->etype)) + { + SPEC_EXTR($1->etype) = 1; + } + } addSymChain ($1); allocVariables ($1) ; cleanUpLevel (SymbolTab,1); @@ -147,7 +169,7 @@ function_definition using_reentrant : using_reentrant_interrupt - | using_reentrant_interrupt using_reentrant { $$ = mergeSpec($1,$2); } + | using_reentrant_interrupt using_reentrant { $$ = mergeSpec($1,$2,"using_reentrant"); } ; using_reentrant_interrupt @@ -165,6 +187,10 @@ using_reentrant_interrupt $$->class = SPECIFIER ; SPEC_CRTCL($$) = 1; } + | NAKED { $$ = newLink (); + $$->class = SPECIFIER ; + SPEC_NAKED($$) = 1; + } | NONBANKED {$$ = newLink (); $$->class = SPECIFIER ; SPEC_NONBANKED($$) = 1; @@ -201,14 +227,14 @@ function_body ; primary_expr - : identifier { $$ = newAst(EX_VALUE,symbolVal($1)); } - | CONSTANT { $$ = newAst(EX_VALUE,$1); } + : identifier { $$ = newAst_VALUE(symbolVal($1)); } + | CONSTANT { $$ = newAst_VALUE($1); } | string_literal | '(' expr ')' { $$ = $2 ; } ; string_literal - : STRING_LITERAL { $$ = newAst(EX_VALUE,$1); } + : STRING_LITERAL { $$ = newAst_VALUE($1); } ; postfix_expr @@ -224,14 +250,14 @@ postfix_expr { $3 = newSymbol($3->name,NestLevel); $3->implicit = 1; - $$ = newNode(PTR_OP,newNode('&',$1,NULL),newAst(EX_VALUE,symbolVal($3))); + $$ = newNode(PTR_OP,newNode('&',$1,NULL),newAst_VALUE(symbolVal($3))); /* $$ = newNode('.',$1,newAst(EX_VALUE,symbolVal($3))) ; */ } | postfix_expr PTR_OP identifier { $3 = newSymbol($3->name,NestLevel); $3->implicit = 1; - $$ = newNode(PTR_OP,$1,newAst(EX_VALUE,symbolVal($3))); + $$ = newNode(PTR_OP,$1,newAst_VALUE(symbolVal($3))); } | postfix_expr INC_OP { $$ = newNode(INC_OP,$1,NULL);} @@ -250,7 +276,7 @@ unary_expr | DEC_OP unary_expr { $$ = newNode(DEC_OP,NULL,$2); } | unary_operator cast_expr { $$ = newNode($1,$2,NULL) ; } | SIZEOF unary_expr { $$ = newNode(SIZEOF,NULL,$2); } - | SIZEOF '(' type_name ')' { $$ = newAst(EX_VALUE,sizeofOp($3)); } + | SIZEOF '(' type_name ')' { $$ = newAst_VALUE(sizeofOp($3)); } ; unary_operator @@ -264,7 +290,7 @@ unary_operator cast_expr : unary_expr - | '(' type_name ')' cast_expr { $$ = newNode(CAST,newAst(EX_LINK,$2),$4); } + | '(' type_name ')' cast_expr { $$ = newNode(CAST,newAst_LINK($2),$4); } ; multiplicative_expr @@ -288,41 +314,40 @@ shift_expr relational_expr : shift_expr - | relational_expr '<' shift_expr { $$ = newNode('<',$1,$3); } - | relational_expr '>' shift_expr { $$ = newNode('>',$1,$3); } + | relational_expr '<' shift_expr { + $$ = (port->lt_nge ? + newNode('!',newNode(GE_OP,$1,$3),NULL) : + newNode('<', $1,$3)); + } + | relational_expr '>' shift_expr { + $$ = (port->gt_nle ? + newNode('!',newNode(LE_OP,$1,$3),NULL) : + newNode('>',$1,$3)); + } | relational_expr LE_OP shift_expr { - /* $$ = newNode(LE_OP,$1,$3); */ - /* getting 8051 specific here : will change - LE_OP operation to "not greater than" i.e. - ( a <= b ) === ( ! ( a > b )) */ - $$ = newNode('!', - newNode('>', $1 , $3 ), - NULL); + $$ = (port->le_ngt ? + newNode('!', newNode('>', $1 , $3 ), NULL) : + newNode(LE_OP,$1,$3)); } | relational_expr GE_OP shift_expr { - /* $$ = newNode(GE_OP,$1,$3) ; */ - /* getting 8051 specific here : will change - GE_OP operation to "not less than" i.e. - ( a >= b ) === ( ! ( a < b )) */ - $$ = newNode('!', - newNode('<', $1 , $3 ), - NULL); + $$ = (port->ge_nlt ? + newNode('!', newNode('<', $1 , $3 ), NULL) : + newNode(GE_OP,$1,$3)); } ; equality_expr : relational_expr - | equality_expr EQ_OP relational_expr { $$ = newNode(EQ_OP,$1,$3);} - | equality_expr NE_OP relational_expr - { - /* $$ = newNode(NE_OP,$1,$3); */ - /* NE_OP changed : - expr1 != expr2 is equivalent to - (! expr1 == expr2) */ - $$ = newNode('!', - newNode(EQ_OP,$1,$3), - NULL); - } + | equality_expr EQ_OP relational_expr { + $$ = (port->eq_nne ? + newNode('!',newNode(NE_OP,$1,$3),NULL) : + newNode(EQ_OP,$1,$3)); + } + | equality_expr NE_OP relational_expr { + $$ = (port->ne_neq ? + newNode('!', newNode(EQ_OP,$1,$3), NULL) : + newNode(NE_OP,$1,$3)); + } ; and_expr @@ -438,7 +463,7 @@ declaration symbol *sym , *sym1; for (sym1 = sym = reverseSyms($2);sym != NULL;sym = sym->next) { - link *lnk = copyLinkChain($1); + sym_link *lnk = copyLinkChain($1); /* do the pointer stuff */ pointerTypes(sym->type,lnk); addDecl (sym,0,lnk) ; @@ -454,28 +479,28 @@ declaration_specifiers /* if the decl $2 is not a specifier */ /* find the spec and replace it */ if ( !IS_SPEC($2)) { - link *lnk = $2 ; + sym_link *lnk = $2 ; while (lnk && !IS_SPEC(lnk->next)) lnk = lnk->next; - lnk->next = mergeSpec($1,lnk->next); + lnk->next = mergeSpec($1,lnk->next, yytext); $$ = $2 ; } else - $$ = mergeSpec($1,$2); + $$ = mergeSpec($1,$2, yytext); } | type_specifier { $$ = $1; } | type_specifier declaration_specifiers { /* if the decl $2 is not a specifier */ /* find the spec and replace it */ if ( !IS_SPEC($2)) { - link *lnk = $2 ; + sym_link *lnk = $2 ; while (lnk && !IS_SPEC(lnk->next)) lnk = lnk->next; - lnk->next = mergeSpec($1,lnk->next); + lnk->next = mergeSpec($1,lnk->next, yytext); $$ = $2 ; } else - $$ = mergeSpec($1,$2); + $$ = mergeSpec($1,$2, yytext); } ; @@ -524,12 +549,12 @@ Interrupt_storage type_specifier : type_specifier2 - | type_specifier2 AT CONSTANT + | type_specifier2 AT constant_expr { /* add this to the storage class specifier */ SPEC_ABSA($1) = 1; /* set the absolute addr flag */ /* now get the abs addr from value */ - SPEC_ADDR($1) = (int) floatFromVal ($3) ; + SPEC_ADDR($1) = (int) floatFromVal(constExprValue($3,TRUE)) ; } ; @@ -542,8 +567,7 @@ type_specifier2 | SHORT { $$=newLink(); $$->class = SPECIFIER ; - SPEC_LONG($$) = 0 ; - SPEC_SHORT($$) = 1 ; + $$->select.s._short = 1 ; } | INT { $$=newLink(); @@ -553,18 +577,17 @@ type_specifier2 | LONG { $$=newLink(); $$->class = SPECIFIER ; - SPEC_LONG($$) = 1 ; - SPEC_SHORT($$) = 0; + SPEC_LONG($$) = 1 ; } | SIGNED { $$=newLink(); $$->class = SPECIFIER ; - SPEC_USIGN($$) = 0 ; + $$->select.s._signed = 1; } | UNSIGNED { $$=newLink(); $$->class = SPECIFIER ; - SPEC_USIGN($$) = 1 ; + SPEC_USIGN($$) = 1 ; } | VOID { $$=newLink(); @@ -574,7 +597,6 @@ type_specifier2 | CONST { $$=newLink(); $$->class = SPECIFIER ; - SPEC_SCLS($$) = S_CONSTANT ; SPEC_CONST($$) = 1; } | VOLATILE { @@ -634,8 +656,7 @@ type_specifier2 | TYPE_NAME { symbol *sym; - link *p ; - + sym_link *p ; sym = findSym(TypedefTab,NULL,$1) ; $$ = p = copyLinkChain(sym->type); SPEC_TYPEDEF(getSpec(p)) = 0; @@ -690,24 +711,23 @@ struct_or_union ; opt_stag - : stag - | { /* synthesize a name add to structtable */ - $$ = newStruct(genSymName(NestLevel)) ; - $$->level = NestLevel ; - addSym (StructTab, $$, $$->tag,$$->level,currBlockno) ; - } - ; +: stag +| { /* synthesize a name add to structtable */ + $$ = newStruct(genSymName(NestLevel)) ; + $$->level = NestLevel ; + addSym (StructTab, $$, $$->tag,$$->level,currBlockno, 0); +}; stag - : identifier { /* add name to structure table */ - $$ = findSymWithBlock (StructTab,$1,currBlockno); - if (! $$ ) { - $$ = newStruct($1->name) ; - $$->level = NestLevel ; - addSym (StructTab, $$, $$->tag,$$->level,currBlockno) ; - } - } - ; +: identifier { /* add name to structure table */ + $$ = findSymWithBlock (StructTab,$1,currBlockno); + if (! $$ ) { + $$ = newStruct($1->name) ; + $$->level = NestLevel ; + addSym (StructTab, $$, $$->tag,$$->level,currBlockno,0); + } +}; + struct_declaration_list : struct_declaration @@ -729,14 +749,18 @@ struct_declaration symbol *sym ; for ( sym = $2 ; sym != NULL ; sym = sym->next ) { + /* make the symbol one level up */ + sym->level-- ; + pointerTypes(sym->type,copyLinkChain($1)); if (!sym->type) { sym->type = copyLinkChain($1); sym->etype = getSpec(sym->type); + /* make sure the type is complete and sane */ + checkTypeSanity(sym->etype, sym->name); } else addDecl (sym,0,cloneSpec($1)); - } $$ = $2; } @@ -779,7 +803,7 @@ enum_specifier (csym && csym->level == $2->level)) werror(E_DUPLICATE_TYPEDEF,csym->name); - addSym ( enumTab,$2,$2->name,$2->level,$2->block); + addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0); addSymChain ($4); allocVariables (reverseSyms($4)); $$ = copyLinkChain(cenum->type); @@ -803,6 +827,8 @@ enum_specifier enumerator_list : enumerator + | enumerator_list ',' { + } | enumerator_list ',' enumerator { $3->next = $1 ; $$ = $3 ; @@ -859,7 +885,7 @@ declarator2 | '(' declarator ')' { $$ = $2; } | declarator2 '[' ']' { - link *p; + sym_link *p; p = newLink (); DCL_TYPE(p) = ARRAY ; @@ -868,7 +894,7 @@ declarator2 } | declarator2 '[' constant_expr ']' { - link *p ; + sym_link *p ; value *tval; p = (tval = constExprValue($3,TRUE))->etype; @@ -900,25 +926,25 @@ declarator2 { werror(E_OLD_STYLE,$1->name) ; - /* assume it returns an it */ + /* assume it returns an int */ $1->type = $1->etype = newIntLink(); $$ = $1 ; } ; pointer - : far_near_pointer { $$ = $1 ;} - | far_near_pointer type_specifier_list + : unqualified_pointer { $$ = $1 ;} + | unqualified_pointer type_specifier_list { $$ = $1 ; DCL_TSPEC($1) = $2; } - | far_near_pointer pointer + | unqualified_pointer pointer { $$ = $1 ; $$->next = $2 ; } - | far_near_pointer type_specifier_list pointer + | unqualified_pointer type_specifier_list pointer { $$ = $1 ; if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) { @@ -940,6 +966,7 @@ pointer case S_CODE: DCL_PTR_CONST($3) = 1; DCL_TYPE($3) = CPOINTER ; + break; case S_EEPROM: DCL_TYPE($3) = EEPPOINTER; break; @@ -953,31 +980,17 @@ pointer } ; -far_near_pointer - : far_near '*' { - if ($1 == NULL) { - $$ = newLink(); - DCL_TYPE($$) = POINTER ; - } - else - $$ = $1 ; +unqualified_pointer + : '*' + { + $$ = newLink(); + DCL_TYPE($$)=UPOINTER; } ; -far_near - : _XDATA { $$ = newLink() ; DCL_TYPE($$) = FPOINTER ; } - | _CODE { $$ = newLink() ; DCL_TYPE($$) = CPOINTER ; DCL_PTR_CONST($$) = 1;} - | _PDATA { $$ = newLink() ; DCL_TYPE($$) = PPOINTER ; } - | _IDATA { $$ = newLink() ; DCL_TYPE($$) = IPOINTER ; } - | _NEAR { $$ = NULL ; } - | _GENERIC { $$ = newLink() ; DCL_TYPE($$) = GPOINTER ; } - | _EEPROM { $$ = newLink() ; DCL_TYPE($$) = EEPPOINTER ;} - | { $$ = newLink() ; DCL_TYPE($$) = UPOINTER ; } - ; - type_specifier_list : type_specifier - | type_specifier_list type_specifier { $$ = mergeSpec ($1,$2); } + | type_specifier_list type_specifier { $$ = mergeSpec ($1,$2, "type_specifier_list"); } ; parameter_identifier_list @@ -1030,7 +1043,7 @@ type_name | type_specifier_list abstract_declarator { /* go to the end of the list */ - link *p; + sym_link *p; pointerTypes($2,$1); for ( p = $2 ; p->next ; p=p->next); p->next = $1 ; @@ -1073,9 +1086,23 @@ abstract_declarator2 } | '(' ')' { $$ = NULL;} | '(' parameter_type_list ')' { $$ = NULL;} - | abstract_declarator2 '(' ')' - | abstract_declarator2 '(' parameter_type_list ')' - ; + | abstract_declarator2 '(' ')' { + // $1 must be a pointer to a function + sym_link *p=newLink(); + DCL_TYPE(p) = FUNCTION; + $1->next=p; + } + | abstract_declarator2 '(' parameter_type_list ')' { + if (!IS_VOID($3->type)) { + // this is nonsense, so let's just burp something + werror(E_TOO_FEW_PARMS); + } else { + // $1 must be a pointer to a function + sym_link *p=newLink(); + DCL_TYPE(p) = FUNCTION; + $1->next=p; + } + } initializer : assignment_expr { $$ = newiList(INIT_NODE,$1); } @@ -1097,7 +1124,7 @@ statement | jump_statement | INLINEASM ';' { ast *ex = newNode(INLINEASM,NULL,NULL); - ALLOC_ATOMIC(ex->values.inlineasm,strlen($1)); + ex->values.inlineasm = Safe_calloc(1,strlen($1)+1); strcpy(ex->values.inlineasm,$1); $$ = ex; } @@ -1299,7 +1326,7 @@ expr_opt jump_statement : GOTO identifier ';' { $2->islbl = 1; - $$ = newAst(EX_VALUE,symbolVal($2)); + $$ = newAst_VALUE(symbolVal($2)); $$ = newNode(GOTO,$$,NULL); } | CONTINUE ';' { @@ -1309,7 +1336,7 @@ jump_statement $$ = NULL; } else { - $$ = newAst(EX_VALUE,symbolVal(STACK_PEEK(continueStack))); + $$ = newAst_VALUE(symbolVal(STACK_PEEK(continueStack))); $$ = newNode(GOTO,$$,NULL); /* mark the continue label as referenced */ STACK_PEEK(continueStack)->isref = 1; @@ -1320,7 +1347,7 @@ jump_statement werror(E_BREAK_CONTEXT); $$ = NULL; } else { - $$ = newAst(EX_VALUE,symbolVal(STACK_PEEK(breakStack))); + $$ = newAst_VALUE(symbolVal(STACK_PEEK(breakStack))); $$ = newNode(GOTO,$$,NULL); STACK_PEEK(breakStack)->isref = 1; }