X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCsymt.c;h=e86314e249c577ce9def84216ca7f2ffca63735c;hb=90bdb43b342189fcb94a398855d43f3f47f96738;hp=c1bdae25ea296d09230145938c6e19770ee8b39a;hpb=edae25c7ae2b0749ca7d491b391b99967652a0fd;p=fw%2Fsdcc diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index c1bdae25..e86314e2 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -796,7 +796,7 @@ newBoolLink () } /*------------------------------------------------------------------*/ -/* getSize - returns size of a type chain in bits */ +/* getSize - returns size of a type chain in bytes */ /*------------------------------------------------------------------*/ unsigned int getSize (sym_link * p) @@ -860,29 +860,41 @@ getSize (sym_link * p) } } -/*---------------------------------------------------------------------*/ -/* getAllocSize - returns size of a type chain in bytes for allocation */ -/*---------------------------------------------------------------------*/ -unsigned int -getAllocSize (sym_link *p) +/*------------------------------------------------------------------*/ +/* checkStructFlexArray - check tree behind a struct */ +/*------------------------------------------------------------------*/ +static bool +checkStructFlexArray (symbol *sym, sym_link *p) { - if (IS_STRUCT (p) && SPEC_STRUCT (p)->type == STRUCT) - { - /* if this is a struct specifier then */ - /* calculate the size as it could end */ - /* with an array of unspecified length */ - symbol *sflds = SPEC_STRUCT (p)->fields; + /* if nothing return FALSE */ + if (!p) + return FALSE; - while (sflds && sflds->next) - sflds = sflds->next; + if (IS_SPEC (p)) + { + /* (nested) struct with flexible array member? */ + if (IS_STRUCT (p) && SPEC_STRUCT (p)->b_flexArrayMember) + { + werror (W_INVALID_FLEXARRAY); + return FALSE; + } + return FALSE; + } - if (sflds && !IS_BITFIELD (sflds->type)) - return sflds->offset + getAllocSize (sflds->type); - else - return SPEC_STRUCT (p)->size; + /* this is a declarator */ + if (IS_ARRAY (p)) + { + /* flexible array member? */ + if (!DCL_ELEM(p)) + { + if (!options.std_c99) + werror (W_C89_NO_FLEXARRAY); + return TRUE; + } + /* walk tree */ + return checkStructFlexArray (sym, p->next); } - else - return getSize (p); + return FALSE; } /*------------------------------------------------------------------*/ @@ -1233,7 +1245,11 @@ compStructSize (int su, structdef * sdef) /* change it to a unsigned bit */ SPEC_NOUN (loop->etype) = V_BITFIELD; - SPEC_USIGN (loop->etype) = 1; + /* ISO/IEC 9899 J.3.9 implementation defined behaviour: */ + /* a "plain" int bitfield is unsigned */ + if (!loop->etype->select.s.b_signed) + SPEC_USIGN(loop->etype) = 1; + SPEC_BLEN (loop->etype) = loop->bitVar; if (loop->bitVar == BITVAR_PAD) { @@ -1264,12 +1280,24 @@ compStructSize (int su, structdef * sdef) bitOffset += loop->bitVar; } else { - /* does not fit; need to realign first */ - sum++; - loop->offset = (su == UNION ? sum = 0 : sum); - bitOffset = 0; - SPEC_BSTR (loop->etype) = bitOffset; - bitOffset += loop->bitVar; + if( TARGET_IS_PIC16 && getenv("PIC16_PACKED_BITFIELDS") ) { + /* if PIC16 && enviroment variable is set, then + * tightly pack bitfields, this means that when a + * bitfield goes beyond byte alignment, do not + * automatically start allocatint from next byte, + * but also use the available bits first */ + fprintf(stderr, ": packing bitfields in structures\n"); + SPEC_BSTR (loop->etype) = bitOffset; + bitOffset += loop->bitVar; + loop->offset = (su == UNION ? sum = 0 : sum); + } else { + /* does not fit; need to realign first */ + sum++; + loop->offset = (su == UNION ? sum = 0 : sum); + bitOffset = 0; + SPEC_BSTR (loop->etype) = bitOffset; + bitOffset += loop->bitVar; + } } while (bitOffset>8) { bitOffset -= 8; @@ -1288,6 +1316,21 @@ compStructSize (int su, structdef * sdef) loop->offset = sum; checkDecl (loop, 1); sum += getSize (loop->type); + + /* search for "flexibel array members" */ + /* and do some syntax checks */ + if ( su == STRUCT + && checkStructFlexArray (loop, loop->type)) + { + /* found a "flexible array member" */ + sdef->b_flexArrayMember = TRUE; + /* is another struct-member following? */ + if (loop->next) + werror (E_FLEXARRAY_NOTATEND); + /* is it the first struct-member? */ + else if (loop == sdef->fields) + werror (E_FLEXARRAY_INEMPTYSTRCT); + } } loop = loop->next; @@ -1385,8 +1428,7 @@ checkSClass (symbol * sym, int isProto) fprintf (stderr, "checkSClass: %s \n", sym->name); } - /* type is literal can happen for enums change - to auto */ + /* type is literal can happen for enums change to auto */ if (SPEC_SCLS (sym->etype) == S_LITERAL && !SPEC_ENUM (sym->etype)) SPEC_SCLS (sym->etype) = S_AUTO; @@ -1521,6 +1563,7 @@ checkSClass (symbol * sym, int isProto) /* arrays & pointers cannot be defined for bits */ /* SBITS or SFRs or BIT */ if ((IS_ARRAY (sym->type) || IS_PTR (sym->type)) && + !IS_FUNCPTR (sym->type) && (SPEC_NOUN (sym->etype) == V_BIT || SPEC_NOUN (sym->etype) == V_SBIT || SPEC_NOUN (sym->etype) == V_BITFIELD || @@ -1620,6 +1663,7 @@ copyLinkChain (sym_link * p) { sym_link *head, *curr, *loop; + /* note: v_struct and v_struct->fields are not copied! */ curr = p; head = loop = (curr ? newLink (p->class) : (void *) NULL); while (curr) @@ -1767,24 +1811,20 @@ computeType (sym_link * type1, sym_link * type2, /* which ever is greater in size */ if (IS_FLOAT (etype1) || IS_FLOAT (etype2)) rType = newFloatLink (); - else - /* if both are fixed16x16 then result is float */ - if (IS_FIXED16X16(etype1) && IS_FIXED16X16(etype2)) + /* if both are fixed16x16 then result is float */ + else if (IS_FIXED16X16(etype1) && IS_FIXED16X16(etype2)) rType = newFixed16x16Link(); - else - if (IS_FIXED16X16(etype1) && IS_FLOAT (etype2)) + else if (IS_FIXED16X16(etype1) && IS_FLOAT (etype2)) rType = newFloatLink (); - if (IS_FLOAT (etype1) && IS_FIXED16X16 (etype2) ) + else if (IS_FLOAT (etype1) && IS_FIXED16X16 (etype2) ) rType = newFloatLink (); - else - /* if both are bitvars choose the larger one */ - if (IS_BITVAR (etype1) && IS_BITVAR (etype2)) - { - rType = SPEC_BLEN (etype1) >= SPEC_BLEN (etype2) ? - copyLinkChain (type1) : copyLinkChain (type1); - } - /* if only one of them is a bit variable - then the other one prevails */ + + /* if both are bitvars choose the larger one */ + else if (IS_BITVAR (etype1) && IS_BITVAR (etype2)) + rType = SPEC_BLEN (etype1) >= SPEC_BLEN (etype2) ? + copyLinkChain (type1) : copyLinkChain (type1); + + /* if only one of them is a bit variable then the other one prevails */ else if (IS_BITVAR (etype1) && !IS_BITVAR (etype2)) { rType = copyLinkChain (type2); @@ -1799,10 +1839,9 @@ computeType (sym_link * type1, sym_link * type2, if (getSize (etype2) > 1) SPEC_NOUN (getSpec (rType)) = V_INT; } - else - /* if one of them is a pointer or array then that - prevails */ - if (IS_PTR (type1) || IS_ARRAY (type1)) + /* if one of them is a pointer or array then that + prevails */ + else if (IS_PTR (type1) || IS_ARRAY (type1)) rType = copyLinkChain (type1); else if (IS_PTR (type2) || IS_ARRAY (type2)) rType = copyLinkChain (type2); @@ -1852,28 +1891,34 @@ computeType (sym_link * type1, sym_link * type2, } else if (IS_CHAR (reType)) { - if (op == '|' || op == '^') - return computeTypeOr (etype1, etype2, reType); - else if ( op == '&' - && SPEC_USIGN (etype1) != SPEC_USIGN (etype2)) - { - SPEC_USIGN (reType) = 1; - return rType; - } - else if (op == '*') - { - SPEC_NOUN (reType) = V_INT; - SPEC_USIGN (reType) = 0; - return rType; - } - /* TODO: should be in SDCCast.c */ - else if ( op == '/' - && ( !SPEC_USIGN (etype1) - || !SPEC_USIGN (etype2))) + /* promotion of some special cases */ + switch (op) { - SPEC_NOUN (reType) = V_INT; - SPEC_USIGN (reType) = 0; - return rType; + case '|': + case '^': + return computeTypeOr (etype1, etype2, reType); + case '&': + if (SPEC_USIGN (etype1) != SPEC_USIGN (etype2)) + { + SPEC_USIGN (reType) = 1; + return rType; + } + break; + case '*': + SPEC_NOUN (reType) = V_INT; + SPEC_USIGN (reType) = 0; + return rType; + case '/': + /* if both are unsigned char then no promotion required */ + if (!(SPEC_USIGN (etype1) && SPEC_USIGN (etype2))) + { + SPEC_NOUN (reType) = V_INT; + SPEC_USIGN (reType) = 0; + return rType; + } + break; + default: + break; } } break; @@ -1920,12 +1965,12 @@ computeType (sym_link * type1, sym_link * type2, && ( (SPEC_USIGN (etype1) /* if this operand is promoted to a larger type, then it will be promoted to a signed type */ - && !(getSize (etype1) < getSize (reType)) + && !(bitsForType (etype1) < bitsForType (reType)) /* char require special handling */ && !IS_CHAR (etype1)) || /* same for 2nd operand */ (SPEC_USIGN (etype2) - && !(getSize (etype2) < getSize (reType)) + && !(bitsForType (etype2) < bitsForType (reType)) && !IS_CHAR (etype2)) || /* if both are 'unsigned char' and not promoted let the result be unsigned too */ @@ -2534,6 +2579,22 @@ void cdbStructBlock (int block) } } +/*-----------------------------------------------------------------*/ +/* processFuncPtrArgs - does some processing with args of func ptrs*/ +/*-----------------------------------------------------------------*/ +void +processFuncPtrArgs (sym_link * funcType) +{ + value *val = FUNC_ARGS(funcType); + + /* if it is void then remove parameters */ + if (val && IS_VOID (val->type)) + { + FUNC_ARGS(funcType) = NULL; + return; + } +} + /*-----------------------------------------------------------------*/ /* processFuncArgs - does some processing with function args */ /*-----------------------------------------------------------------*/ @@ -2587,7 +2648,7 @@ processFuncArgs (symbol * func) the function does not have VA_ARG and as port dictates */ if (!IFFUNC_HASVARARGS(funcType) && - (argreg = (*port->reg_parm) (val->type))) + (argreg = (*port->reg_parm) (val->type, FUNC_ISREENT(funcType)))) { SPEC_REGPARM (val->etype) = 1; SPEC_ARGREG(val->etype) = argreg; @@ -2658,7 +2719,7 @@ processFuncArgs (symbol * func) SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) = bit; else SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) = - (options.model != MODEL_SMALL ? xdata : data); + port->mem.default_local_map; #if 0 /* ?? static functions shouldn't imply static parameters - EEP */ @@ -2668,6 +2729,8 @@ processFuncArgs (symbol * func) } #endif } + if (SPEC_OCLS (val->sym->etype) == pdata) + val->sym->iaccess = 1; if (!isinSet(operKeyReset, val->sym)) { addSet (&operKeyReset, val->sym); applyToSet (operKeyReset, resetParmKey); @@ -3062,7 +3125,7 @@ printTypeChainRaw (sym_link * start, FILE * of) /* powof2 - returns power of two for the number if number is pow 2 */ /*-----------------------------------------------------------------*/ int -powof2 (TYPE_UDWORD num) +powof2 (TYPE_TARGET_ULONG num) { int nshifts = 0; int n1s = 0; @@ -3076,7 +3139,7 @@ powof2 (TYPE_UDWORD num) } if (n1s > 1 || nshifts == 0) - return 0; + return -1; return nshifts - 1; } @@ -3393,17 +3456,50 @@ initCSupport () { for (muldivmod = 1; muldivmod < 3; muldivmod++) { - /* div and mod */ - SNPRINTF (buffer, sizeof(buffer), - "_%s%s%s", - smuldivmod[muldivmod], - ssu[su], - sbwd[bwd]); - __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent); - FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1; + /* div and mod : s8_t x s8_t -> s8_t should be s8_t x s8_t -> s16_t, see below */ + if (!TARGET_IS_PIC16 || muldivmod != 1 || bwd != 0 || su != 0) + { + SNPRINTF (buffer, sizeof(buffer), + "_%s%s%s", + smuldivmod[muldivmod], + ssu[su], + sbwd[bwd]); + __muldiv[muldivmod][bwd][su] = funcOfType ( + _mangleFunctionName(buffer), + __multypes[bwd][su], + __multypes[bwd][su], + 2, + options.intlong_rent); + FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1; + } } } } + + if (TARGET_IS_PIC16) + { + /* PIC16 port wants __divschar/__modschar to return an int, so that both + * 100 / -4 = -25 and -128 / -1 = 128 can be handled correctly + * (first one would have to be sign extended, second one must not be). + * Similarly, modschar should be handled, but the iCode introduces cast + * here and forces '% : s8 x s8 -> s8' ... */ + su = 0; bwd = 0; + for (muldivmod = 1; muldivmod < 2; muldivmod++) { + SNPRINTF (buffer, sizeof(buffer), + "_%s%s%s", + smuldivmod[muldivmod], + ssu[su], + sbwd[bwd]); + __muldiv[muldivmod][bwd][su] = funcOfType ( + _mangleFunctionName(buffer), + __multypes[1][su], + __multypes[bwd][su], + 2, + options.intlong_rent); + FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1; + } + } + /* mul only */ muldivmod = 0; /* byte */ @@ -3488,7 +3584,7 @@ sym_link *validateLink(sym_link *l, " expected %s, got %s\n", macro, args, file, line, DECLSPEC2TXT(select), l ? DECLSPEC2TXT(l->class) : "null-link"); - exit(-1); + exit(EXIT_FAILURE); return l; // never reached, makes compiler happy. }