jwasm/H/symbols.h
2014-06-18 19:16:56 +04:00

538 lines
23 KiB
C

/****************************************************************************
*
* 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