From 67613b6eceb41c8a242c2556a0f59311adb0b388 Mon Sep 17 00:00:00 2001 From: bernhardheld Date: Sat, 6 Mar 2004 11:44:05 +0000 Subject: [PATCH] * sim/ucsim/configure.in, * sim/ucsim/configure, * sim/ucsim/Makefile.in: use docdir * src/SDCC.y: fixed sbit atrributes * src/SDCCast.c (getResultTypeFromType): added support for bitfields * src/SDCCast.c (decorateType): |^& need special promotion handling * src/SDCCast.h, * src/SDCCsymt.h: moved definition of RESULT_TYPE * src/SDCCsymt.h (computeType), * src/SDCCicode.c: computeType() needs op * src/SDCCsymt.c (checkTypeSanity), * doc/sddman.lyx: "plain" bitfields are unsigned * src/SDCCsymt.c (computeTypeOr): added * src/SDCCsymt.c (computeType): added support for bitfields, fixed |^& ops * src/SDCCval.c (val*): computeType() needs op * src/SDCCval.c (valCastLiteral): fixed casting of bitfields * support/regression/tests/onebyte.c: added tests for |^& git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3250 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 21 ++++ doc/sdccman.lyx | 11 +- sim/ucsim/configure | 22 +++- sim/ucsim/configure.in | 6 ++ sim/ucsim/doc/Makefile.in | 2 +- src/SDCC.y | 2 + src/SDCCast.c | 53 ++++++--- src/SDCCast.h | 11 -- src/SDCCicode.c | 102 +++++++++++------- src/SDCCsymt.c | 168 ++++++++++++++++++++++++++--- src/SDCCsymt.h | 16 ++- src/SDCCval.c | 29 +++-- support/regression/tests/onebyte.c | 48 +++++++++ 13 files changed, 397 insertions(+), 94 deletions(-) diff --git a/ChangeLog b/ChangeLog index a07891ff..d467f934 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2004-03-06 Bernhard Held + + * sim/ucsim/configure.in, + * sim/ucsim/configure, + * sim/ucsim/doc/Makefile.in: use docdir + * src/SDCC.y: fixed sbit atrributes + * src/SDCCast.c (getResultTypeFromType): added support for bitfields + * src/SDCCast.c (decorateType): |^& need special promotion handling + * src/SDCCast.h, + * src/SDCCsymt.h: moved definition of RESULT_TYPE + * src/SDCCsymt.h (computeType), + * src/SDCCicode.c: computeType() needs op + * src/SDCCsymt.c (checkTypeSanity), + * doc/sddman.lyx: "plain" bitfields are unsigned + * src/SDCCsymt.c (computeTypeOr): added + * src/SDCCsymt.c (computeType): added support for bitfields, fixed + |^& ops + * src/SDCCval.c (val*): computeType() needs op + * src/SDCCval.c (valCastLiteral): fixed casting of bitfields + * support/regression/tests/onebyte.c: added tests for |^& + 2004-03-06 Hans Dorn * src/pic16/gen.c: (genpic16Code) use copy of printILine's output diff --git a/doc/sdccman.lyx b/doc/sdccman.lyx index be855b59..8b6f8ed1 100644 --- a/doc/sdccman.lyx +++ b/doc/sdccman.lyx @@ -8275,7 +8275,16 @@ Apart from this 8051 specific storage class most architectures support ANSI-C \end_inset - + +\newline + +\layout Standard + +In accordance with ISO/IEC 9899 bits and bitfields without an explicit signed + modifier are implemented as unsigned. +\layout Standard + + \begin_inset Foot collapsed false diff --git a/sim/ucsim/configure b/sim/ucsim/configure index 6e256422..865f6db9 100755 --- a/sim/ucsim/configure +++ b/sim/ucsim/configure @@ -467,7 +467,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS AWK VERSION VERSIONHI VERSIONLO VERSIONP enable_ucsim enable_dlso enable_51 enable_avr enable_z80 enable_hc08 enable_xa enable_serio CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT CXXCPP INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA RANLIB ac_ct_RANLIB STRIP build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS ac_ct_CC LN_S ECHO ac_ct_STRIP CPP EGREP LIBTOOL LIBTOOL_DEPS dl_ok DL panel_ok curses_ok CURSES_LIBS M_OR_MM SHAREDLIB PICOPT dlso_ok LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS AWK VERSION VERSIONHI VERSIONLO VERSIONP enable_ucsim enable_dlso enable_51 enable_avr enable_z80 enable_hc08 enable_xa enable_serio CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT CXXCPP INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA RANLIB ac_ct_RANLIB STRIP build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS ac_ct_CC LN_S ECHO ac_ct_STRIP CPP EGREP LIBTOOL LIBTOOL_DEPS dl_ok DL panel_ok curses_ok CURSES_LIBS M_OR_MM SHAREDLIB PICOPT dlso_ok docdir LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -940,6 +940,10 @@ ac_env_CPP_set=${CPP+set} ac_env_CPP_value=$CPP ac_cv_env_CPP_set=${CPP+set} ac_cv_env_CPP_value=$CPP +ac_env_docdir_set=${docdir+set} +ac_env_docdir_value=$docdir +ac_cv_env_docdir_set=${docdir+set} +ac_cv_env_docdir_value=$docdir # # Report the --help message. @@ -1045,6 +1049,7 @@ Some influential environment variables: CC C compiler command CFLAGS C compiler flags CPP C preprocessor + docdir documentation installation directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -4883,7 +4888,7 @@ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes case $host in *-*-irix6*) # Find out which ABI we are using. - echo '#line 4886 "configure"' > conftest.$ac_ext + echo '#line 4891 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -5430,7 +5435,7 @@ chmod -w . save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -o out/conftest2.$ac_objext" compiler_c_o=no -if { (eval echo configure:5433: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then +if { (eval echo configure:5438: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s out/conftest.err; then @@ -7275,7 +7280,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <>confdefs.h <<_ACEOF _ACEOF +# *nix default: "${datadir}/sdcc/doc" + +if test "${docdir}" = ""; then + docdir="\${datadir}"/sdcc/doc +fi + # Generating output files # =========================================================================== @@ -13401,6 +13412,7 @@ s,@M_OR_MM@,$M_OR_MM,;t t s,@SHAREDLIB@,$SHAREDLIB,;t t s,@PICOPT@,$PICOPT,;t t s,@dlso_ok@,$dlso_ok,;t t +s,@docdir@,$docdir,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF diff --git a/sim/ucsim/configure.in b/sim/ucsim/configure.in index 9f25ae00..eb113efc 100644 --- a/sim/ucsim/configure.in +++ b/sim/ucsim/configure.in @@ -466,6 +466,12 @@ fi AC_DEFINE_UNQUOTED(_A_, "${A}") AC_DEFINE_UNQUOTED(_M_, "${M}") +# *nix default: "${datadir}/sdcc/doc" +AC_ARG_VAR(docdir, documentation installation directory) +if test "${docdir}" = ""; then + docdir="\${datadir}"/sdcc/doc +fi +AC_SUBST(docdir) # Generating output files # =========================================================================== diff --git a/sim/ucsim/doc/Makefile.in b/sim/ucsim/doc/Makefile.in index 3cabe9c9..10e628aa 100644 --- a/sim/ucsim/doc/Makefile.in +++ b/sim/ucsim/doc/Makefile.in @@ -22,7 +22,7 @@ man1dir = $(mandir)/man1 man2dir = $(mandir)/man2 infodir = @infodir@ srcdir = @srcdir@ -docdir = $(prefix)/share/sdcc/doc/ucsim +docdir = @docdir@/ucsim # Compiling entire program or any subproject diff --git a/src/SDCC.y b/src/SDCC.y index c6660523..c5944eaf 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -702,6 +702,8 @@ sfr_reg_bit $$ = newLink(SPECIFIER) ; SPEC_NOUN($$) = V_SBIT; SPEC_SCLS($$) = S_SBIT; + SPEC_BLEN($$) = 1; + SPEC_BSTR($$) = 0; ignoreTypedefType = 1; } | sfr_attributes diff --git a/src/SDCCast.c b/src/SDCCast.c index 5308992c..8e20910c 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -2019,10 +2019,18 @@ RESULT_TYPE getResultTypeFromType (sym_link *type) { /* type = getSpec (type); */ - if (IS_BITVAR (type)) + if (IS_BIT (type)) return RESULT_TYPE_BIT; if (IS_BITFIELD (type)) - return RESULT_TYPE_CHAR; + { + int blen = SPEC_BLEN (type); + + if (blen <= 1) + return RESULT_TYPE_BIT; + if (blen <= 8) + return RESULT_TYPE_CHAR; + return RESULT_TYPE_INT; + } if (IS_CHAR (type)) return RESULT_TYPE_CHAR; if ( IS_INT (type) @@ -2556,7 +2564,10 @@ decorateType (ast * tree, RESULT_TYPE resultType) tree->left = addCast (tree->left, resultType, FALSE); tree->right = addCast (tree->right, resultType, FALSE); - TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE); + TTYPE (tree) = computeType (LTYPE (tree), + RTYPE (tree), + resultType, + tree->opval.op); TETYPE (tree) = getSpec (TTYPE (tree)); /* if left is a literal exchange left & right */ @@ -2774,7 +2785,8 @@ decorateType (ast * tree, RESULT_TYPE resultType) TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), - FALSE)); + resultType, + tree->opval.op)); return tree; @@ -2806,7 +2818,8 @@ decorateType (ast * tree, RESULT_TYPE resultType) TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), - resultType == RESULT_TYPE_CHAR ? FALSE : TRUE)); + resultType, + tree->opval.op)); /* if right is a literal and */ /* left is also a division by a literal then */ @@ -2872,7 +2885,8 @@ decorateType (ast * tree, RESULT_TYPE resultType) TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), - resultType == RESULT_TYPE_CHAR ? FALSE : TRUE)); + resultType, + tree->opval.op)); return tree; /*------------------------------------------------------------------*/ @@ -2987,7 +3001,8 @@ decorateType (ast * tree, RESULT_TYPE resultType) TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), - resultType == RESULT_TYPE_CHAR ? FALSE : TRUE)); + resultType, + tree->opval.op)); return tree; @@ -3121,8 +3136,9 @@ decorateType (ast * tree, RESULT_TYPE resultType) tree->right = addCast (tree->right, resultType, TRUE); TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), - RTYPE (tree), - resultType == RESULT_TYPE_CHAR ? FALSE : TRUE)); + RTYPE (tree), + resultType, + tree->opval.op)); } return tree; @@ -3226,8 +3242,9 @@ decorateType (ast * tree, RESULT_TYPE resultType) tree->right = addCast (tree->right, resultType, TRUE); TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), - RTYPE (tree), - resultType == RESULT_TYPE_CHAR ? FALSE : TRUE)); + RTYPE (tree), + resultType, + tree->opval.op)); } LRVAL (tree) = RRVAL (tree) = 1; @@ -3374,8 +3391,9 @@ decorateType (ast * tree, RESULT_TYPE resultType) tree->left = addCast (tree->left, resultType, TRUE); TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), - NULL, - resultType == RESULT_TYPE_CHAR ? FALSE : TRUE)); + NULL, + resultType, + tree->opval.op)); } else /* RIGHT_OP */ { @@ -3858,7 +3876,8 @@ decorateType (ast * tree, RESULT_TYPE resultType) goto errorTreeReturn; } - TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE); + TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), + resultType, tree->opval.op); TETYPE (tree) = getSpec (TTYPE (tree)); return tree; @@ -3941,7 +3960,8 @@ decorateType (ast * tree, RESULT_TYPE resultType) TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), - FALSE)); + RESULT_TYPE_NOPROM, + tree->opval.op)); if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) werror (E_CODE_WRITE, "-="); @@ -3983,7 +4003,8 @@ decorateType (ast * tree, RESULT_TYPE resultType) TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), - FALSE)); + RESULT_TYPE_NOPROM, + tree->opval.op)); if (!tree->initMode && IS_CONSTANT (LETYPE (tree))) werror (E_CODE_WRITE, "+="); diff --git a/src/SDCCast.h b/src/SDCCast.h index 04211fa9..d46ad5f1 100644 --- a/src/SDCCast.h +++ b/src/SDCCast.h @@ -170,17 +170,6 @@ ast; x == AND_ASSIGN || x == OR_ASSIGN || x == INC_OP || x == DEC_OP) #define IS_DEREF_OP(x) (( x->opval.op == '*' && x->right == NULL) || x->opval.op == '.') -typedef enum -{ - RESULT_TYPE_NONE = 0, - RESULT_CHECK = 0, /* TODO: replace all occurences with the appropriate type and remove me */ - RESULT_TYPE_BIT, - RESULT_TYPE_CHAR, - RESULT_TYPE_INT, - RESULT_TYPE_OTHER, - RESULT_TYPE_IFX, -} RESULT_TYPE; - /* forward declarations for global variables */ extern ast *staticAutos; extern FILE *codeOutFile; diff --git a/src/SDCCicode.c b/src/SDCCicode.c index 5c875c1a..f4e50eba 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -45,7 +45,6 @@ symbol *entryLabel; /* function entry label */ /*-----------------------------------------------------------------*/ /* forward definition of some functions */ -operand *geniCodeDivision (operand *, operand *, bool); operand *geniCodeAssign (operand *, operand *, int); static operand *geniCodeArray (operand *, operand *,int); static operand *geniCodeArray2Ptr (operand *); @@ -1703,10 +1702,11 @@ setOperandType (operand * op, sym_link * type) } } + /*-----------------------------------------------------------------*/ /* Get size in byte of ptr need to access an array */ /*-----------------------------------------------------------------*/ -int +static int getArraySizePtr (operand * op) { sym_link *ltype = operandType(op); @@ -1766,7 +1766,7 @@ usualUnaryConversions (operand * op) static sym_link * usualBinaryConversions (operand ** op1, operand ** op2, - bool resultIsInt, char op) + RESULT_TYPE resultType, char op) { sym_link *ctype; sym_link *rtype = operandType (*op2); @@ -1804,10 +1804,10 @@ usualBinaryConversions (operand ** op1, operand ** op2, && ( (IS_CHAR (getSpec (ltype)) && !IS_UNSIGNED (getSpec (ltype))) || (IS_CHAR (getSpec (rtype)) && !IS_UNSIGNED (getSpec (rtype))))) /* one or two signed char operands: promote to int */ - resultIsInt = TRUE; + resultType = RESULT_TYPE_INT; #endif - ctype = computeType (ltype, rtype, resultIsInt); + ctype = computeType (ltype, rtype, resultType, op); #ifdef OLDONEBYTEOPS @@ -2069,8 +2069,8 @@ geniCodeGoto (symbol * label) /*-----------------------------------------------------------------*/ /* geniCodeMultiply - gen intermediate code for multiplication */ /*-----------------------------------------------------------------*/ -operand * -geniCodeMultiply (operand * left, operand * right, bool resultIsInt) +static operand * +geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType) { iCode *ic; int p2 = 0; @@ -2086,7 +2086,7 @@ geniCodeMultiply (operand * left, operand * right, bool resultIsInt) p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand)); } - resType = usualBinaryConversions (&left, &right, resultIsInt, '*'); + resType = usualBinaryConversions (&left, &right, resultType, '*'); #if 1 rtype = operandType (right); retype = getSpec (rtype); @@ -2100,12 +2100,12 @@ geniCodeMultiply (operand * left, operand * right, bool resultIsInt) efficient in most cases than 2 bytes result = 2 bytes << literal if port has 1 byte muldiv */ if (p2 && !IS_FLOAT (letype) - && !((resultIsInt) && (getSize (resType) != getSize (ltype)) + && !((resultType != RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)) && (port->support.muldiv == 1)) && strcmp (port->target, "pic14") != 0 /* don't shift for pic */ && strcmp (port->target, "pic16") != 0) { - if ((resultIsInt) && (getSize (resType) != getSize (ltype))) + if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))) { /* LEFT_OP need same size for left and result, */ left = geniCodeCast (resType, left, TRUE); @@ -2130,8 +2130,8 @@ geniCodeMultiply (operand * left, operand * right, bool resultIsInt) /*-----------------------------------------------------------------*/ /* geniCodeDivision - gen intermediate code for division */ /*-----------------------------------------------------------------*/ -operand * -geniCodeDivision (operand * left, operand * right, bool resultIsInt) +static operand * +geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType) { iCode *ic; int p2 = 0; @@ -2141,7 +2141,7 @@ geniCodeDivision (operand * left, operand * right, bool resultIsInt) sym_link *ltype = operandType (left); sym_link *letype = getSpec (ltype); - resType = usualBinaryConversions (&left, &right, resultIsInt, '/'); + resType = usualBinaryConversions (&left, &right, resultType, '/'); /* if the right is a literal & power of 2 and left is unsigned then make it a @@ -2168,8 +2168,8 @@ geniCodeDivision (operand * left, operand * right, bool resultIsInt) /*-----------------------------------------------------------------*/ /* geniCodeModulus - gen intermediate code for modulus */ /*-----------------------------------------------------------------*/ -operand * -geniCodeModulus (operand * left, operand * right, bool resultIsInt) +static operand * +geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType) { iCode *ic; sym_link *resType; @@ -2180,7 +2180,7 @@ geniCodeModulus (operand * left, operand * right, bool resultIsInt) return operandFromValue (valMod (left->operand.valOperand, right->operand.valOperand)); - resType = usualBinaryConversions (&left, &right, resultIsInt, '%'); + resType = usualBinaryConversions (&left, &right, resultType, '%'); /* now they are the same size */ ic = newiCode ('%', left, right); @@ -2231,8 +2231,8 @@ subtractExit: /*-----------------------------------------------------------------*/ /* geniCodeSubtract - generates code for subtraction */ /*-----------------------------------------------------------------*/ -operand * -geniCodeSubtract (operand * left, operand * right) +static operand * +geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType) { iCode *ic; int isarray = 0; @@ -2255,12 +2255,15 @@ geniCodeSubtract (operand * left, operand * right) { isarray = left->isaddr; right = geniCodeMultiply (right, - operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE)); + operandFromLit (getSize (ltype->next)), + (getArraySizePtr(left) >= INTSIZE) ? + RESULT_TYPE_INT : + RESULT_TYPE_CHAR); resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype); } else { /* make them the same size */ - resType = usualBinaryConversions (&left, &right, FALSE, '-'); + resType = usualBinaryConversions (&left, &right, resultType, '-'); } ic = newiCode ('-', left, right); @@ -2279,8 +2282,8 @@ geniCodeSubtract (operand * left, operand * right) /*-----------------------------------------------------------------*/ /* geniCodeAdd - generates iCode for addition */ /*-----------------------------------------------------------------*/ -operand * -geniCodeAdd (operand * left, operand * right, int lvl) +static operand * +geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl) { iCode *ic; sym_link *resType; @@ -2308,7 +2311,11 @@ geniCodeAdd (operand * left, operand * right, int lvl) size = operandFromLit (getSize (ltype->next)); SPEC_USIGN (getSpec (operandType (size))) = 1; indexUnsigned = IS_UNSIGNED (getSpec (operandType (right))); - right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE)); + right = geniCodeMultiply (right, + size, + (getArraySizePtr(left) >= INTSIZE) ? + RESULT_TYPE_INT : + RESULT_TYPE_CHAR); /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules. It doesn't make sense when accessing arrays, so let's fix it here: */ @@ -2319,7 +2326,7 @@ geniCodeAdd (operand * left, operand * right, int lvl) } else { // make them the same size - resType = usualBinaryConversions (&left, &right, FALSE, '+'); + resType = usualBinaryConversions (&left, &right, resultType, '+'); } /* if they are both literals then we know */ @@ -2401,12 +2408,22 @@ geniCodeArray (operand * left, operand * right, int lvl) left = geniCodeRValue (left, FALSE); } - return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl); + return geniCodeDerefPtr (geniCodeAdd (left, + right, + (getArraySizePtr(left) >= INTSIZE) ? + RESULT_TYPE_INT : + RESULT_TYPE_CHAR, + lvl), + lvl); } size = operandFromLit (getSize (ltype->next)); SPEC_USIGN (getSpec (operandType (size))) = 1; indexUnsigned = IS_UNSIGNED (getSpec (operandType (right))); - right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE)); + right = geniCodeMultiply (right, + size, + (getArraySizePtr(left) >= INTSIZE) ? + RESULT_TYPE_INT : + RESULT_TYPE_CHAR); /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules. It doesn't make sense when accessing arrays, so let's fix it here: */ if (indexUnsigned) @@ -2909,7 +2926,7 @@ geniCodeLogic (operand * left, operand * right, int op) } } - ctype = usualBinaryConversions (&left, &right, FALSE, ' '); + ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, ' '); ic = newiCode (op, left, right); IC_RESULT (ic) = newiTempOperand (newCharLink (), 1); @@ -3498,7 +3515,7 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) /* if the min is not zero then we no make it zero */ if (min) { - cond = geniCodeSubtract (cond, operandFromLit (min)); + cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR); if (!IS_LITERAL(getSpec(operandType(cond)))) setOperandType (cond, UCHARTYPE); } @@ -3866,31 +3883,34 @@ ast2iCode (ast * tree,int lvl) case '/': return geniCodeDivision (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE), - IS_INT (tree->ftype)); + getResultTypeFromType (tree->ftype)); case '%': return geniCodeModulus (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE), - IS_INT (tree->ftype)); + getResultTypeFromType (tree->ftype)); case '*': if (right) return geniCodeMultiply (geniCodeRValue (left, FALSE), geniCodeRValue (right, FALSE), - IS_INT (tree->ftype)); + getResultTypeFromType (tree->ftype)); else return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl); case '-': if (right) return geniCodeSubtract (geniCodeRValue (left, FALSE), - geniCodeRValue (right, FALSE)); + geniCodeRValue (right, FALSE), + getResultTypeFromType (tree->ftype)); else return geniCodeUnaryMinus (geniCodeRValue (left, FALSE)); case '+': if (right) return geniCodeAdd (geniCodeRValue (left, FALSE), - geniCodeRValue (right, FALSE),lvl); + geniCodeRValue (right, FALSE), + getResultTypeFromType (tree->ftype), + lvl); else return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */ @@ -3981,7 +4001,8 @@ ast2iCode (ast * tree,int lvl) geniCodeAssign (left, geniCodeMultiply (geniCodeRValue (operandFromOperand (left), FALSE), - geniCodeRValue (right, FALSE),FALSE), 0); + geniCodeRValue (right, FALSE), FALSE), + getResultTypeFromType (tree->ftype)); case DIV_ASSIGN: return @@ -3989,7 +4010,7 @@ ast2iCode (ast * tree,int lvl) geniCodeDivision (geniCodeRValue (operandFromOperand (left), FALSE), geniCodeRValue (right, FALSE), - IS_INT (tree->ftype)), + getResultTypeFromType (tree->ftype)), 0); case MOD_ASSIGN: return @@ -3997,7 +4018,7 @@ ast2iCode (ast * tree,int lvl) geniCodeModulus (geniCodeRValue (operandFromOperand (left), FALSE), geniCodeRValue (right, FALSE), - IS_INT (tree->ftype)), + getResultTypeFromType (tree->ftype)), 0); case ADD_ASSIGN: { @@ -4013,7 +4034,10 @@ ast2iCode (ast * tree,int lvl) return geniCodeAssign (left, geniCodeAdd (geniCodeRValue (operandFromOperand (left), FALSE), - right,lvl), 0); + right, + getResultTypeFromType (tree->ftype), + lvl), + 0); } case SUB_ASSIGN: { @@ -4032,7 +4056,9 @@ ast2iCode (ast * tree,int lvl) geniCodeAssign (left, geniCodeSubtract (geniCodeRValue (operandFromOperand (left), FALSE), - right), 0); + right, + getResultTypeFromType (tree->ftype)), + 0); } case LEFT_ASSIGN: return diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index c1c8a8ce..4ceceaf0 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -24,6 +24,8 @@ #include "common.h" #include "newalloc.h" +#include "SDCCsymt.h" + value *aggregateToPointer (value *val); void printTypeChainRaw (sym_link * start, FILE * of); @@ -566,6 +568,14 @@ void checkTypeSanity(sym_link *etype, char *name) { SPEC_NOUN(etype)=V_INT; } + /* ISO/IEC 9899 J.3.9 implementation defined behaviour: */ + /* a "plain" int bitfield is unsigned */ + if (SPEC_NOUN(etype)==V_BIT || + SPEC_NOUN(etype)==V_SBIT) { + if (!etype->select.s._signed) + SPEC_USIGN(etype) = 1; + } + if (etype->select.s._signed && SPEC_USIGN(etype)) { // signed AND unsigned werror (E_SIGNED_AND_UNSIGNED_INVALID, noun, name); @@ -1578,17 +1588,85 @@ cleanUpLevel (bucket ** table, int level) } } +/*------------------------------------------------------------------*/ +/* computeTypeOr - computes the resultant type from two types */ +/*------------------------------------------------------------------*/ +static sym_link * +computeTypeOr (sym_link * etype1, sym_link * etype2, sym_link * reType) +{ + /* sanity check */ + assert (IS_CHAR (etype1) && IS_CHAR (etype2)); + + if (SPEC_USIGN (etype1) == SPEC_USIGN (etype2)) + { + SPEC_USIGN (reType) = SPEC_USIGN (etype1); + return reType; + } + + if (SPEC_USIGN (etype1)) + { + if ( IS_LITERAL (etype2) + && floatFromVal (valFromType (etype2)) >= 0) + SPEC_USIGN (reType) = 1; + else + { + /* promote to int */ + SPEC_USIGN (reType) = 0; + SPEC_NOUN (reType) = V_INT; + } + } + else /* etype1 signed */ + { + if ( IS_LITERAL (etype2) + && floatFromVal (valFromType (etype2)) <= 127) + SPEC_USIGN (reType) = 0; + else + { + /* promote to int */ + SPEC_USIGN (reType) = 0; + SPEC_NOUN (reType) = V_INT; + } + } + + if (SPEC_USIGN (etype2)) + { + if ( IS_LITERAL (etype1) + && floatFromVal (valFromType (etype1)) >= 0) + SPEC_USIGN (reType) = 1; + else + { + /* promote to int */ + SPEC_USIGN (reType) = 0; + SPEC_NOUN (reType) = V_INT; + } + } + else /* etype2 signed */ + { + if ( IS_LITERAL (etype1) + && floatFromVal (valFromType (etype1)) <= 127) + SPEC_USIGN (reType) = 0; + else + { + /* promote to int */ + SPEC_USIGN (reType) = 0; + SPEC_NOUN (reType) = V_INT; + } + } + return reType; +} + /*------------------------------------------------------------------*/ /* computeType - computes the resultant type from two types */ /*------------------------------------------------------------------*/ sym_link * -computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt) +computeType (sym_link * type1, sym_link * type2, + RESULT_TYPE resultType, char op) { sym_link *rType; sym_link *reType; sym_link *etype1 = getSpec (type1); sym_link *etype2; - + etype2 = type2 ? getSpec (type2) : type1; /* if one of them is a float then result is a float */ @@ -1598,12 +1676,28 @@ computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt) if (IS_FLOAT (etype1) || IS_FLOAT (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 (IS_BITVAR (etype1) && !IS_BITVAR (etype2)) - rType = copyLinkChain (type2); + else if (IS_BITVAR (etype1) && !IS_BITVAR (etype2)) + { + rType = copyLinkChain (type2); + /* bitfield can have up to 16 bits */ + if (getSize (etype1) > 1) + SPEC_NOUN (getSpec (rType)) = V_INT; + } else if (IS_BITVAR (etype2) && !IS_BITVAR (etype1)) - rType = copyLinkChain (type1); + { + rType = copyLinkChain (type1); + /* bitfield can have up to 16 bits */ + if (getSize (etype2) > 1) + SPEC_NOUN (getSpec (rType)) = V_INT; + } else /* if one of them is a pointer or array then that prevails */ @@ -1621,8 +1715,60 @@ computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt) /* avoid conflicting types */ reType->select.s._signed = 0; - if (IS_CHAR (reType) && promoteCharToInt) - SPEC_NOUN (reType) = V_INT; + /* if result is a literal then make not so */ + if (IS_LITERAL (reType)) + SPEC_SCLS (reType) = S_REGISTER; + + switch (resultType) + { + case RESULT_TYPE_CHAR: + if (IS_BITVAR (reType)) + { + SPEC_NOUN (reType) = V_CHAR; + SPEC_SCLS (reType) = 0; + SPEC_USIGN (reType) = 0; + return rType; + } + break; + case RESULT_TYPE_INT: + case RESULT_TYPE_NONE: + if (IS_BIT (reType)) + { + SPEC_NOUN (reType) = V_CHAR; + SPEC_SCLS (reType) = 0; + SPEC_USIGN (reType) = 0; + return rType; + } + else if (IS_BITFIELD (reType)) + { + /* could be smarter, but it depends on the op */ + /* this is for the worst case: a multiplication of 4 * 4 bit */ + SPEC_NOUN (reType) = SPEC_BLEN (reType) <= 4 ? V_CHAR : V_INT; + SPEC_SCLS (reType) = 0; + SPEC_USIGN (reType) = 0; + return rType; + } + 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 + { + SPEC_NOUN (reType) = V_INT; + SPEC_USIGN (reType) = 0; + return rType; + } + } + break; + default: + break; + } /* SDCC's sign promotion: - if one or both operands are unsigned, the resultant type will be unsigned @@ -1638,7 +1784,7 @@ computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt) - if the result of an operation with two char's is promoted to a larger type, the result will be signed. - More sophisticated is the last one: + More sophisticated are these: - if the result of an operation with two char's is a char again, the result will only then be unsigned, if both operands are unsigned. In all other cases the result will be signed. @@ -1653,6 +1799,8 @@ computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt) unsigned; this helps to avoid overflow: 2 * 100 = 200; + - ToDo: document '|', '^' and '&' + Homework: - why is (200 * 200 < 0) true? - why is { char l = 200, r = 200; (r * l > 0) } true? */ @@ -1679,10 +1827,6 @@ computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt) else SPEC_USIGN (reType) = 0; - /* if result is a literal then make not so */ - if (IS_LITERAL (reType)) - SPEC_SCLS (reType) = S_REGISTER; - return rType; } diff --git a/src/SDCCsymt.h b/src/SDCCsymt.h index 49ed5eb8..82acf79b 100644 --- a/src/SDCCsymt.h +++ b/src/SDCCsymt.h @@ -457,6 +457,8 @@ extern sym_link *validateLink(sym_link *l, #define IS_BITVAR(x) (IS_SPEC(x) && (x->select.s.noun == V_BITFIELD || \ x->select.s.noun == V_BIT || \ x->select.s.noun == V_SBIT )) +#define IS_BIT(x) (IS_SPEC(x) && (x->select.s.noun == V_BIT || \ + x->select.s.noun == V_SBIT )) #define IS_FLOAT(x) (IS_SPEC(x) && x->select.s.noun == V_FLOAT) #define IS_ARITHMETIC(x) (IS_INTEGRAL(x) || IS_FLOAT(x)) #define IS_AGGREGATE(x) (IS_ARRAY(x) || IS_STRUCT(x)) @@ -502,6 +504,18 @@ extern sym_link *floatType; #include "SDCCval.h" +typedef enum +{ + RESULT_TYPE_NONE = 0, /* operands will be promoted to int */ + RESULT_CHECK = 0, /* TODO: replace all occurences with the appropriate type and remove me */ + RESULT_TYPE_BIT, + RESULT_TYPE_CHAR, + RESULT_TYPE_INT, + RESULT_TYPE_OTHER, /* operands will be promoted to int */ + RESULT_TYPE_IFX, + RESULT_TYPE_NOPROM, /* operands will be promoted to int */ +} RESULT_TYPE; + /* forward definitions for the symbol table related functions */ void initSymt (); symbol *newSymbol (char *, int); @@ -541,7 +555,7 @@ int funcInChain (sym_link *); void addSymChain (symbol *); sym_link *structElemType (sym_link *, value *); symbol *getStructElement (structdef *, symbol *); -sym_link *computeType (sym_link *, sym_link *, bool promoteCharToInt); +sym_link *computeType (sym_link *, sym_link *, RESULT_TYPE, char); void processFuncArgs (symbol *); int isSymbolEqual (symbol *, symbol *); int powof2 (TYPE_UDWORD); diff --git a/src/SDCCval.c b/src/SDCCval.c index c5f25568..b2f8fe0e 100644 --- a/src/SDCCval.c +++ b/src/SDCCval.c @@ -280,7 +280,7 @@ resolveIvalSym (initList * ilist, sym_link * type) if (ilist->type == INIT_NODE) { if (IS_PTR (type)) - resultType = RESULT_TYPE_NONE; + resultType = RESULT_TYPE_INT; else resultType = getResultTypeFromType (getSpec (type)); ilist->init.node = decorateType (resolveSymbols (ilist->init.node), @@ -1086,7 +1086,8 @@ valMult (value * lval, value * rval) val = newValue (); val->type = val->etype = computeType (lval->etype, rval->etype, - TRUE); + RESULT_TYPE_INT, + '*'); SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ if (IS_FLOAT (val->type)) @@ -1135,7 +1136,8 @@ valDiv (value * lval, value * rval) val = newValue (); val->type = val->etype = computeType (lval->etype, rval->etype, - TRUE); + RESULT_TYPE_INT, + '/'); SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ if (IS_FLOAT (val->type)) @@ -1173,7 +1175,8 @@ valMod (value * lval, value * rval) val = newValue(); val->type = val->etype = computeType (lval->etype, rval->etype, - TRUE); + RESULT_TYPE_INT, + '%'); SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ if (SPEC_LONG (val->type)) @@ -1209,7 +1212,8 @@ valPlus (value * lval, value * rval) val = newValue(); val->type = val->etype = computeType (lval->etype, rval->etype, - TRUE); + RESULT_TYPE_INT, + '+'); SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ if (IS_FLOAT (val->type)) @@ -1247,7 +1251,8 @@ valMinus (value * lval, value * rval) val = newValue(); val->type = val->etype = computeType (lval->etype, rval->etype, - TRUE); + RESULT_TYPE_INT, + '-'); SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ if (IS_FLOAT (val->type)) @@ -1285,8 +1290,8 @@ valShift (value * lval, value * rval, int lr) val = newValue(); val->type = val->etype = computeType (lval->etype, NULL, - /* promote left shift */ - lr ? TRUE : FALSE); + RESULT_TYPE_INT, + 'S'); SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ if (getSize (val->type) * 8 <= (TYPE_UDWORD) floatFromVal (rval) && @@ -1435,7 +1440,7 @@ valBitwise (value * lval, value * rval, int op) /* create a new value */ val = newValue (); - val->type = computeType (lval->etype, rval->etype, FALSE); + val->type = computeType (lval->etype, rval->etype, RESULT_TYPE_CHAR, op); val->etype = getSpec (val->type); SPEC_SCLS (val->etype) = S_LITERAL; @@ -1563,6 +1568,12 @@ valCastLiteral (sym_link * dtype, double fval) if (SPEC_NOUN (val->etype) == V_FLOAT) SPEC_CVAL (val->etype).v_float = fval; + else if (SPEC_NOUN (val->etype) == V_BIT || + SPEC_NOUN (val->etype) == V_SBIT) + SPEC_CVAL (val->etype).v_uint = l & 1; + else if (SPEC_NOUN (val->etype) == V_BITFIELD) + SPEC_CVAL (val->etype).v_uint = l & + (0xffffu >> (16 - SPEC_BLEN (val->etype))); else if (SPEC_NOUN (val->etype) == V_CHAR) { if (SPEC_USIGN (val->etype)) SPEC_CVAL (val->etype).v_uint= (TYPE_UBYTE) l; diff --git a/support/regression/tests/onebyte.c b/support/regression/tests/onebyte.c index a5fb515d..1dffcc0f 100644 --- a/support/regression/tests/onebyte.c +++ b/support/regression/tests/onebyte.c @@ -121,3 +121,51 @@ testMod(void) r16 = 0; cL = -128; ucR = 5; r16 = cL % ucR; ASSERT(r16 == -3); } + +void +testOr(void) +{ + {attrL} char cL; + {attrL} unsigned char ucL; + {attrR} char cR; + {attrR} unsigned char ucR; + volatile short r16, r16b; + + cL = 0x00; cR = 0x80; r16 = cL | cR; r16b = cR | cL; ASSERT(r16 == (short) 0xff80); ASSERT(r16b == (short) 0xff80); + ucL = 0x80; cR = 0x00; r16 = ucL | cR; r16b = cR | ucL; ASSERT(r16 == 0x80); ASSERT(r16b == 0x80); + ucL = 0x80; ucR = 0x80; r16 = ucL | ucR; r16b = ucR | ucL; ASSERT(r16 == 0x80); ASSERT(r16b == 0x80); +} + +void +testXor(void) +{ + {attrL} char cL; + {attrL} unsigned char ucL; + {attrR} char cR; + {attrR} unsigned char ucR; + volatile short r16, r16b; + + cL = 0x80; cR = 0x80; r16 = cL ^ cR; r16b = cR ^ cL; ASSERT(r16 == 0); ASSERT(r16b == 0); + cL = 0x80; cR = 0x00; r16 = cL ^ cR; r16b = cR ^ cL; ASSERT(r16 == (short) 0xff80); ASSERT(r16b == (short) 0xff80); + + ucL = 0x80; cR = 0x80; r16 = ucL ^ cR; r16b = cR ^ ucL; ASSERT(r16 == (short) 0xff00); ASSERT(r16b == (short) 0xff00); + ucL = 0x80; cR = 0; r16 = ucL ^ cR; r16b = cR ^ ucL; ASSERT(r16 == 0x80); ASSERT(r16b == 0x80); + ucL = 0; cR = 0x80; r16 = ucL ^ cR; r16b = cR ^ ucL; ASSERT(r16 == (short) 0xff80); ASSERT(r16b == (short) 0xff80); + + ucL = 0x80; ucR = 0x80; r16 = ucL ^ ucR; r16b = ucR ^ ucL; ASSERT(r16 == 0); ASSERT(r16b == 0); + ucL = 0; ucR = 0x80; r16 = ucL ^ ucR; r16b = ucR ^ ucL; ASSERT(r16 == 0x80); ASSERT(r16b == 0x80); +} + +void +testAnd(void) +{ + {attrL} char cL; + {attrL} unsigned char ucL; + {attrR} char cR; + {attrR} unsigned char ucR; + volatile short r16, r16b; + + cL = 0x80; cR = 0x80; r16 = cL & cR; r16b = cR & cL; ASSERT(r16 == (short) 0xff80); ASSERT(r16b == (short) 0xff80); + ucL = 0x80; cR = 0x80; r16 = ucL & cR; r16b = cR & ucL; ASSERT(r16 == 0x80); ASSERT(r16b == 0x80); + ucL = 0x80; ucR = 0x80; r16 = ucL & ucR; r16b = ucR & ucL; ASSERT(r16 == 0x80); ASSERT(r16b == 0x80); +} -- 2.30.2