/* Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it would be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, this software is distributed without any warranty that it is free of the rightful claim of any third person regarding infringement or the like. Any license provided herein, whether implied or otherwise, applies only to this software file. Patent licenses, if any, provided herein do not apply to combinations of this program with other software, or any other product whatsoever. You should have received a copy of the GNU General Public License along with this program; if not, write the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, Mountain View, CA 94043, or: http://www.sgi.com For further information regarding this notice, see: http://oss.sgi.com/projects/GenInfo/NoticeExplan */ /* -*-Mode: c++;-*- (Tell emacs to use c++ mode) */ #ifndef symtab_defs_INCLUDED #define symtab_defs_INCLUDED // Note: // // The comments in this file are intentionally brief. For detail description, // please refer to the "WHIRL Symbol Table Specification", which is the only // document actively maintained. enum ST_CLASS { CLASS_UNK = 0, CLASS_VAR = 1, // data variable CLASS_FUNC = 2, // addrress of a function. CLASS_CONST = 3, // constant value CLASS_PREG = 4, // pseudo register CLASS_BLOCK = 5, // base to a block of data CLASS_NAME = 6, // just hold an ST name CLASS_COUNT = 7 // total number of classes }; // ST_CLASS enum ST_SCLASS { // the values should not overlap with those in ST_CLASS for error checking SCLASS_UNKNOWN = 0, SCLASS_AUTO = 1, // stack variable SCLASS_FORMAL = 2, // formal parameter SCLASS_FORMAL_REF = 3, // reference parameter SCLASS_PSTATIC = 4, // PU scope static data SCLASS_FSTATIC = 5, // file scope static data SCLASS_COMMON = 6, // common block (linker allocated) SCLASS_EXTERN = 7, // unallocated external data or text SCLASS_UGLOBAL = 8, // uninitialized global data SCLASS_DGLOBAL = 9, // initialized global data SCLASS_TEXT = 10, // executable code SCLASS_REG = 11, // register variable SCLASS_CPLINIT = 12, // cplinit SCLASS_EH_REGION = 13, // eh region SCLASS_EH_REGION_SUPP = 14, // eh region supp SCLASS_DISTR_ARRAY = 15, // distributed array SCLASS_COMMENT = 16, // comment section SCLASS_THREAD_PRIVATE_FUNCS = 17, // thread-private constr/destr funcs SCLASS_COUNT = 18 // total number of classes }; // ST_SCLASS enum ST_EXPORT { EXPORT_LOCAL = 0, // Not exported, e.g. C static EXPORT_LOCAL_INTERNAL = 1, // Statics that do not have address // passed outside of a.out/DSO. EXPORT_INTERNAL = 2, // Exported, only visible and used // within the containing // DSO/executable, i.e. not even // passed outside using a pointer. EXPORT_HIDDEN = 3, // Exported, but name is hidden // within the containing // DSO/executable. However, the // address may be exported from the // DSO via a pointer. EXPORT_PROTECTED = 4, // Exported from DSO, but // non-preemptible. EXPORT_PREEMPTIBLE = 5, // Exported and preemptible. EXPORT_OPTIONAL = 6, // STO_OPTIONAL case in "sys/elf.h" EXPORT_COUNT = 7 // Must be last for consistency // checking }; // ST_EXPORT enum ST_FLAGS { ST_IS_WEAK_SYMBOL = 0x00000001, // Weak external name ST_IS_SPLIT_COMMON = 0x00000002, // part of a splitted common ST_IS_NOT_USED = 0x00000004, // Symbol is not referenced ST_IS_INITIALIZED = 0x00000008, // Symbol is initialized ST_IS_RETURN_VAR = 0x00000010, // CLASS_VAR: Return value ST_IS_VALUE_PARM = 0x00000020, // CLASS_VAR: Value parm ST_PROMOTE_PARM = 0x00000040, // CLASS_VAR: Promote C formal ST_KEEP_NAME_W2F = 0x00000080, // CLASS_VAR: don't mangle name ST_IS_DATAPOOL = 0x00000100, // CLASS_VAR: represents datapool ST_IS_RESHAPED = 0x00000200, // lno may reshape the ST ST_EMIT_SYMBOL = 0x00000400, // emit the empty dummy symbol ST_HAS_NESTED_REF = 0x00000800, // has ref in nested pu ST_INIT_VALUE_ZERO = 0x00001000, // has initial value of zero ST_GPREL = 0x00002000, // force object to be gp-rel ST_NOT_GPREL = 0x00004000, // force object to not be gp-rel ST_IS_NAMELIST = 0x00008000, // namelist table ST_IS_F90_TARGET = 0x00010000, // F90 target ST_DECLARED_STATIC = 0x00020000, // VMS formals declared static ST_IS_EQUIVALENCED = 0x00040000, // is part of an equivalence ST_IS_FILL_ALIGN = 0x00080000, // has fill/align pragma. ST_IS_OPTIONAL_ARGUMENT = 0x00100000, // F90 OPTIONAL arguments ST_PT_TO_UNIQUE_MEM = 0x00200000, // a pointer that is not aliased ST_IS_TEMP_VAR = 0x00400000, // compiler generated temp. variable ST_IS_CONST_VAR = 0x00800000, // read-only variable ST_ADDR_SAVED = 0x01000000, // address saved ST_ADDR_PASSED = 0x02000000, // address passed ST_IS_THREAD_PRIVATE = 0x04000000, // Symbol is allocated in XLOCAL // data segment ST_PT_TO_COMPILER_GENERATED_MEM = 0x08000000, // a pointer to compiler- // allocated memory space ST_IS_SHARED_AUTO = 0x10000000, // SCLASS_AUTO and accessed with // SHARED scope in an MP region ST_ASSIGNED_TO_DEDICATED_PREG = 0x20000000, // assigned to dedicated preg // specified in offset ST_ASM_FUNCTION_ST = 0x40000000, // ST is CLASS_NAME asm string with // file scope. ST_HAS_NAMED_SECTION = 0x80000000 // has named section attribute // new flags must go into flags_ext field. }; // ST_FLAGS // symbol table element class ST { public: union { STR_IDX name_idx; // index to the name string TCON_IDX tcon; // constant value } u1; mUINT32 flags; // misc. attributes mUINT8 flags_ext; // more attributes ST_CLASS sym_class : 8; // class info ST_SCLASS storage_class : 8; // storage info ST_EXPORT export_class : 8; // export class of the symbol union { TY_IDX type; // idx to high-level type PU_IDX pu; // idx to program unit table BLK_IDX blk; // idx to block table } u2; mUINT64 offset; // offset from base ST_IDX base_idx; // base of the allocated block ST_IDX st_idx; // my own st_idx // operations ST () {Fail_FmtAssertion("ST default constructor must not be called.");} void Verify(UINT level) const; void Print(FILE *f, BOOL verbose = TRUE) const; }; // ST // Give information about a field in a struct. The TY of the struct type // points to the FLD entry for the first field. The remaining fields // follow in consecutive FLD entries, until a flag indicates it is the last // field. enum FLD_FLAGS { FLD_LAST_FIELD = 0x0001, // last field in a struct FLD_EQUIVALENCE = 0x0002, // fortran equivalence FLD_BEGIN_UNION = 0x0004, // begin a union FLD_END_UNION = 0x0008, // end a union FLD_BEGIN_MAP = 0x0010, // begin a map (fortran) FLD_END_MAP = 0x0020, // end a map FLD_IS_BIT_FIELD = 0x0040 // is bit field }; struct FLD { STR_IDX name_idx; TY_IDX type; mUINT64 ofst; // offset within the struct in bytes mUINT8 bsize; // bit field size in bits mUINT8 bofst; // bit field offset starting at // byte specified by ofst mUINT16 flags; // misc. attributes ST_IDX st; // used if an st exists for this fld mUINT64 adjusted_ofst; //field offset after account for the size //of ptrs to shared TY_IDX orig_type; // original type for ptr-to-shared, used for debug // operations FLD (); void Verify (UINT64 record_size) const; void Print (FILE *f) const; }; // FLD typedef TY_IDX TYLIST; // for now, it's just a list of TY_IDX // Give information about a dimension of an array. The TY of the array type // points to the ARB entry for the first dimension. The remaining dimensions // follow in consecutive ARB entries until a flag indicates it is the last // dimension. enum ARB_FLAGS { ARB_CONST_LBND = 0x0001, // constant lower bound ARB_CONST_UBND = 0x0002, // constant upper bound ARB_CONST_STRIDE = 0x0004, // constant stride ARB_FIRST_DIMEN = 0x0008, // first dimension ARB_LAST_DIMEN = 0x0010 // last dimension }; struct ARB { mUINT16 flags; // misc. attributes mUINT16 dimension; // number of dimensions mUINT32 unused; // must be zero'ed union { mINT64 lbnd_val; // constant lower bound value struct { ST_IDX lbnd_var; // variable that stores the // non-constant lower bound mINT32 unused; // filler, must be zero'ed } var; } u1; union { mINT64 ubnd_val; // constant upper bound value struct { ST_IDX ubnd_var; // variable that stores the // non-constant upper bound mINT32 unused; // filler, must be zero'ed } var; } u2; union { mINT64 stride_val; // constant stride struct { ST_IDX stride_var; // variable that stores the // non-constant stride mINT32 unused; // filler, must be zero'ed } var; } u3; // access functions INT64 Lbnd_val () const { return u1.lbnd_val; } void Set_lbnd_val (INT64 val) { u1.lbnd_val = val; } ST_IDX Lbnd_var () const { return u1.var.lbnd_var; } void Set_lbnd_var (ST_IDX st) { u1.var.lbnd_var = st; u1.var.unused = 0; } INT64 Ubnd_val () const { return u2.ubnd_val; } void Set_ubnd_val (INT64 val) { u2.ubnd_val = val; } ST_IDX Ubnd_var () const { return u2.var.ubnd_var; } void Set_ubnd_var (ST_IDX st) { u2.var.ubnd_var = st; u2.var.unused = 0; } INT64 Stride_val () const { return u3.stride_val; } void Set_stride_val (INT64 val) { u3.stride_val = val; } ST_IDX Stride_var () const { return u3.var.stride_var; } void Set_stride_var (ST_IDX st) { u3.var.stride_var = st; u3.var.unused = 0; } // operations ARB () { memset(this, 0, sizeof(ARB)); } void Verify (mUINT16 dim) const; void Print (FILE *f) const; }; // ARB enum LABEL_KIND { LKIND_DEFAULT = 0, LKIND_ASSIGNED = 1, // in ASSIGNED statement LKIND_BEGIN_EH_RANGE = 2, LKIND_END_EH_RANGE = 3, LKIND_BEGIN_HANDLER = 4, LKIND_END_HANDLER = 5, LKIND_TAG = 6 // symbolic address, never branched to }; enum LABEL_FLAGS { LABEL_TARGET_OF_GOTO_OUTER_BLOCK = 1, LABEL_ADDR_SAVED = 2, LABEL_ADDR_PASSED = 4 }; struct LABEL { STR_IDX name_idx; mUINT32 flags:24; LABEL_KIND kind:8; // operations LABEL () {Fail_FmtAssertion("LABEL default constructor must not be called.");} LABEL (STR_IDX idx, LABEL_KIND k) : name_idx (idx), kind (k) {} void Verify(UINT level) const; void Print (FILE *f) const; }; // LABEL struct PREG { STR_IDX name_idx; // operations PREG(void) { Fail_FmtAssertion("PREG default constructor must not be called."); } PREG (STR_IDX idx) : name_idx (idx) { } void Verify(UINT level) const; void Print (FILE *f) const; }; // PREG // misc. ST attributes enum ST_ATTR_KIND { ST_ATTR_UNKNOWN = 0, ST_ATTR_DEDICATED_REGISTER = 1, // physical register number ST_ATTR_SECTION_NAME = 2, // name of sections where defined. ST_ATTR_FN_RET_TY_IDX = 3, ST_ATTR_FN_ARG_TY_IDX = 4 }; struct ST_ATTR { ST_IDX st_idx; ST_ATTR_KIND kind; union { mUINT32 value; // generic 32-bit value mPREG_NUM reg_id; STR_IDX section_name; } u; // operations ST_ATTR () { Fail_FmtAssertion("ST_ATTR default constructor must not be called."); } ST_ATTR (ST_IDX idx, ST_ATTR_KIND akind, UINT32 val) : st_idx (idx), kind (akind) { u.value = val; } void Verify (UINT level) const; void Print (FILE* f) const; }; // ST_ATTR /* Kinds of types: */ enum TY_KIND { KIND_INVALID = 0, // Invalid KIND_SCALAR = 1, // integer/floating point KIND_ARRAY = 2, // array KIND_STRUCT = 3, // struct/union KIND_POINTER = 4, // pointer KIND_FUNCTION = 5, // function/procedure KIND_VOID = 6, // C void type KIND_LAST = 8 }; enum TY_FLAGS { TY_IS_CHARACTER = 0x0001, /* type is a character (fortran) */ TY_IS_LOGICAL = 0x0002, /* Type is logical (fortran) */ TY_IS_UNION = 0x0004, /* Struct or class type is union */ TY_IS_PACKED = 0x0008, /* Struct or class type is packed */ TY_PTR_AS_ARRAY = 0x0010, /* Treat pointer as array */ TY_ANONYMOUS = 0x0020, /* Anonymous structs/classes/unions */ TY_SPLIT = 0x0040, /* Split from a larger common block * equivalence (block_split) */ TY_IS_F90_POINTER = 0x0080, /* If the type is an F90 pointer */ TY_NOT_IN_UNION = 0x0100, /* If the type cannot be part of a union */ TY_NO_ANSI_ALIAS = 0x0200, // ANSI alias rules don't applied TY_IS_NON_POD = 0x0400, // type is non pod (for C++ classes) TY_IS_SHARED = 0x0800, // UPC shared type TY_IS_STRICT = 0x1000, TY_IS_RELAXED = 0x2000, TY_IS_WRITTEN = 0x4000, //make w2c to output the type definition TY_USES_THREADS = 0x8000 //for ARRAY - dimension multiplied by THREADS }; // TY flags that are valid only for KIND_FUNCTION enum TY_PU_FLAGS { TY_RETURN_TO_PARAM = 0x00000001, // return value through first param TY_IS_VARARGS = 0x00000002, // variable number of arguments TY_HAS_PROTOTYPE = 0x00000004 // has ansi-style prototype }; #define UPC_INDEFINITE_BLOCK_SIZE -1 class TY { public: mUINT64 size; // size of the type in bytes TY_KIND kind : 8; // kind of type mTYPE_ID mtype : 8; // WHIRL data type mUINT16 flags; // misc. attributes union { FLD_IDX fld; TYLIST_IDX tylist; ARB_IDX arb; } u1; // idx to FLD_TAB, TYLIST_TAB, etc. STR_IDX name_idx; // name union { TY_IDX etype; // type of array element (array only) TY_IDX pointed; // pointed-to type (pointers only) mUINT32 pu_flags; // attributes for KIND_FUNCTION } u2; mUINT32 block_size; // block size for UPC shared data mUINT64 adjusted_size; // access function for unions FLD_IDX Fld () const { return u1.fld; } void Set_fld (FLD_IDX idx) { u1.fld = idx; } TYLIST_IDX Tylist () const { return u1.tylist; } void Set_tylist (TYLIST_IDX idx) { u1.tylist = idx; } ARB_IDX Arb () const { return u1.arb; } void Set_arb (ARB_IDX idx) { u1.arb = idx; } TY_IDX Etype () const { Is_True(kind == KIND_ARRAY, ("non-KIND_ARRAY type has no element type")); return u2.etype; } void Set_etype (TY_IDX idx) { u2.etype = idx; } TY_IDX Pointed () const { Is_True(kind == KIND_POINTER, ("non-KIND_POINTER type doesn't point")); return u2.pointed; } void Set_pointed (TY_IDX idx) { u2.pointed = idx; } PU_IDX Pu_flags () const { return u2.pu_flags; } void Set_pu_flag (TY_PU_FLAGS f) { u2.pu_flags |= f; } void Clear_pu_flag (TY_PU_FLAGS f) { u2.pu_flags &= ~f; } // operations TY (); void Verify(UINT level) const; void Print (FILE *f) const; }; // TY // PU_FLAGS: cannot use enum as some of the the values are > max unsigned int #define PU_IS_PURE 0x00000001 // pure function #define PU_NO_SIDE_EFFECTS 0x00000002 // no side effect #define PU_IS_INLINE_FUNCTION 0x00000004 // inline keyword specified #define PU_NO_INLINE 0x00000008 // noinline pragma specified #define PU_MUST_INLINE 0x00000010 // must inline #define PU_NO_DELETE 0x00000020 // nodelete pragma specified #define PU_HAS_EXC_SCOPES 0x00000040 // has eh regions, or would have // if exceptions were enabled #define PU_IS_NESTED_FUNC 0x00000080 // is a nested function #define PU_HAS_NON_MANGLED_CALL 0x00000100 // PU has a call in which no // reshaped arrays are passed #define PU_ARGS_ALIASED 0x00000200 // f77 arguments are aliased #define PU_NEEDS_FILL_ALIGN_LOWERING 0x00000400 // needs fill/align lowering #define PU_NEEDS_T9 0x00000800 // needs T9 #define PU_HAS_VERY_HIGH_WHIRL 0x00001000 // PU has very high whirl in it #define PU_HAS_ALTENTRY 0x00002000 // PU has alternate entries #define PU_RECURSIVE 0x00004000 // in recursive path #define PU_IS_MAINPU 0x00008000 // is entry point of program #define PU_UPLEVEL 0x00010000 // Other PU nested in this one #define PU_MP_NEEDS_LNO 0x00020000 // PU needs LNO processing #define PU_HAS_ALLOCA 0x00040000 // PU has alloca in it #define PU_IN_ELF_SECTION 0x00080000 // PU is in its own Elf section #define PU_HAS_MP 0x00100000 // Symtab has MP region/do within it #define PU_MP 0x00200000 // PU is an MP region/do #define PU_HAS_NAMELIST 0x00400000 // PU has namelist #define PU_HAS_RETURN_ADDRESS 0x00800000 // __return_address was used #define PU_HAS_REGION 0x01000000 // PU has regions in it #define PU_HAS_INLINES 0x02000000 // PU has inlined code in it #define PU_CALLS_SETJMP 0x04000000 // PU has calls to setjmp(2) #define PU_CALLS_LONGJMP 0x08000000 // PU has calls to longjmp(2) #define PU_IPA_ADDR_ANALYSIS 0x10000000 // IPA has done address analysis #define PU_SMART_ADDR_ANALYSIS 0x20000000 // Unnecessary addr flags are reset #define PU_HAS_SYSCALL_LINKAGE 0x40000000 // preserve input regs #define PU_HAS_GLOBAL_PRAGMAS 0x80000000 // PU is a dummy pu with global // pragmas #define PU_HAS_USER_ALLOCA 0x0000000100000000LL // PU has user alloca in it #define PU_HAS_UNKNOWN_CONTROL_FLOW 0x0000000200000000LL // PU has unknown control flow // which disables tail call // optimization #define PU_IS_THUNK 0x0000000400000000LL // pu is a C++ thunk enum PU_SRC_LANG_FLAGS { PU_UNKNOWN_LANG = 0x00, // UNKNOWN PU_MIXED_LANG = 0x01, // MIXED PU_C_LANG = 0x02, // C PU_CXX_LANG = 0x04, // C++ PU_F77_LANG = 0x08, // F77 PU_F90_LANG = 0x10, // F90 PU_JAVA_LANG = 0x20 // JAVA }; struct PU { TARGET_INFO_IDX target_idx; // idx to table for target-specific // information TY_IDX prototype; // function prototype SYMTAB_IDX lexical_level; // lexical level (of nested proc). mUINT8 gp_group; // gp_group id mUINT8 src_lang; // source language // TODO: can put flags in 40-bit unused field and remove 64-bit flag field. // TODO: do this when can make incompatible change. mUINT64 unused : 40; // for alignment for flags mUINT64 flags; // misc. attributes about this func. // operations PU (); void Verify(UINT level) const; void Print (FILE *f) const; }; // PU // BLK only exists for CLASS_BLOCK. // It is used for data layout in be. // Only reason it is not local to be is that // the IPA global symbol table will need the info. class BLK { private: mUINT64 size; // size of the block mUINT16 align; // alignment of the block: 1,2,4,8 mUINT16 flags; // block flags mUINT16 section_idx; // section index (0 if not a section) mUINT16 scninfo_idx; // scninfo_idx (0 if not a section) public: BLK () : size (0), section_idx(0), scninfo_idx(0), flags (0) {} void Init (void) { memset (this, 0, sizeof(BLK));} public: // access functions UINT64 Size () const { return size; } void Set_size (UINT64 s) { size = s; } UINT16 Align () const { return align; } void Set_align (UINT16 s) { align = s; } UINT16 Section_idx () const { return section_idx; } void Set_section_idx (UINT16 s) { section_idx = s; } UINT16 Scninfo_idx () const { return scninfo_idx; } void Set_scninfo_idx (UINT16 s) { scninfo_idx = s; } UINT16 Flags () const { return flags; } BOOL Is_set (UINT16 f) const { return flags & f; } void Set_flags (UINT16 f) { flags |= f; } void Clear_flags (UINT16 f) { flags &= ~f; } void Clear_all_flags () { flags = 0; } void Print (FILE *f) const; }; // BLK // BLK flags #define BLK_SECTION 0x0001 // block for elf section #define BLK_ROOT_BASE 0x0002 // block should not be merged #define BLK_IS_BASEREG 0x0004 // block that maps into reg #define BLK_DECREMENT 0x0008 // grow block by decrementing #define BLK_EXEC 0x0010 // (ELF) executable instructions #define BLK_NOBITS 0x0020 // (ELF) occupies no space in file #define BLK_MERGE 0x0040 // (ELF) merge duplicates in ld #define BLK_COMPILER_LAYOUT 0x0080 // children symbols are not connected // place holder for misc. file-level info enum FILE_INFO_FLAGS { FI_IPA = 0x1, // IPA generated file FI_NEEDS_LNO = 0x2, // needs to run LNO FI_HAS_INLINES = 0x4, // some PUs have PU_HAS_INLINES set FI_HAS_MP = 0x8 // need to process MP constructs }; struct FILE_INFO { mUINT32 flags; // misc. attributes mUINT8 gp_group; // gp group id mUINT32 unused : 24; // filler, must be zero void Verify() const; void Print (FILE *f) const; FILE_INFO () : flags (0), gp_group (0), unused (0) {} }; // Type definitions of the symbol tables typedef SEGMENTED_ARRAY PU_TAB; typedef RELATED_SEGMENTED_ARRAY ST_TAB; typedef SEGMENTED_ARRAY TY_TAB; typedef SEGMENTED_ARRAY FLD_TAB; typedef SEGMENTED_ARRAY TYLIST_TAB; typedef SEGMENTED_ARRAY ARB_TAB; typedef RELATED_SEGMENTED_ARRAY