+2004-03-06 Bernhard Held <bernhard AT bernhardheld.de>
+
+ * 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 <hjdorn AT users.sourceforge.net>
* src/pic16/gen.c: (genpic16Code) use copy of printILine's output
\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
# include <unistd.h>
#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.
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.
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.
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=$?
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
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 7278 "configure"
+#line 7283 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 7376 "configure"
+#line 7381 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
_ACEOF
+# *nix default: "${datadir}/sdcc/doc"
+
+if test "${docdir}" = ""; then
+ docdir="\${datadir}"/sdcc/doc
+fi
+
# Generating output files
# ===========================================================================
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
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
# ===========================================================================
man2dir = $(mandir)/man2
infodir = @infodir@
srcdir = @srcdir@
-docdir = $(prefix)/share/sdcc/doc/ucsim
+docdir = @docdir@/ucsim
# Compiling entire program or any subproject
$$ = newLink(SPECIFIER) ;
SPEC_NOUN($$) = V_SBIT;
SPEC_SCLS($$) = S_SBIT;
+ SPEC_BLEN($$) = 1;
+ SPEC_BSTR($$) = 0;
ignoreTypedefType = 1;
}
| sfr_attributes
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)
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 */
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
RTYPE (tree),
- FALSE));
+ resultType,
+ tree->opval.op));
return tree;
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 */
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
RTYPE (tree),
- resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
+ resultType,
+ tree->opval.op));
return tree;
/*------------------------------------------------------------------*/
TETYPE (tree) = getSpec (TTYPE (tree) =
computeType (LTYPE (tree),
RTYPE (tree),
- resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
+ resultType,
+ tree->opval.op));
return tree;
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;
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;
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 */
{
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;
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, "-=");
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, "+=");
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;
/*-----------------------------------------------------------------*/
/* 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 *);
}
}
+
/*-----------------------------------------------------------------*/
/* Get size in byte of ptr need to access an array */
/*-----------------------------------------------------------------*/
-int
+static int
getArraySizePtr (operand * op)
{
sym_link *ltype = operandType(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);
&& ( (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
/*-----------------------------------------------------------------*/
/* 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;
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);
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);
/*-----------------------------------------------------------------*/
/* 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;
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
/*-----------------------------------------------------------------*/
/* 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;
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);
/*-----------------------------------------------------------------*/
/* 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;
{
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);
/*-----------------------------------------------------------------*/
/* 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;
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: */
}
else
{ // make them the same size
- resType = usualBinaryConversions (&left, &right, FALSE, '+');
+ resType = usualBinaryConversions (&left, &right, resultType, '+');
}
/* if they are both literals then we know */
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)
}
}
- ctype = usualBinaryConversions (&left, &right, FALSE, ' ');
+ ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, ' ');
ic = newiCode (op, left, right);
IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
/* 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);
}
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 */
geniCodeAssign (left,
geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
FALSE),
- geniCodeRValue (right, FALSE),FALSE), 0);
+ geniCodeRValue (right, FALSE), FALSE),
+ getResultTypeFromType (tree->ftype));
case DIV_ASSIGN:
return
geniCodeDivision (geniCodeRValue (operandFromOperand (left),
FALSE),
geniCodeRValue (right, FALSE),
- IS_INT (tree->ftype)),
+ getResultTypeFromType (tree->ftype)),
0);
case MOD_ASSIGN:
return
geniCodeModulus (geniCodeRValue (operandFromOperand (left),
FALSE),
geniCodeRValue (right, FALSE),
- IS_INT (tree->ftype)),
+ getResultTypeFromType (tree->ftype)),
0);
case ADD_ASSIGN:
{
return geniCodeAssign (left,
geniCodeAdd (geniCodeRValue (operandFromOperand (left),
FALSE),
- right,lvl), 0);
+ right,
+ getResultTypeFromType (tree->ftype),
+ lvl),
+ 0);
}
case SUB_ASSIGN:
{
geniCodeAssign (left,
geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
FALSE),
- right), 0);
+ right,
+ getResultTypeFromType (tree->ftype)),
+ 0);
}
case LEFT_ASSIGN:
return
#include "common.h"
#include "newalloc.h"
+#include "SDCCsymt.h"
+
value *aggregateToPointer (value *val);
void printTypeChainRaw (sym_link * start, FILE * of);
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);
}
}
+/*------------------------------------------------------------------*/
+/* 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 */
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 */
/* 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
- 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.
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?
*/
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;
}
#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))
#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);
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);
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),
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))
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))
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))
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))
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))
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) &&
/* 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;
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;
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);
+}