sdcc-gas/src/SDCCsymt.h

735 lines
36 KiB
C

/*-------------------------------------------------------------------------
SDCCsymt.h - Header file for Symbols table related structures and MACRO's.
Copyright (C) 1998 Sandeep Dutta . sandeep.dutta@usa.net
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-------------------------------------------------------------------------*/
#ifndef SDCCSYMT_H
#define SDCCSYMT_H
#define MAX_NEST_LEVEL 256
#define SDCC_SYMNAME_MAX 64
#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_TRAP INTNO_MAX
#define INTNO_UNSPEC (INTNO_MAX+1) /* interrupt number unspecified */
#define BITVAR_PAD -1
enum
{
TYPEOF_INT = 1,
TYPEOF_SHORT,
TYPEOF_BOOL,
TYPEOF_CHAR,
TYPEOF_LONG,
TYPEOF_LONGLONG,
TYPEOF_FLOAT,
TYPEOF_FIXED16X16,
TYPEOF_BIT,
TYPEOF_BITFIELD,
TYPEOF_SBIT,
TYPEOF_SFR,
TYPEOF_VOID,
TYPEOF_STRUCT,
TYPEOF_ARRAY,
TYPEOF_FUNCTION,
TYPEOF_POINTER,
TYPEOF_FPOINTER,
TYPEOF_CPOINTER,
TYPEOF_GPOINTER,
TYPEOF_PPOINTER,
TYPEOF_IPOINTER,
TYPEOF_EEPPOINTER
};
// 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
/* hash table bucket */
typedef struct bucket
{
void *sym; /* pointer to the object */
char name[SDCC_NAME_MAX + 1]; /* name of this symbol */
long level; /* nest level for this symbol */
int block; /* belongs to which block */
struct bucket *prev; /* ptr 2 previous bucket */
struct bucket *next; /* ptr 2 next bucket */
}
bucket;
typedef struct structdef
{
char tag[SDCC_NAME_MAX + 1]; /* tag part of structure */
long level; /* Nesting level */
int block; /* belongs to which block */
struct symbol *fields; /* pointer to fields */
unsigned size; /* sizeof the table in bytes */
int type; /* STRUCT or UNION */
bool b_flexArrayMember; /* has got a flexible array member,
only needed for syntax checks */
struct symbol *tagsym; /* tag symbol (NULL if no tag) */
}
structdef;
/* noun definitions */
typedef enum
{
V_INT = 1,
V_FLOAT,
V_FIXED16X16,
V_BOOL,
V_CHAR,
V_VOID,
V_STRUCT,
V_LABEL,
V_BIT,
V_BITFIELD,
V_BBITFIELD,
V_SBIT,
V_DOUBLE
}
NOUN;
/* storage class */
typedef enum
{
S_FIXED = 0,
S_AUTO,
S_REGISTER,
S_SFR,
S_SBIT,
S_CODE,
S_XDATA,
S_DATA,
S_IDATA,
S_PDATA,
S_LITERAL,
S_STACK,
S_XSTACK,
S_BIT,
S_EEPROM
}
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
#define TYPE_TARGET_LONGLONG TYPE_QWORD
#define TYPE_TARGET_ULONGLONG TYPE_UQWORD
/* 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 b_long:1; /* 1=long */
unsigned b_longlong:1; /* 1=long 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*/
bool b_implicit_sign:1; /* signedness not explicitly specified - needed to keep char a separate type from signed char and unsigned char. */
unsigned b_static:1; /* 1=static keyword found */
unsigned b_extern:1; /* 1=extern found */
unsigned b_inline:1; /* inline function requested */
unsigned b_noreturn:1; /* promised not to return */
unsigned b_alignas:1; /* alignment */
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 */
struct symbol *addrspace; /* is in named address space */
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 b_needspar:1; /* has to be a parameter */
unsigned _bitStart; /* bit start position */
unsigned _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_TARGET_INT v_int; /* 2 bytes: int and char values */
const char *v_char; /* char character string */
const TYPE_TARGET_UINT *v_char16; /* char16_t character string */
const TYPE_TARGET_ULONG *v_char32;/* char32_t 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 */
TYPE_TARGET_LONGLONG v_longlong; /* 8 bytes: long long constant value */
TYPE_TARGET_ULONGLONG v_ulonglong;/* 8 bytes: unsigned long long const value */
double v_float; /* floating point constant value */
TYPE_TARGET_ULONG v_fixed16x16; /* 4 bytes: fixed point constant value */
struct symbol *v_enum; /* ptr to enum_list if enum==1 */
}
const_val;
struct structdef *v_struct; /* structure pointer */
}
specifier;
/* types of declarators */
typedef enum
{
UPOINTER = 0, /* unknown pointer used only when parsing */
POINTER, /* pointer to near data */
IPOINTER, /* pointer to upper 128 bytes */
PPOINTER, /* paged area pointer */
FPOINTER, /* pointer to far data */
CPOINTER, /* pointer to code space */
GPOINTER, /* generic pointer */
EEPPOINTER, /* pointer to eeprom */
ARRAY,
FUNCTION
}
DECLARATOR_TYPE;
typedef struct declarator
{
DECLARATOR_TYPE dcl_type; /* POINTER,ARRAY or FUNCTION */
size_t 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 symbol *ptr_addrspace; /* pointer is in named address space */
struct sym_link *tspec; /* pointer type specifier */
}
declarator;
typedef enum
{
DECLARATOR = 1,
SPECIFIER
} SYM_LINK_CLASS;
#define DECLSPEC2TXT(select) (select==DECLARATOR?"DECLARATOR":select==SPECIFIER?"SPECIFIER":"UNKNOWN")
typedef struct sym_link
{
SYM_LINK_CLASS xclass; /* DECLARATOR or SPECIFIER */
unsigned tdef:1; /* current link created by */
/* typedef if this flag is set */
union
{
specifier s; /* if CLASS == SPECIFIER */
declarator d; /* if CLASS == DECLARATOR */
} select;
/* function attributes */
struct
{
struct value *args; /* the defined arguments */
unsigned hasVargs:1; /* functions has varargs */
unsigned calleeSaves:1; /* functions uses callee save */
unsigned hasbody:1; /* function body defined */
unsigned hasFcall:1; /* does it call other functions */
unsigned reent:1; /* function is reentrant */
unsigned naked:1; /* naked function */
unsigned shadowregs:1; /* function uses shadow registers (pic16 port) */
unsigned wparam:1; /* first byte of arguments is passed via WREG (pic16 port) */
unsigned nonbanked:1; /* function has the nonbanked attribute */
unsigned banked:1; /* function has the banked attribute */
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 noreturn:1; /* promised not to return */
unsigned smallc:1; /* Parameters on stack are passed in reverse order */
unsigned z88dk_fastcall:1; /* For the z80-related ports: Function has a single paramter of at most 32 bits that is passed in dehl */
unsigned z88dk_callee:1; /* Stack pointer adjustment for parameters passed on the stack is done by the callee */
unsigned z88dk_shortcall:1; /* Short call available via rst (see values later) (Z80 only) */
unsigned z88dk_has_params_offset:1; /* Has a parameter offset (Z80 only) */
unsigned intno; /* Number of interrupt for interrupt service routine */
short regbank; /* register bank 2b used */
unsigned builtin; /* is a builtin function */
unsigned javaNative; /* is a JavaNative Function (TININative ONLY) */
unsigned overlay; /* force parameters & locals into overlay segment */
unsigned hasStackParms; /* function has parameters on stack */
bool preserved_regs[9]; /* Registers preserved by the function - may be an underestimate */
unsigned char z88dk_shortcall_rst; /* Rst for a short call */
unsigned short z88dk_shortcall_val; /* Value for a short call */
unsigned short z88dk_params_offset; /* Additional offset from for arguments */
} funcAttrs;
struct sym_link *next; /* next element on the chain */
}
sym_link;
typedef struct symbol
{
char name[SDCC_SYMNAME_MAX + 1]; /* Input Variable Name */
char rname[SDCC_NAME_MAX + 1]; /* internal name */
long level; /* declaration lev,fld offset */
short block; /* sequential block # of definition */
int seqPoint; /* sequence point defined or, if unbound, used */
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 islbl:1; /* is a temporary label */
unsigned isref:1; /* has been referenced */
unsigned isind:1; /* is an induction variable */
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 equivalent of a symbol */
unsigned udChked:1; /* use def checking has been already done */
unsigned generated:1; /* code generated (function symbols only) */
unsigned isinscope:1; /* is in scope */
/* following flags are used by the backend
for code generation and can be changed
if a better scheme for backend is thought of */
unsigned isLiveFcall:1; /* is live at or across a function call */
unsigned isspilt:1; /* has to be spilt */
unsigned spillA:1; /* spilt be register allocator */
unsigned remat:1; /* can be remateriazed */
unsigned isptr:1; /* is a pointer */
unsigned uptr:1; /* used as a pointer */
unsigned isFree:1; /* used by register allocator */
unsigned islocal:1; /* is a local variable */
unsigned blockSpil:1; /* spilt at block level */
unsigned remainSpil:1; /* spilt because not used in remainder */
unsigned stackSpil:1; /* has been spilt on temp stack location */
unsigned onStack:1; /* this symbol allocated on the stack */
unsigned iaccess:1; /* indirect access */
unsigned ruonly:1; /* used in return statement only */
unsigned spildir:1; /* spilt in direct space */
unsigned ptrreg:1; /* this symbol assigned to a ptr reg */
unsigned noSpilLoc:1; /* cannot be assigned a spil location */
bool funcDivFlagSafe:1; /* we know this function is safe to call with undocumented stm8 flag bit 6 set*/
bool funcUsesVolatile:1; /* The function accesses a volatile variable */
unsigned isstrlit; /* is a string literal and it's usage count */
unsigned accuse; /* can be left in the accumulator
On the Z80 accuse is divided into
ACCUSE_A and ACCUSE_HL as the idea
is quite similar.
*/
unsigned dptr; /* 8051 variants with multiple DPTRS
currently implemented in DS390 only
*/
int allocreq; /* allocation is required for this variable */
int stack; /* offset on stack */
int xstack; /* offset on xternal stack */
short nRegs; /* number of registers required */
short regType; /* type of register required */
struct reg_info *regs[8]; /* can have at the most 8 registers */
struct asmop *aop; /* asmoperand for this symbol */
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. substitution */
struct symbol *psbase; /* if pseudo symbol, the symbol it is based on */
union
{
struct symbol *spillLoc; /* register spil location */
struct set *itmpStack; /* symbols spilt @ this stack location */
}
usl;
int bitVar; /* if bitVar != 0: this is a bit variable, bitVar is the size in bits */
unsigned bitUnnamed:1; /* unnamed bit variable */
unsigned offset; /* offset from top if struct */
int lineDef; /* defined line number */
char *fileDef; /* defined filename */
int lastLine; /* for functions the last line */
struct sym_link *type; /* 1st link to declarator chain */
struct sym_link *etype; /* last link to declarator chain */
struct symbol *next; /* crosslink to next symbol */
struct symbol *localof; /* local variable of which function */
struct initList *ival; /* ptr to initializer if any */
struct bitVect *defs; /* bit vector for definitions */
struct bitVect *uses; /* bit vector for uses */
struct bitVect *regsUsed; /* for functions registers used */
int liveFrom; /* live from iCode sequence number */
int liveTo; /* live to sequence 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 */
struct symbol *addressmod[2]; /* access functions for named address spaces */
bool for_newralloc;
}
symbol;
extern sym_link *validateLink (sym_link * l,
const char *macro, const char *args, const char select, 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_PTR_ADDRSPACE(l) validateLink(l, "DCL_PTR_ADDRSPACE", #l, DECLARATOR, __FILE__, __LINE__)->select.d.ptr_addrspace
#define DCL_TSPEC(l) validateLink(l, "DCL_TSPEC", #l, DECLARATOR, __FILE__, __LINE__)->select.d.tspec
#define FUNC_DEBUG //assert(IS_FUNC(x));
#define FUNC_HASVARARGS(x) (x->funcAttrs.hasVargs)
#define IFFUNC_HASVARARGS(x) (IS_FUNC(x) && FUNC_HASVARARGS(x))
#define FUNC_ARGS(x) (x->funcAttrs.args)
#define IFFUNC_ARGS(x) (IS_FUNC(x) && FUNC_ARGS(x))
#define FUNC_HASFCALL(x) (x->funcAttrs.hasFcall)
#define IFFUNC_HASFCALL(x) (IS_FUNC(x) && FUNC_HASFCALL(x))
#define FUNC_HASBODY(x) (x->funcAttrs.hasbody)
#define IFFUNC_HASBODY(x) (IS_FUNC(x) && FUNC_HASBODY(x))
#define FUNC_CALLEESAVES(x) (x->funcAttrs.calleeSaves)
#define IFFUNC_CALLEESAVES(x) (IS_FUNC(x) && FUNC_CALLEESAVES(x))
#define FUNC_ISISR(x) (x->funcAttrs.intrtn)
#define IFFUNC_ISISR(x) (IS_FUNC(x) && FUNC_ISISR(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_ISNORETURN(x) (x->funcAttrs.noreturn)
#define IFFUNC_ISNORETURN(x) (IS_FUNC(x) && FUNC_ISNORETURN(x))
#define FUNC_ISREENT(x) (x->funcAttrs.reent)
#define IFFUNC_ISREENT(x) (IS_FUNC(x) && FUNC_ISREENT(x))
#define FUNC_ISSHADOWREGS(x) (x->funcAttrs.shadowregs)
#define IFFUNC_ISSHADOWREGS(x) (IS_FUNC(x) && FUNC_ISSHADOWREGS(x))
#define FUNC_ISWPARAM(x) (x->funcAttrs.wparam)
#define IFFUNC_ISWPARAM(x) (IS_FUNC(x) && FUNC_ISWPARAM(x))
#define FUNC_ISNAKED(x) (x->funcAttrs.naked)
#define IFFUNC_ISNAKED(x) (IS_FUNC(x) && FUNC_ISNAKED(x))
#define FUNC_NONBANKED(x) (x->funcAttrs.nonbanked)
#define IFFUNC_NONBANKED(x) (IS_FUNC(x) && FUNC_NONBANKED(x))
#define FUNC_BANKED(x) (x->funcAttrs.banked)
#define IFFUNC_BANKED(x) (IS_FUNC(x) && FUNC_BANKED(x))
#define FUNC_ISCRITICAL(x) (x->funcAttrs.critical)
#define IFFUNC_ISCRITICAL(x) (IS_FUNC(x) && FUNC_ISCRITICAL(x))
#define FUNC_ISBUILTIN(x) (x->funcAttrs.builtin)
#define IFFUNC_ISBUILTIN(x) (IS_FUNC(x) && FUNC_ISBUILTIN(x))
#define FUNC_ISJAVANATIVE(x) (x->funcAttrs.javaNative)
#define IFFUNC_ISJAVANATIVE(x) (IS_FUNC(x) && FUNC_ISJAVANATIVE(x))
#define FUNC_ISOVERLAY(x) (x->funcAttrs.overlay)
#define IFFUNC_ISOVERLAY(x) (IS_FUNC(x) && FUNC_ISOVERLAY(x))
#define FUNC_ISSMALLC(x) (x->funcAttrs.smallc)
#define IFFUNC_ISSMALLC(x) (IS_FUNC(x) && FUNC_ISSMALLC(x))
#define FUNC_ISZ88DK_FASTCALL(x) (x->funcAttrs.z88dk_fastcall)
#define IFFUNC_ISZ88DK_FASTCALL(x) (IS_FUNC(x) && FUNC_ISZ88DK_FASTCALL(x))
#define FUNC_ISZ88DK_CALLEE(x) (x->funcAttrs.z88dk_callee)
#define IFFUNC_ISZ88DK_CALLEE(x) (IS_FUNC(x) && FUNC_ISZ88DK_CALLEE(x))
#define FUNC_ISZ88DK_SHORTCALL(x) (x->funcAttrs.z88dk_shortcall)
#define IFFUNC_ISZ88DK_SHORTCALL(x) (IS_FUNC(x) && FUNC_ISZ88DK_SHORTCALL(x))
#define BANKED_FUNCTIONS ( options.model == MODEL_HUGE || \
( (options.model == MODEL_LARGE || options.model == MODEL_MEDIUM) && \
TARGET_Z80_LIKE ) )
#define IFFUNC_ISBANKEDCALL(x) ( IS_FUNC(x) && \
( FUNC_BANKED(x) || ( BANKED_FUNCTIONS && !FUNC_NONBANKED(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.b_long
#define SPEC_LONGLONG(x) validateLink(x, "SPEC_LONGLONG", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_longlong
#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_SIGN(x) validateLink(x, "SPEC_USIGN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_signed
#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.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.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.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_BUNNAMED", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_bitUnnamed
#define SPEC_NEEDSPAR(x) validateLink(x, "SPEC_NEEDSPAR", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_needspar
/* Sleaze: SPEC_ISR_SAVED_BANKS is only used on
* function type symbols, which obviously cannot
* be of BIT type. Therefore, we recycle the
* _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.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_ADDRSPACE(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.addrspace
#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.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
#define SPEC_NORETURN(x) validateLink(x, "SPEC_NORETURN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_noreturn
#define SPEC_ALIGNAS(x) validateLink(x, "SPEC_ALIGNAS", #x, SPECIFIER, __FILE__, __LINE__)->select.s.b_alignas
/* type check macros */
#define IS_DECL(x) ( x && x->xclass == DECLARATOR )
#define IS_SPEC(x) ( x && x->xclass == SPECIFIER )
#define IS_ARRAY(x) (IS_DECL(x) && DCL_TYPE(x) == ARRAY)
#define IS_DATA_PTR(x) (IS_DECL(x) && DCL_TYPE(x) == POINTER)
#define IS_SMALL_PTR(x) (IS_DECL(x) && (DCL_TYPE(x) == POINTER || \
DCL_TYPE(x) == IPOINTER || \
DCL_TYPE(x) == PPOINTER ))
#define IS_PTR(x) (IS_DECL(x) && (DCL_TYPE(x) == POINTER || \
DCL_TYPE(x) == FPOINTER || \
DCL_TYPE(x) == GPOINTER || \
DCL_TYPE(x) == IPOINTER || \
DCL_TYPE(x) == PPOINTER || \
DCL_TYPE(x) == EEPPOINTER || \
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.b_long)
#define IS_LONGLONG(x) (IS_SPEC(x) && x->select.s.b_longlong)
#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) (isConstant (x))
#define IS_RESTRICT(x) (isRestrict (x))
#define IS_STRUCT(x) (IS_SPEC(x) && x->select.s.noun == V_STRUCT)
#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_NORETURN(x) (IS_SPEC(x) && SPEC_NORETURN(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_BOOL(x) (IS_SPEC(x) && x->select.s.noun == V_BOOL)
#define IS_CHAR(x) (IS_SPEC(x) && x->select.s.noun == V_CHAR)
#define IS_EXTERN(x) (IS_SPEC(x) && x->select.s.b_extern)
#define IS_VOLATILE(x) (isVolatile (x))
#define IS_INTEGRAL(x) (IS_SPEC(x) && (x->select.s.noun == V_INT || \
x->select.s.noun == V_BOOL || \
x->select.s.noun == V_CHAR || \
x->select.s.noun == V_BITFIELD || \
x->select.s.noun == V_BBITFIELD || \
x->select.s.noun == V_BIT || \
x->select.s.noun == V_SBIT ))
#define IS_BITFIELD(x) (IS_SPEC(x) && (x->select.s.noun == V_BITFIELD || \
x->select.s.noun == V_BBITFIELD ))
#define IS_BITVAR(x) (IS_SPEC(x) && (x->select.s.noun == V_BITFIELD || \
x->select.s.noun == V_BBITFIELD || \
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_BOOLEAN(x) (IS_SPEC(x) && (x->select.s.noun == V_BIT || \
x->select.s.noun == V_SBIT || \
x->select.s.noun == V_BBITFIELD || \
x->select.s.noun == V_BOOL ))
#define IS_FLOAT(x) (IS_SPEC(x) && x->select.s.noun == V_FLOAT)
#define IS_FIXED16X16(x) (IS_SPEC(x) && x->select.s.noun == V_FIXED16X16)
#define IS_FIXED(x) (IS_FIXED16X16(x))
#define IS_ARITHMETIC(x) (IS_INTEGRAL(x) || IS_FLOAT(x) || IS_FIXED(x))
#define IS_AGGREGATE(x) (IS_ARRAY(x) || IS_STRUCT(x))
#define IS_LITERAL(x) (IS_SPEC(x) && x->select.s.sclass == S_LITERAL)
#define IS_CODE(x) (IS_SPEC(x) && SPEC_SCLS(x) == S_CODE)
#define IS_REGPARM(x) (IS_SPEC(x) && SPEC_REGPARM(x))
#define IS_VALID_PARAMETER_STORAGE_CLASS_SPEC(x) (!SPEC_TYPEDEF(x) && !SPEC_EXTR(x) && !SPEC_STAT(x) && SPEC_SCLS(x) != S_AUTO)
/* symbol check macros */
#define IS_AUTO(x) (x->level && !IS_STATIC(x->etype) && !IS_EXTERN(x->etype))
/* forward declaration for the global vars */
extern bucket *SymbolTab[];
extern bucket *StructTab[];
extern bucket *TypedefTab[];
extern bucket *LabelTab[];
extern bucket *enumTab[];
extern bucket *AddrspaceTab[];
extern symbol *fsadd;
extern symbol *fssub;
extern symbol *fsmul;
extern symbol *fsdiv;
extern symbol *fseq;
extern symbol *fsneq;
extern symbol *fslt;
extern symbol *fps16x16_add;
extern symbol *fps16x16_sub;
extern symbol *fps16x16_mul;
extern symbol *fps16x16_div;
extern symbol *fps16x16_eq;
extern symbol *fps16x16_neq;
extern symbol *fps16x16_lt;
extern symbol *fps16x16_lteq;
extern symbol *fps16x16_gt;
extern symbol *fps16x16_gteq;
/* Dims: mul/div/mod, BYTE/WORD/DWORD/QWORD, SIGNED/UNSIGNED/BOTH */
extern symbol *muldiv[3][4][4];
/* 16 x 16 -> 32 multiplication SIGNED/UNSIGNED */
extern symbol *muls16tos32[2];
/* Dims: BYTE/WORD/DWORD/QWORD SIGNED/UNSIGNED */
extern sym_link *multypes[4][2];
/* Dims: to/from float, BYTE/WORD/DWORD/QWORD, SIGNED/USIGNED */
extern symbol *conv[2][4][2];
/* Dims: to/from fixed16x16, BYTE/WORD/DWORD/QWORD/FLOAT, SIGNED/USIGNED */
extern symbol *fp16x16conv[2][5][2];
/* Dims: shift left/shift right, BYTE/WORD/DWORD/QWORD, SIGNED/UNSIGNED */
extern symbol *rlrr[2][4][2];
extern symbol *memcpy_builtin;
#define SCHARTYPE multypes[0][0]
#define UCHARTYPE multypes[0][1]
#define INTTYPE multypes[1][0]
#define UINTTYPE multypes[1][1]
#define LONGTYPE multypes[2][0]
#define ULONGTYPE multypes[2][1]
#define LONGLONGTYPE multypes[3][0]
#define ULONGLONGTYPE multypes[3][1]
extern sym_link *floatType;
extern sym_link *fixed16x16Type;
#include "SDCCval.h"
typedef enum
{
RESULT_TYPE_NONE = 0, /* operands will be promoted to int */
RESULT_TYPE_BOOL,
RESULT_TYPE_CHAR,
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 initSymt ();
symbol *newSymbol (const char *, long);
sym_link *newLink (SYM_LINK_CLASS);
sym_link *newFloatLink ();
structdef *newStruct (const char *);
void addDecl (symbol *, int, sym_link *);
sym_link *finalizeSpec (sym_link *);
sym_link *mergeSpec (sym_link *, sym_link *, const char *name);
sym_link *mergeDeclSpec (sym_link *, sym_link *, const char *name);
symbol *reverseSyms (symbol *);
sym_link *reverseLink (sym_link *);
symbol *copySymbol (const symbol *);
symbol *copySymbolChain (const symbol *);
void printSymChain (symbol *, int);
void printStruct (structdef *, int);
char *genSymName (long);
sym_link *getSpec (sym_link *);
int compStructSize (int, structdef *);
sym_link *copyLinkChain (const sym_link *);
int checkDecl (symbol *, int);
void checkBasic (sym_link *, sym_link *);
value *checkPointerIval (sym_link *, value *);
value *checkStructIval (symbol *, value *);
value *checkArrayIval (sym_link *, value *);
value *checkIval (sym_link *, value *);
unsigned int getSize (sym_link *);
unsigned int bitsForType (sym_link *);
sym_link *newIntLink ();
sym_link *newCharLink ();
sym_link *newLongLink ();
sym_link *newBoolLink ();
sym_link *newVoidLink ();
int compareType (sym_link *, sym_link *);
int compareTypeExact (sym_link *, sym_link *, long);
int compareTypeInexact (sym_link *, sym_link *);
int checkFunction (symbol *, symbol *);
void cleanUpLevel (bucket **, long);
void cleanUpBlock (bucket **, int);
symbol *getAddrspace (sym_link *type);
int funcInChain (sym_link *);
void addSymChain (symbol **);
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 (const symbol *, const symbol *);
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 ();
void initBuiltIns ();
void pointerTypes (sym_link *, sym_link *);
void cdbStructBlock (int);
void initHashT ();
bucket *newBucket ();
void addSym (bucket **, void *, char *, long, int, int checkType);
void deleteSym (bucket **, void *, const char *);
void *findSym (bucket **, void *, const char *);
void *findSymWithLevel (bucket **, struct symbol *);
void *findSymWithBlock (bucket **, struct symbol *, int, long);
void changePointer (sym_link * p);
void checkTypeSanity (sym_link * etype, const char *name);
sym_link *typeFromStr (const char *);
STORAGE_CLASS sclsFromPtr (sym_link * ptr);
sym_link *newEnumType (symbol *);
void promoteAnonStructs (int, structdef *);
int isConstant (sym_link * type);
int isVolatile (sym_link * type);
int isRestrict (sym_link * type);
value *aggregateToPointer (value *);
extern char *nounName (sym_link *); /* noun strings */
extern void printFromToType (sym_link *, sym_link *);
#endif