#define SDCC_NAME_MAX 3*SDCC_SYMNAME_MAX // big enough for _<func>_<var>_etc
#include "SDCChasht.h"
#include "SDCCglobl.h"
+#include "dbuf.h"
#define INTNO_MAX 255 /* maximum allowed interrupt number */
#define INTNO_UNSPEC (INTNO_MAX+1) /* interrupt number unspecified */
};
// values for first byte (or 3 most significant bits) of generic pointer.
+#if 0
#define GPTYPE_FAR 0x00
#define GPTYPE_NEAR 0x40
#define GPTYPE_XSTACK 0x60
#define GPTYPE_CODE 0x80
+#else
+#define GPTYPE_FAR (port->gp_tags.tag_far)
+#define GPTYPE_NEAR (port->gp_tags.tag_near)
+#define GPTYPE_XSTACK (port->gp_tags.tag_xstack)
+#define GPTYPE_CODE (port->gp_tags.tag_code)
+#endif
#define HASHTAB_SIZE 256
struct symbol *fields; /* pointer to fields */
unsigned size; /* sizeof the table in bytes */
int type; /* STRUCT or UNION */
+ bool b_flexArrayMember; /* has got an flexible array member,
+ only needed for syntax checks */
}
structdef;
}
STORAGE_CLASS;
+#define TYPE_TARGET_CHAR TYPE_BYTE
+#define TYPE_TARGET_INT TYPE_WORD
+#define TYPE_TARGET_LONG TYPE_DWORD
+#define TYPE_TARGET_UCHAR TYPE_UBYTE
+#define TYPE_TARGET_UINT TYPE_UWORD
+#define TYPE_TARGET_ULONG TYPE_UDWORD
+
/* specifier is the last in the type-chain */
typedef struct specifier
{
NOUN noun; /* CHAR INT STRUCTURE LABEL */
STORAGE_CLASS sclass; /* REGISTER,AUTO,FIX,CONSTANT */
struct memmap *oclass; /* output storage class */
- unsigned _long:1; /* 1=long */
- unsigned _short:1; /* 1=short int */
- unsigned _unsigned:1; /* 1=unsigned, 0=signed */
- unsigned _signed:1; /* just for sanity checks only*/
- unsigned _static:1; /* 1=static keyword found */
- unsigned _extern:1; /* 1=extern found */
- unsigned _absadr:1; /* absolute address specfied */
- unsigned _volatile:1; /* is marked as volatile */
- unsigned _const:1; /* is a constant */
- unsigned _typedef:1; /* is typedefed */
- unsigned _isregparm:1; /* is the first parameter */
- unsigned _isenum:1; /* is an enumerated type */
- unsigned _addr; /* address of symbol */
- unsigned _stack; /* stack offset for stacked v */
+ unsigned b_long:1; /* 1=long */
+ unsigned b_short:1; /* 1=short int */
+ unsigned b_unsigned:1; /* 1=unsigned, 0=signed */
+ unsigned b_signed:1; /* just for sanity checks only*/
+ unsigned b_static:1; /* 1=static keyword found */
+ unsigned b_extern:1; /* 1=extern found */
+ unsigned b_inline:1; /* inline function requested */
+ unsigned b_absadr:1; /* absolute address specfied */
+ unsigned b_volatile:1; /* is marked as volatile */
+ unsigned b_const:1; /* is a constant */
+ unsigned b_restrict:1; /* is restricted */
+ unsigned b_typedef:1; /* is typedefed */
+ unsigned b_isregparm:1; /* is the first parameter */
+ unsigned b_isenum:1; /* is an enumerated type */
+ unsigned b_bitUnnamed:1; /* is an unnamed bit-field */
unsigned _bitStart; /* bit start position */
int _bitLength; /* bit length */
+ unsigned _addr; /* address of symbol */
+ unsigned _stack; /* stack offset for stacked v */
int argreg; /* reg no for regparm */
union
{ /* Values if constant or enum */
- TYPE_WORD v_int; /* 2 bytes: int and char values */
- char *v_char; /* character string */
- TYPE_UWORD v_uint; /* 2 bytes: unsigned int const value */
- TYPE_DWORD v_long; /* 4 bytes: long constant value */
- TYPE_UDWORD v_ulong; /* 4 bytes: unsigned long constant value */
- double v_float; /* floating point constant value */
- TYPE_UDWORD v_fixed16x16; /* 4 bytes: fixed floating point constant value */
- struct symbol *v_enum; /* ptr to enum_list if enum==1 */
+ TYPE_TARGET_INT v_int; /* 2 bytes: int and char values */
+ char *v_char; /* character string */
+ TYPE_TARGET_UINT v_uint; /* 2 bytes: unsigned int const value */
+ TYPE_TARGET_LONG v_long; /* 4 bytes: long constant value */
+ TYPE_TARGET_ULONG v_ulong; /* 4 bytes: unsigned long constant value */
+ double v_float; /* floating point constant value */
+ TYPE_TARGET_ULONG v_fixed16x16; /* 4 bytes: fixed floating point constant value */
+ struct symbol *v_enum; /* ptr to enum_list if enum==1 */
}
const_val;
struct structdef *v_struct; /* structure pointer */
typedef struct declarator
{
DECLARATOR_TYPE dcl_type; /* POINTER,ARRAY or FUNCTION */
- unsigned int num_elem; /* # of elems if type==array */
+ unsigned int num_elem; /* # of elems if type==array, */
+ /* always 0 for flexible arrays */
unsigned ptr_const:1; /* pointer is constant */
unsigned ptr_volatile:1; /* pointer is volatile */
+ unsigned ptr_restrict:1; /* pointer is resticted */
struct sym_link *tspec; /* pointer type specifier */
}
declarator;
DECLARATOR=1,
SPECIFIER
} SYM_LINK_CLASS;
-#define DECLSPEC2TXT(select) (select==DECLARATOR?"DECLARATOR":select==SPECIFIER?"SPECIFIER":"UNKNOW")
+#define DECLSPEC2TXT(select) (select==DECLARATOR?"DECLARATOR":select==SPECIFIER?"SPECIFIER":"UNKNOWN")
typedef struct sym_link
{
unsigned critical:1; /* critical function */
unsigned intrtn:1; /* this is an interrupt routine */
unsigned rbank:1; /* seperate register bank */
+ unsigned inlinereq:1; /* inlining requested */
unsigned intno; /* 1=Interrupt svc routine */
short regbank; /* register bank 2b used */
unsigned builtin; /* is a builtin function */
char name[SDCC_SYMNAME_MAX + 1]; /* Input Variable Name */
char rname[SDCC_NAME_MAX + 1]; /* internal name */
- short level; /* declration lev,fld offset */
- short block; /* sequential block # of defintion */
+ short level; /* declaration lev,fld offset */
+ short block; /* sequential block # of definition */
int key;
+ unsigned flexArrayLength; /* if the symbol specifies a struct
+ with a "flexible array member", then the additional length in bytes for
+ the "fam" is stored here. Because the length can be different from symbol
+ to symbol AND v_struct isn't copied in copyLinkChain(), it's located here
+ in the symbol and not in v_struct or the declarator */
unsigned implicit:1; /* implicit flag */
unsigned undefined:1; /* undefined variable */
+ unsigned infertype:1; /* type should be inferred from first assign */
unsigned _isparm:1; /* is a parameter */
unsigned ismyparm:1; /* is parameter of the function being generated */
unsigned isitmp:1; /* is an intermediate temp */
unsigned isinvariant:1; /* is a loop invariant */
unsigned cdef:1; /* compiler defined symbol */
unsigned addrtaken:1; /* address of the symbol was taken */
- unsigned isreqv:1; /* is the register quivalent of a symbol */
+ unsigned isreqv:1; /* is the register equivalent of a symbol */
unsigned udChked:1; /* use def checking has been already done */
+ unsigned generated:1; /* code generated (function symbols only) */
/* following flags are used by the backend
for code generation and can be changed
struct iCode *fuse; /* furthest use */
struct iCode *rematiCode; /* rematerialise with which instruction */
struct operand *reqv; /* register equivalent of a local variable */
- struct symbol *prereqv; /* symbol before register equiv. substituion */
+ struct symbol *prereqv; /* symbol before register equiv. substitution */
struct symbol *psbase; /* if pseudo symbol, the symbol it is based on */
union
{
struct set *itmpStack; /* symbols spilt @ this stack location */
}
usl;
- short bitVar; /* this is a bit variable */
+ char bitVar; /* if bitVar != 0: this is a bit variable, bitVar is the size in bits */
+ char bitUnnamed:1; /* unnamed bit variable */
unsigned offset; /* offset from top if struct */
int lineDef; /* defined line number */
int used; /* no. of times this was used */
int recvSize; /* size of first argument */
struct bitVect *clashes; /* overlaps with what other symbols */
+ struct ast * funcTree; /* function body ast if inlined */
}
symbol;
const char *file,
unsigned line);
/* Easy Access Macros */
+#define IS_OP_RUONLY(x) (IS_SYMOP(x) && OP_SYMBOL(x) && OP_SYMBOL(x)->ruonly)
+#define IS_OP_ACCUSE(x) (IS_SYMOP(x) && OP_SYMBOL(x) && OP_SYMBOL(x)->accuse)
+
#define DCL_TYPE(l) validateLink(l, "DCL_TYPE", #l, DECLARATOR, __FILE__, __LINE__)->select.d.dcl_type
#define DCL_ELEM(l) validateLink(l, "DCL_ELEM", #l, DECLARATOR, __FILE__, __LINE__)->select.d.num_elem
#define DCL_PTR_CONST(l) validateLink(l, "DCL_PTR_CONST", #l, DECLARATOR, __FILE__, __LINE__)->select.d.ptr_const
#define DCL_PTR_VOLATILE(l) validateLink(l, "DCL_PTR_VOLATILE", #l, DECLARATOR, __FILE__, __LINE__)->select.d.ptr_volatile
+#define DCL_PTR_RESTRICT(l) validateLink(l, "DCL_PTR_RESTRICT", #l, DECLARATOR, __FILE__, __LINE__)->select.d.ptr_restrict
#define DCL_TSPEC(l) validateLink(l, "DCL_TSPEC", #l, DECLARATOR, __FILE__, __LINE__)->select.d.tspec
#define FUNC_DEBUG //assert(IS_FUNC(x));
#define FUNC_INTNO(x) (x->funcAttrs.intno)
#define FUNC_REGBANK(x) (x->funcAttrs.regbank)
#define FUNC_HASSTACKPARM(x) (x->funcAttrs.hasStackParms)
+#define FUNC_ISINLINE(x) (x->funcAttrs.inlinereq)
+#define IFFUNC_ISINLINE(x) (IS_FUNC(x) && FUNC_ISINLINE(x))
#define FUNC_ISREENT(x) (x->funcAttrs.reent)
#define IFFUNC_ISREENT(x) (IS_FUNC(x) && FUNC_ISREENT(x))
IFFUNC_BANKED(x)))
#define SPEC_NOUN(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.noun
-#define SPEC_LONG(x) validateLink(x, "SPEC_LONG", #x, SPECIFIER, __FILE__, __LINE__)->select.s._long
-#define SPEC_SHORT(x) validateLink(x, "SPEC_LONG", #x, SPECIFIER, __FILE__, __LINE__)->select.s._short
-#define SPEC_USIGN(x) validateLink(x, "SPEC_USIGN", #x, SPECIFIER, __FILE__, __LINE__)->select.s._unsigned
+#define SPEC_LONG(x) validateLink(x, "SPEC_LONG", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_long
+#define SPEC_SHORT(x) validateLink(x, "SPEC_LONG", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_short
+#define SPEC_USIGN(x) validateLink(x, "SPEC_USIGN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_unsigned
#define SPEC_SCLS(x) validateLink(x, "SPEC_SCLS", #x, SPECIFIER, __FILE__, __LINE__)->select.s.sclass
-#define SPEC_ENUM(x) validateLink(x, "SPEC_ENUM", #x, SPECIFIER, __FILE__, __LINE__)->select.s._isenum
+#define SPEC_ENUM(x) validateLink(x, "SPEC_ENUM", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_isenum
#define SPEC_OCLS(x) validateLink(x, "SPEC_OCLS", #x, SPECIFIER, __FILE__, __LINE__)->select.s.oclass
-#define SPEC_STAT(x) validateLink(x, "SPEC_STAT", #x, SPECIFIER, __FILE__, __LINE__)->select.s._static
-#define SPEC_EXTR(x) validateLink(x, "SPEC_EXTR", #x, SPECIFIER, __FILE__, __LINE__)->select.s._extern
+#define SPEC_STAT(x) validateLink(x, "SPEC_STAT", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_static
+#define SPEC_EXTR(x) validateLink(x, "SPEC_EXTR", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_extern
#define SPEC_CODE(x) validateLink(x, "SPEC_CODE", #x, SPECIFIER, __FILE__, __LINE__)->select.s._codesg
-#define SPEC_ABSA(x) validateLink(x, "SPEC_ABSA", #x, SPECIFIER, __FILE__, __LINE__)->select.s._absadr
+#define SPEC_ABSA(x) validateLink(x, "SPEC_ABSA", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_absadr
#define SPEC_BANK(x) validateLink(x, "SPEC_BANK", #x, SPECIFIER, __FILE__, __LINE__)->select.s._regbank
#define SPEC_ADDR(x) validateLink(x, "SPEC_ADDR", #x, SPECIFIER, __FILE__, __LINE__)->select.s._addr
#define SPEC_STAK(x) validateLink(x, "SPEC_STAK", #x, SPECIFIER, __FILE__, __LINE__)->select.s._stack
#define SPEC_CVAL(x) validateLink(x, "SPEC_CVAL", #x, SPECIFIER, __FILE__, __LINE__)->select.s.const_val
#define SPEC_BSTR(x) validateLink(x, "SPEC_BSTR", #x, SPECIFIER, __FILE__, __LINE__)->select.s._bitStart
#define SPEC_BLEN(x) validateLink(x, "SPEC_BLEN", #x, SPECIFIER, __FILE__, __LINE__)->select.s._bitLength
+#define SPEC_BUNNAMED(x) validateLink(x, "SPEC_BLEN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_bitUnnamed
/* Sleaze: SPEC_ISR_SAVED_BANKS is only used on
* function type symbols, which obviously cannot
* _bitStart field instead of defining a new field.
*/
#define SPEC_ISR_SAVED_BANKS(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s._bitStart
-#define SPEC_VOLATILE(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s._volatile
-#define SPEC_CONST(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s._const
+#define SPEC_VOLATILE(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_volatile
+#define SPEC_CONST(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_const
+#define SPEC_RESTRICT(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_restrict
#define SPEC_STRUCT(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.v_struct
-#define SPEC_TYPEDEF(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s._typedef
-#define SPEC_REGPARM(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s._isregparm
+#define SPEC_TYPEDEF(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_typedef
+#define SPEC_REGPARM(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_isregparm
#define SPEC_ARGREG(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.argreg
+#define SPEC_INLINE(x) validateLink(x, "SPEC_INLINE", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_inline
/* type check macros */
#define IS_DECL(x) ( x && x->class == DECLARATOR )
DCL_TYPE(x) == CPOINTER || \
DCL_TYPE(x) == UPOINTER ))
#define IS_PTR_CONST(x) (IS_PTR(x) && DCL_PTR_CONST(x))
+#define IS_PTR_RESTRICT(x) (IS_PTR(x) && DCL_PTR_RESTRICT(x))
#define IS_FARPTR(x) (IS_DECL(x) && DCL_TYPE(x) == FPOINTER)
#define IS_CODEPTR(x) (IS_DECL(x) && DCL_TYPE(x) == CPOINTER)
#define IS_GENPTR(x) (IS_DECL(x) && DCL_TYPE(x) == GPOINTER)
#define IS_FUNCPTR(x) (IS_DECL(x) && (DCL_TYPE(x) == CPOINTER || DCL_TYPE(x) == GPOINTER) && IS_FUNC(x->next))
#define IS_FUNC(x) (IS_DECL(x) && DCL_TYPE(x) == FUNCTION)
-#define IS_LONG(x) (IS_SPEC(x) && x->select.s._long)
-#define IS_UNSIGNED(x) (IS_SPEC(x) && x->select.s._unsigned)
-#define IS_TYPEDEF(x)(IS_SPEC(x) && x->select.s._typedef)
+#define IS_LONG(x) (IS_SPEC(x) && x->select.s.b_long)
+#define IS_UNSIGNED(x) (IS_SPEC(x) && x->select.s.b_unsigned)
+#define IS_TYPEDEF(x)(IS_SPEC(x) && x->select.s.b_typedef)
#define IS_CONSTANT(x) (!x ? 0 : \
IS_SPEC(x) ? \
- x->select.s._const : \
+ x->select.s.b_const : \
x->select.d.ptr_const)
#define IS_STRUCT(x) (IS_SPEC(x) && x->select.s.noun == V_STRUCT)
-#define IS_ABSOLUTE(x) (IS_SPEC(x) && x->select.s._absadr )
+#define IS_ABSOLUTE(x) (IS_SPEC(x) && x->select.s.b_absadr )
#define IS_REGISTER(x) (IS_SPEC(x) && SPEC_SCLS(x) == S_REGISTER)
#define IS_RENT(x) (IS_SPEC(x) && x->select.s._reent )
#define IS_STATIC(x) (IS_SPEC(x) && SPEC_STAT(x))
+#define IS_INLINE(x) (IS_SPEC(x) && SPEC_INLINE(x))
#define IS_INT(x) (IS_SPEC(x) && x->select.s.noun == V_INT)
#define IS_VOID(x) (IS_SPEC(x) && x->select.s.noun == V_VOID)
#define IS_CHAR(x) (IS_SPEC(x) && x->select.s.noun == V_CHAR)
-#define IS_EXTERN(x) (IS_SPEC(x) && x->select.s._extern)
+#define IS_EXTERN(x) (IS_SPEC(x) && x->select.s.b_extern)
#define IS_VOLATILE(x) (!x ? 0 : \
IS_SPEC(x) ? \
- x->select.s._volatile : \
+ x->select.s.b_volatile : \
x->select.d.ptr_volatile)
#define IS_INTEGRAL(x) (IS_SPEC(x) && (x->select.s.noun == V_INT || \
x->select.s.noun == V_CHAR || \
x->select.s.noun == V_SBIT ))
#define IS_BITFIELD(x) (IS_SPEC(x) && (x->select.s.noun == V_BITFIELD))
#define IS_BITVAR(x) (IS_SPEC(x) && (x->select.s.noun == V_BITFIELD || \
- x->select.s.noun == V_BIT || \
+ 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 ))
extern symbol *__fps16x16_gt;
extern symbol *__fps16x16_gteq;
-/* Dims: mul/div/mod, BYTE/WORD/DWORD, SIGNED/UNSIGNED */
-extern symbol *__muldiv[3][3][2];
+/* Dims: mul/div/mod, BYTE/WORD/DWORD, SIGNED/UNSIGNED/BOTH */
+extern symbol *__muldiv[3][3][4];
/* Dims: BYTE/WORD/DWORD SIGNED/UNSIGNED */
extern sym_link *__multypes[3][2];
/* Dims: to/from float, BYTE/WORD/DWORD, SIGNED/USIGNED */
RESULT_TYPE_INT,
RESULT_TYPE_OTHER, /* operands will be promoted to int */
RESULT_TYPE_IFX,
+ RESULT_TYPE_GPTR, /* operands will be promoted to generic ptr */
} RESULT_TYPE;
/* forward definitions for the symbol table related functions */
void printStruct (structdef *, int);
char *genSymName (int);
sym_link *getSpec (sym_link *);
-char *genSymName (int);
int compStructSize (int, structdef *);
sym_link *copyLinkChain (sym_link *);
int checkDecl (symbol *, int);
value *checkArrayIval (sym_link *, value *);
value *checkIval (sym_link *, value *);
unsigned int getSize (sym_link *);
-unsigned int getAllocSize (sym_link *);
unsigned int bitsForType (sym_link *);
sym_link *newIntLink ();
sym_link *newCharLink ();
sym_link *structElemType (sym_link *, value *);
symbol *getStructElement (structdef *, symbol *);
sym_link *computeType (sym_link *, sym_link *, RESULT_TYPE, int);
+void processFuncPtrArgs (sym_link *);
void processFuncArgs (symbol *);
int isSymbolEqual (symbol *, symbol *);
-int powof2 (TYPE_UDWORD);
+int powof2 (TYPE_TARGET_ULONG);
+void dbuf_printTypeChain (sym_link *, struct dbuf_s *);
void printTypeChain (sym_link *, FILE *);
void printTypeChainRaw (sym_link *, FILE *);
void initCSupport ();