/**************************************************************************** * * Open Watcom Project * * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. * * ======================================================================== * * This file contains Original Code and/or Modifications of Original * Code as defined in and that are subject to the Sybase Open Watcom * Public License version 1.0 (the 'License'). You may not use this file * except in compliance with the License. BY USING THIS FILE YOU AGREE TO * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is * provided with the Original Code and Modifications, and is also * available at www.sybase.com/developer/opensource. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR * NON-INFRINGEMENT. Please see the License for the specific language * governing rights and limitations under the License. * * ======================================================================== * * Description: defines symbol structures asym and dsym, * and prototypes of functions in symbols.c. * This file is included by parser.h. * ****************************************************************************/ #ifndef _SYMBOLS_H_ #define _SYMBOLS_H_ /* * SYM_LIB - library paths are no longer added to the symbol table * SYM_LNAME has been removed. It was used for the null-entry in the LNAME table only * v2.01: SYM_PROC has been removed. * v2.01: SYM_LIB has been removed. */ enum sym_state { SYM_UNDEFINED, SYM_INTERNAL, /* 1 internal label */ SYM_EXTERNAL, /* 2 external */ SYM_SEG, /* 3 segment */ SYM_GRP, /* 4 group */ SYM_STACK, /* 5 stack variable - in local symbol tables only */ SYM_STRUCT_FIELD, /* 6 struct member - not in symbol table - except record fields */ SYM_TYPE, /* 7 structure, union, typedef, record */ SYM_ALIAS, /* 8 alias name */ SYM_MACRO, /* 9 macro */ SYM_TMACRO, /* 10 text macro */ SYM_CLASS_LNAME /* 11 lname item for segm class - not in symbol table */ }; /* v2.04: MT_SHORT removed */ /* v2.07: MT_ABS (0xC2) removed */ enum memtype { MT_SIZE_MASK = 0x1F, /* if MT_SPECIAL==0 then bits 0-4 = size - 1 */ MT_FLOAT = 0x20, /* bit 5=1 */ MT_SIGNED = 0x40, /* bit 6=1 */ MT_BYTE = 1 - 1, MT_SBYTE = MT_BYTE | MT_SIGNED, MT_WORD = 2 - 1, MT_SWORD = MT_WORD | MT_SIGNED, MT_DWORD = 4 - 1, MT_SDWORD= MT_DWORD | MT_SIGNED, MT_REAL4 = MT_DWORD | MT_FLOAT, MT_FWORD = 6 - 1, MT_QWORD = 8 - 1, MT_SQWORD= MT_QWORD | MT_SIGNED, MT_REAL8 = MT_QWORD | MT_FLOAT, MT_TBYTE = 10 - 1, MT_REAL10= MT_TBYTE | MT_FLOAT, MT_OWORD = 16 - 1, #if AVXSUPP MT_YMMWORD = 32 - 1, #endif MT_PROC = 0x80, /* symbol is a TYPEDEF PROTO, state=SYM_TYPE, typekind=TYPE_TYPEDEF, prototype is stored in target_type */ MT_NEAR = 0x81, MT_FAR = 0x82, MT_EMPTY = 0xC0, MT_BITS = 0xC1, /* record field */ MT_PTR = 0xC3, /* v2.05: changed, old value 0x83 */ MT_TYPE = 0xC4, /* symbol has user-defined type (struct, union, record) */ MT_SPECIAL = 0x80, /* bit 7 */ MT_SPECIAL_MASK = 0xC0, /* bit 6+7 */ MT_ADDRESS = 0x80, /* bit 7=1, bit 6 = 0 */ }; #define IS_SIGNED(x) (((x) & MT_SPECIAL_MASK) == MT_SIGNED) /* symbols can be * - "labels" (data or code, internal, external, stack) * mem_type is MT_BYTE..MT_OWORD, MT_NEAR, MT_FAR, MT_PTR * - constants (EQU) or assembly time variables ("="), * mem_type "usually" is MT_EMPTY. * - types (STRUCT, UNION, TYPEDEF, RECORD), mem_type = MT_TYPE * - preprocessor items (macros and text macros), which have no * mem_type (MT_EMPTY). */ struct macro_instance; typedef void (* internal_func)( struct asym *, void * ); struct debug_info { uint_32 start_line; /* procs's start line */ uint_32 end_line; /* procs's last line */ uint_32 ln_fileofs; /* file offset to line numbers */ uint_16 line_numbers;/* line numbers in function */ uint_16 file; /* proc's start file */ unsigned next_proc; /* index next proc */ unsigned next_file; /* index next file */ }; struct asym { /* v2.11: name changed from 'next' to 'nextitem' */ struct asym *nextitem; /* next symbol in hash line */ char *name; /* symbol name */ union { int_32 offset; /* used by SYM_INTERNAL (labels), SYM_TYPE, SYM_STACK, v2.11: SYM_SEG */ int_32 value; /* used by SYM_INTERNAL (equates) */ uint_32 uvalue; /* v2.01: equates (they are 33-bit!) */ char *string_ptr;/* used by SYM_TMACRO */ struct asym *substitute;/* v2.04b: used by SYM_ALIAS */ /* func_ptr: used by SYM_MACRO if predefined==1 */ ret_code (* func_ptr)( struct macro_instance *, char *, struct asm_tok * ); //int_32 max_offset; /* used by SYM_SEG; v2.11 field moved */ int_32 class_lname_idx;/* used by SYM_CLASS_LNAME */ }; struct asym *segment; /* used by SYM_INTERNAL, SYM_EXTERNAL */ enum sym_state state; enum memtype mem_type; unsigned char used:1, /* symbol has been referenced */ isdefined:1, /* symbol is "defined" in this pass */ scoped:1, /* symbol is local label or SYM_STACK */ /* v2.07: removed */ //isglobal:1, /* symbol has been added to the globals queue */ #if DLLIMPORT iat_used:1, /* v2.07: IAT entry of symbol used (SYM_EXTERNAL + isproc==1 only) */ #endif isequate:1, /* symbol has been defined with EQU */ predefined:1, /* symbol is predefined */ variable:1, /* symbol is variable (defined by '=' directive) */ ispublic:1; /* symbol has been added to the publics queue */ unsigned char list:1, /* symbol is to be listed */ isarray:1, /* symbol is an array (total_length is valid) */ isdata:1, /* field first_size is valid */ isproc:1, /* symbol is PROC or PROTO; has proc_info extension */ #if FASTPASS issaved:1, /* assembly-time variables only: symbol has been saved */ #endif //#if FASTMEM==0 /* v2.09: obsolete */ // isstatic:1, /* symbol stored in static memory */ //#endif fwdref:1, /* symbol was forward referenced */ included:1; /* COFF: static symbol added to public queue. ELF:symbol added to symbol table (SYM_INTERNAL) */ union { /* for SYM_INTERNAL (data labels, memtype != NEAR|FAR), SYM_STRUCT_FIELD */ uint_32 first_size; /* size of 1st initializer's dimension in bytes */ /* for SYM_INTERNAL (memtype == NEAR|FAR), * SYM_GRP (Ofssize), * SYM_EXTERNAL (Ofssize, comm, weak, isfar, is_ptr, ptr_memtype), * SYM_STACK (Ofssize, isfar, is_vararg, is_ptr, ptr_memtype ), * SYM_TYPE, TYPE_TYPEDEF (Ofssize, isfar, is_ptr, ptr_memtype ) */ struct { unsigned char Ofssize; /* offset size (USE16, USE32) */ unsigned char is_ptr; /* PTR indirection */ union { unsigned char ptr_memtype;/* pointer target type */ unsigned char asmpass; /* SYM_INTERNAL (mem_type NEAR|FAR) */ }; unsigned char seg_ofssize:2; /* SYM_EXTERNAL only */ unsigned char iscomm:1; /* is communal */ unsigned char weak:1; /* 1 if an unused "externdef" */ unsigned char isfar:1; /* SYM_EXTERNAL, SYM_TYPE, SYM_STACK */ unsigned char is_vararg:1;/* SYM_STACK, VARARG param */ }; /* for SYM_MACRO */ struct { unsigned char mac_vararg:1,/* accept additional params */ isfunc:1, /* it's a macro function */ #if MACROLABEL label:1, /* macro is "label-aware" */ #endif #if VARARGML mac_multiline:1, /* v2.11: vararg arguments may be on multiple lines */ #endif purged:1; /* macro has been PURGEd */ }; }; union { /* for SYM_INTERNAL (data labels only), SYM_STRUCT_FIELD */ uint_32 first_length; /* size of 1st initializer's dimension in item units */ /* SYM_TYPE (TYPEKIND_STRUCT or TYPEKIND_UNION) */ uint_32 max_mbr_size; /* max size members */ /* SYM_STACK, SYM_TYPE (TYPEKIND_TYPEDEF), SYM_EXTERNAL, SYM_INTERNAL (code labels) */ struct asym *target_type; /* set if ptr_memtype is MT_TYPE */ /* SYM_TMACRO (if it's a register variable for FASTCALL) */ uint_16 regist[2]; }; union { /* for SYM_INTERNAL, SYM_STRUCT_FIELD, * SYM_TYPE, SYM_STACK, * SYM_EXTERNAL (comm=1) * SYM_TMACRO: size of buffer allocated for the text in string_ptr */ uint_32 total_size; /* total number of bytes (sizeof) */ /* for SYM_INTERNAL, isequate=1 (numeric equates) */ int_32 value3264; /* high bits for equates */ #if DLLIMPORT struct dll_desc *dll; /* SYM_EXTERNAL (isproc=1) */ #endif /* for SYM_SEG; v2.11: moved here to make segment's offset field contain "local start offset" (=0) */ int_32 max_offset; }; union { /* SYM_INTERNAL, SYM_STRUCT_FIELD, * SYM_STACK, SYM_EXTERNAL (comm==1): * total number of elements (LENGTHOF) */ uint_32 total_length; struct asym *altname; /* SYM_EXTERNAL (comm==0): alternative name */ struct debug_info *debuginfo;/* SYM_INTERNAL (isproc==1): debug info (COFF) */ internal_func sfunc_ptr; /* SYM_INTERNAL+predefined */ struct { /* SYM_TYPE */ /* codeview type index (used after assembly steps) * v2.04: moved from first_length, were it didn't work anymore * since the addition of field max_mbr_size. */ uint_16 cvtyperef; uint_8 typekind; }; }; #if (MAX_ID_LEN <= 255) uint_8 name_size; #else uint_16 name_size; #endif enum lang_type langtype; #ifdef DEBUG_OUT union { struct asym *type; /* set if memtype is MT_TYPE */ struct dsym *ttype; /* for easier debugging */ }; #else struct asym *type; /* set if memtype is MT_TYPE */ #endif union { /* SYM_INTERNAL, SYM_UNDEFINED, SYM_EXTERNAL: backpatching fixup */ struct fixup *bp_fixup; /* for SYM_EXTERNAL */ unsigned ext_idx; /* table index ( for coff and elf ) */ struct { /* omf indices are 16-bit only! */ uint_16 ext_idx1; /* omf: (external definition) index */ uint_16 ext_idx2; /* omf: (external definition) index for weak external */ }; }; }; /*---------------------------------------------------------------------------*/ /* Structures for grpdef, segdef, externdef, pubdef, included library, */ /* procedure and symbolic integer constants. */ /*---------------------------------------------------------------------------*/ struct seg_item { struct seg_item *next; struct dsym *seg; }; struct grp_info { struct seg_item *seglist; /* list of segments in the group */ int grp_idx; /* its group index (OMF) */ int lname_idx; /* LNAME index (OMF only) */ unsigned numseg; /* OMF: number of segments in the group */ }; typedef uint_8 * (* FlushSegFunc)( struct dsym *, uint_8 *, unsigned, void * ); struct seg_info { struct asym *group; /* segment's group or NULL */ uint_32 start_loc; /* starting offset of current ledata or lidata */ union { uint_32 current_loc; /* current offset in current ledata or lidata */ uint_32 reloc_offset; /* ELF: reloc file offset */ uint_32 start_offset; /* BIN: start offset in group */ }; #ifdef __I86__ uint_8 huge *CodeBuffer; #else uint_8 *CodeBuffer; #endif uint_32 bytes_written; /* initialized bytes in segment */ union { struct asym *label_list; /* linked list of labels in this seg */ FlushSegFunc flushfunc; /* to flush the segment buffer */ }; struct { struct fixup *head; /* fixup queue head */ struct fixup *tail; /* fixup queue tail */ } FixupList; union { void *LinnumQueue; /* for COFF line numbers */ uint_32 fileoffset; /* used by BIN + ELF */ uint_32 num_linnums; /* used by COFF (after LinnumQueue has been read) */ }; uint_32 num_relocs; /* used by COFF/ELF */ unsigned seg_idx; /* segment #; v2.12: changed from short to unsigned */ enum seg_type segtype; /* segment's type (code, data, ...) */ int lname_idx; /* segment's name LNAME index (OMF only) */ struct asym *clsym; /* segment's class name (stored in an asym item) */ union { uint_16 abs_frame; /* ABS seg, frame number (OMF,BIN) */ #if COMDATSUPP uint_16 comdat_number; /* associated COMDAT segno (COFF) */ uint_16 comdat_idx; /* lname index of COMDAT symbol (OMF) */ #endif }; union { uint_32 abs_offset; /* ABS seg, offset (OMF only) */ char *aliasname; /* ALIAS name (COFF/ELF only) */ }; unsigned char Ofssize; /* segment's offset size */ unsigned char characteristics;/* used by COFF/ELF/PE */ unsigned char alignment; /* is value 2^x */ unsigned char readonly:1; /* if segment is readonly */ unsigned char info:1; /* if segment is info only (COFF/ELF) */ unsigned char force32:1; /* force 32bit segdef (OMF only) */ unsigned char data_in_code:1; /* data items in code segm (OMF only) */ unsigned char internal:1; /* internal segment with private buffer */ unsigned char written:1; /* code/data just written */ unsigned char linnum_init:1; /* v2.10: linnum data emitted for segment? */ unsigned char combine:3; /* combine type, see omfspec.h */ #if COMDATSUPP unsigned char comdat_selection:3; /* if > 0, it's a COMDAT (COFF/OMF) */ #endif }; #define MAX_SEGALIGNMENT 0xFF /* PROC item */ struct proc_info { uint_16 *regslist; /* PROC: list of registers to be saved */ struct dsym *paralist; /* list of parameters */ struct dsym *locallist; /* PROC: list of local variables */ struct dsym *labellist; /* PROC: list of local labels */ unsigned parasize; /* total no. of bytes used by parameters */ unsigned localsize; /* PROC: total no. of bytes used by local variables */ char *prologuearg; /* PROC: prologuearg attribute */ #if AMD64_SUPPORT struct asym *exc_handler; /* PROC: exc handler set by FRAME */ int ReservedStack; /* PROC: win64: additional reserved stack */ #endif uint_32 prolog_list_pos;/* PROC: prologue list pos */ union { unsigned char flags; struct { unsigned char has_vararg:1;/* last param is VARARG */ unsigned char pe_type:1; /* PROC: prolog-epilog type, 1=use LEAVE */ unsigned char isexport:1; /* PROC: EXPORT attribute set */ //unsigned char init_done:1; /* has ParseProc() been called? v2.11: obsolete */ unsigned char forceframe:1;/* PROC: FORCEFRAME prologuearg? */ unsigned char loadds:1; /* PROC: LOADDS prologuearg? */ unsigned char stackparam:1;/* PROC: 1=stack params exists ( not just register params ) */ #if AMD64_SUPPORT unsigned char isframe:1; /* PROC: FRAME attribute set? */ #endif #if STACKBASESUPP unsigned char fpo:1; #endif }; }; uint_8 size_prolog; /* PROC: v2.10: prologue size */ #if STACKBASESUPP uint_16 basereg; /* PROC: v2.11: stack base register */ #endif }; /* macro parameter */ struct mparm_list { //const char *label; /* name of parameter */ char *deflt; /* optional default parm */ unsigned char required:1; /* is parm required (REQ) */ }; /* macro line */ struct srcline { struct srcline *next; uint_8 ph_count; /* placeholders contained in this line */ char line[1]; }; /* macro item */ struct macro_info { uint_16 parmcnt; /* no of params */ union { uint_16 localcnt; /* no of locals */ uint_16 autoexp; /* auto-expansion flags if predefined macro */ }; struct mparm_list *parmlist; /* array of parameter items */ struct srcline *data; /* prepared macro source lines */ #ifdef DEBUG_OUT uint_32 count; /* no of times the macro was invoked */ #endif unsigned srcfile; /* sourcefile index */ }; /* STRUCT field */ struct sfield { struct asym sym; /* field symbol ( state=SYM_STRUCT_FIELD ) */ struct sfield *next; /* next field in STRUCT,UNION,RECORD */ //char *init_dir; /* v2.09: removed ; previously: not used by record fields */ char ivalue[1]; /* v2.09: type changed from char * to char[] */ }; enum type_kind { TYPE_NONE, TYPE_STRUCT, TYPE_UNION, TYPE_TYPEDEF, TYPE_RECORD }; struct struct_info { struct sfield *head; /* STRUCT/UNION/RECORD: start of field list */ struct sfield *tail; /* STRUCT/UNION/RECORD: current/next field */ /* v2.08: typekind moved to struct asym */ //#ifdef __WATCOMC__ // enum type_kind typekind; //#else // uint_8 typekind; //#endif uint_8 alignment; /* STRUCT: 1,2,4,8,16 or 32 */ union { uint_8 flags; struct { unsigned char isInline:1; /* STRUCT/UNION: inline (unused) */ unsigned char isOpen:1; /* STRUCT/UNION: set until the matching ENDS is found */ unsigned char OrgInside:1; /* STRUCT: struct contains an ORG */ }; }; }; /* dsym originally was a "directive_node" * However, currently all symbols except SYM_STRUCT_FIELDs are allocated as a dsym. * the additional 3 fields are used differently depending on symbol's type. */ struct dsym { struct asym sym; union { struct seg_info *seginfo; /* SYM_SEG (segments) */ struct grp_info *grpinfo; /* SYM_GRP (groups) */ struct proc_info *procinfo; /* SYM_INTERNAL|SYM_EXTERNAL (procs, isproc=1) */ struct struct_info *structinfo;/* SYM_TYPE (structs, unions, records [, typedefs]) */ struct macro_info *macroinfo; /* SYM_MACRO (macros) */ /* SYM_STACK, SYM_INTERNAL (code labels, isproc=0) * used to save the local hash table (contains PROC locals: params, * locals, labels). Details see SymGetLocal(), SymSetLocal() in symbols.c */ struct dsym *nextll; } e; /* next item in linked lists of certain symbol types. * - SYM_UNDEFINED -> TAB_UNDEF * - SYM_EXTERNAL -> TAB_EXT * - SYM_SEG -> TAB_SEG * - SYM_GRP -> TAB_GRP * - SYM_ALIAS: -> TAB_ALIAS * for SYM_INTERNAL: * linked list of labels for current segment (used for BackPatch) */ struct dsym *next; union { /* for SYM_UNDEFINED, SYM_EXTERNAL, SYM_ALIAS and SYM_GRP: * predecessor of current symbol with the same state, to allow fast removes. * Actually, the only symbols which may change the state and thus * have a chance to be removed are SYM_UNDEFINED and SYM_EXTERNAL ( weak=TRUE ) * during pass one. */ struct dsym *prev; /* used by PROC symbols (SYM_INTERNAL) for linked list, TAB_PROC */ struct dsym *nextproc; /* used by PROC locals (SYM_STACK) for linked list */ struct dsym *nextlocal; /* used by PROC params (SYM_STACK) for linked list */ struct dsym *nextparam; /* used by SYM_EXTERNAL (weak=FALSE) if altname is set */ /* v2.11: removed; member is in use for SYM_EXTERNAL */ //struct dsym *nextext; }; }; extern struct asym *SymAlloc( const char * ); extern void SymFree( struct asym * ); extern struct asym *SymCreate( const char * ); extern struct asym *SymLCreate( const char * ); extern struct asym *SymAddGlobal( struct asym * ); extern struct asym *SymAddLocal( struct asym *, const char * ); extern struct asym *SymLookup( const char * ); extern struct asym *SymLookupLocal( const char * ); extern struct asym *SymFind( const char *name ); #define SymSearch(x) SymFind(x) extern void SymInit( void ); extern void SymFini( void ); extern void SymPassInit( int pass ); extern void SymMakeAllSymbolsPublic( void ); extern void SymGetAll( struct asym ** ); extern struct asym *SymEnum( struct asym *, int * ); extern uint_32 SymGetCount( void ); #if defined(__WATCOMC__) typedef int (__watcall * StrCmpFunc)(const void *, const void *, size_t ); #else typedef int (* StrCmpFunc)(const void *, const void *, size_t ); #endif extern StrCmpFunc SymCmpFunc; extern void SymSetCmpFunc( void ); extern void SymClearLocal( void ); extern void SymSetLocal( struct asym * ); extern void SymGetLocal( struct asym * ); #endif