mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-22 22:53:13 +01:00
2308 lines
63 KiB
C
2308 lines
63 KiB
C
// Copyright (C) 1984-1998 by Symantec
|
||
// Copyright (C) 2000-2011 by Digital Mars
|
||
// All Rights Reserved
|
||
// http://www.digitalmars.com
|
||
// Written by Walter Bright
|
||
/*
|
||
* This source file is made available for personal use
|
||
* only. The license is in /dmd/src/dmd/backendlicense.txt
|
||
* or /dm/src/dmd/backendlicense.txt
|
||
* For any other uses, please contact Digital Mars.
|
||
*/
|
||
|
||
#if !SPP
|
||
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <time.h>
|
||
|
||
#include "cc.h"
|
||
#include "global.h"
|
||
#include "type.h"
|
||
#include "dt.h"
|
||
#if TX86
|
||
#include "cgcv.h"
|
||
#endif
|
||
|
||
#include "el.h"
|
||
#include "oper.h" /* for OPMAX */
|
||
#include "token.h"
|
||
|
||
#if SCPP
|
||
#include "parser.h"
|
||
#include "cpp.h"
|
||
#endif
|
||
|
||
static char __file__[] = __FILE__; /* for tassert.h */
|
||
#include "tassert.h"
|
||
|
||
//STATIC void symbol_undef(symbol *s);
|
||
STATIC void symbol_freemember(symbol *s);
|
||
STATIC void mptr_hydrate(mptr_t **);
|
||
STATIC void mptr_dehydrate(mptr_t **);
|
||
STATIC void baseclass_hydrate(baseclass_t **);
|
||
STATIC void baseclass_dehydrate(baseclass_t **);
|
||
|
||
/*********************************
|
||
* Allocate/free symbol table.
|
||
*/
|
||
|
||
symbol **symtab_realloc(symbol **tab, size_t symmax)
|
||
{ symbol **newtab;
|
||
|
||
if (config.flags2 & (CFG2phgen | CFG2phuse | CFG2phauto | CFG2phautoy))
|
||
{
|
||
newtab = (symbol **) MEM_PH_REALLOC(tab, symmax * sizeof(symbol *));
|
||
}
|
||
else
|
||
{
|
||
newtab = (symbol **) realloc(tab, symmax * sizeof(symbol *));
|
||
if (!newtab)
|
||
err_nomem();
|
||
}
|
||
return newtab;
|
||
}
|
||
|
||
symbol **symtab_malloc(size_t symmax)
|
||
{ symbol **newtab;
|
||
|
||
if (config.flags2 & (CFG2phgen | CFG2phuse | CFG2phauto | CFG2phautoy))
|
||
{
|
||
newtab = (symbol **) MEM_PH_MALLOC(symmax * sizeof(symbol *));
|
||
}
|
||
else
|
||
{
|
||
newtab = (symbol **) malloc(symmax * sizeof(symbol *));
|
||
if (!newtab)
|
||
err_nomem();
|
||
}
|
||
return newtab;
|
||
}
|
||
|
||
symbol **symtab_calloc(size_t symmax)
|
||
{ symbol **newtab;
|
||
|
||
if (config.flags2 & (CFG2phgen | CFG2phuse | CFG2phauto | CFG2phautoy))
|
||
{
|
||
newtab = (symbol **) MEM_PH_CALLOC(symmax * sizeof(symbol *));
|
||
}
|
||
else
|
||
{
|
||
newtab = (symbol **) calloc(symmax, sizeof(symbol *));
|
||
if (!newtab)
|
||
err_nomem();
|
||
}
|
||
return newtab;
|
||
}
|
||
|
||
void symtab_free(symbol **tab)
|
||
{
|
||
if (config.flags2 & (CFG2phgen | CFG2phuse | CFG2phauto | CFG2phautoy))
|
||
MEM_PH_FREE(tab);
|
||
else if (tab)
|
||
free(tab);
|
||
}
|
||
|
||
/*******************************
|
||
* Type out symbol information.
|
||
*/
|
||
|
||
#ifdef DEBUG
|
||
|
||
void symbol_print(symbol *s)
|
||
{
|
||
#if !SPP
|
||
if (!s) return;
|
||
dbg_printf("symbol %p '%s'\n ",s,s->Sident);
|
||
dbg_printf(" Sclass = "); WRclass((enum SC) s->Sclass);
|
||
dbg_printf(" Ssymnum = %d",s->Ssymnum);
|
||
dbg_printf(" Sfl = "); WRFL((enum FL) s->Sfl);
|
||
dbg_printf(" Sseg = %d\n",s->Sseg);
|
||
// dbg_printf(" Ssize = x%02x\n",s->Ssize);
|
||
dbg_printf(" Soffset = x%04llx",(unsigned long long)s->Soffset);
|
||
dbg_printf(" Sweight = %d",s->Sweight);
|
||
dbg_printf(" Sflags = x%04lx",(unsigned long)s->Sflags);
|
||
dbg_printf(" Sxtrnnum = %d\n",s->Sxtrnnum);
|
||
dbg_printf(" Stype = %p",s->Stype);
|
||
#if SCPP
|
||
dbg_printf(" Ssequence = %x", s->Ssequence);
|
||
dbg_printf(" Scover = %p", s->Scover);
|
||
#endif
|
||
dbg_printf(" Sl = %p",s->Sl);
|
||
dbg_printf(" Sr = %p\n",s->Sr);
|
||
#if SCPP
|
||
if (s->Sscope)
|
||
dbg_printf(" Sscope = '%s'\n",s->Sscope->Sident);
|
||
#endif
|
||
if (s->Stype)
|
||
type_print(s->Stype);
|
||
if (s->Sclass == SCmember || s->Sclass == SCfield)
|
||
{
|
||
dbg_printf(" Smemoff =%5lld", (long long)s->Smemoff);
|
||
dbg_printf(" Sbit =%3d",s->Sbit);
|
||
dbg_printf(" Swidth =%3d\n",s->Swidth);
|
||
}
|
||
#if SCPP
|
||
if (s->Sclass == SCstruct)
|
||
{
|
||
#if VBTABLES
|
||
dbg_printf(" Svbptr = %p, Svptr = %p\n",s->Sstruct->Svbptr,s->Sstruct->Svptr);
|
||
#endif
|
||
}
|
||
#endif
|
||
#endif
|
||
}
|
||
|
||
#endif
|
||
|
||
/*********************************
|
||
* Terminate use of symbol table.
|
||
*/
|
||
|
||
static symbol *keep;
|
||
|
||
void symbol_term()
|
||
{
|
||
symbol_free(keep);
|
||
}
|
||
|
||
/****************************************
|
||
* Keep symbol around until symbol_term().
|
||
*/
|
||
|
||
#if TERMCODE
|
||
|
||
void symbol_keep(symbol *s)
|
||
{
|
||
symbol_debug(s);
|
||
s->Sr = keep; // use Sr so symbol_free() doesn't nest
|
||
keep = s;
|
||
}
|
||
|
||
#endif
|
||
|
||
/***********************************
|
||
* Get user name of symbol.
|
||
*/
|
||
|
||
char *symbol_ident(symbol *s)
|
||
{
|
||
#if SCPP
|
||
static char noname[] = "__unnamed";
|
||
switch (s->Sclass)
|
||
{ case SCstruct:
|
||
if (s->Sstruct->Salias)
|
||
s = s->Sstruct->Salias;
|
||
else if (s->Sstruct->Sflags & STRnotagname)
|
||
return noname;
|
||
break;
|
||
case SCenum:
|
||
if (CPP)
|
||
{ if (s->Senum->SEalias)
|
||
s = s->Senum->SEalias;
|
||
else if (s->Senum->SEflags & SENnotagname)
|
||
return noname;
|
||
}
|
||
break;
|
||
|
||
case SCnamespace:
|
||
if (s->Sident[0] == '?' && s->Sident[1] == '%')
|
||
return "unique"; // an unnamed namespace
|
||
break;
|
||
}
|
||
#endif
|
||
return s->Sident;
|
||
}
|
||
|
||
/****************************************
|
||
* Create a new symbol.
|
||
*/
|
||
|
||
symbol * symbol_calloc(const char *id)
|
||
{ symbol *s;
|
||
int len;
|
||
|
||
len = strlen(id);
|
||
//printf("sizeof(symbol)=%d, sizeof(s->Sident)=%d, len=%d\n",sizeof(symbol),sizeof(s->Sident),len);
|
||
s = (symbol *) mem_fmalloc(sizeof(symbol) - sizeof(s->Sident) + len + 1 + 5);
|
||
memset(s,0,sizeof(symbol) - sizeof(s->Sident));
|
||
#if SCPP
|
||
s->Ssequence = pstate.STsequence;
|
||
pstate.STsequence += 1;
|
||
//if (s->Ssequence == 0x21) *(char*)0=0;
|
||
#endif
|
||
#ifdef DEBUG
|
||
if (debugy)
|
||
dbg_printf("symbol_calloc('%s') = %p\n",id,s);
|
||
s->id = IDsymbol;
|
||
#endif
|
||
memcpy(s->Sident,id,len + 1);
|
||
s->Ssymnum = -1;
|
||
return s;
|
||
}
|
||
|
||
/****************************************
|
||
* Create a symbol, given a name and type.
|
||
*/
|
||
|
||
symbol * symbol_name(const char *name,int sclass,type *t)
|
||
{
|
||
type_debug(t);
|
||
symbol *s = symbol_calloc(name);
|
||
s->Sclass = (enum SC) sclass;
|
||
s->Stype = t;
|
||
s->Stype->Tcount++;
|
||
#if ELFOBJ || MACHOBJ // Burton
|
||
s->Sseg = CDATA;
|
||
#endif
|
||
|
||
if (tyfunc(t->Tty))
|
||
symbol_func(s);
|
||
return s;
|
||
}
|
||
|
||
/****************************************
|
||
* Create a symbol that is an alias to another function symbol.
|
||
*/
|
||
|
||
Funcsym *symbol_funcalias(Funcsym *sf)
|
||
{
|
||
Funcsym *s;
|
||
|
||
symbol_debug(sf);
|
||
assert(tyfunc(sf->Stype->Tty));
|
||
if (sf->Sclass == SCfuncalias)
|
||
sf = sf->Sfunc->Falias;
|
||
s = (Funcsym *)symbol_name(sf->Sident,SCfuncalias,sf->Stype);
|
||
s->Sfunc->Falias = sf;
|
||
#if SCPP
|
||
s->Scover = sf->Scover;
|
||
#endif
|
||
return s;
|
||
}
|
||
|
||
/****************************************
|
||
* Create a symbol, give it a name, storage class and type.
|
||
*/
|
||
|
||
symbol * symbol_generate(int sclass,type *t)
|
||
{ char name[10];
|
||
static int tmpnum;
|
||
|
||
sprintf(name,"_TMP%d",tmpnum++);
|
||
#ifdef DEBUG
|
||
symbol *s = symbol_name(name,sclass,t);
|
||
//symbol_print(s);
|
||
return s;
|
||
#else
|
||
return symbol_name(name,sclass,t);
|
||
#endif
|
||
}
|
||
|
||
/****************************************
|
||
* Generate an auto symbol, and add it to the symbol table.
|
||
*/
|
||
|
||
symbol * symbol_genauto(type *t)
|
||
{ symbol *s;
|
||
|
||
s = symbol_generate(SCauto,t);
|
||
#if SCPP
|
||
//printf("symbol_genauto(t) '%s'\n", s->Sident);
|
||
if (pstate.STdefertemps)
|
||
{ symbol_keep(s);
|
||
s->Ssymnum = -1;
|
||
}
|
||
else
|
||
{ s->Sflags |= SFLfree;
|
||
if (init_staticctor)
|
||
{ // variable goes into _STI_xxxx
|
||
s->Ssymnum = -1; // deferred allocation
|
||
//printf("test2\n");
|
||
//if (s->Sident[4] == '2') *(char*)0=0;
|
||
}
|
||
else
|
||
{
|
||
symbol_add(s);
|
||
}
|
||
}
|
||
#else
|
||
s->Sflags |= SFLfree;
|
||
symbol_add(s);
|
||
#endif
|
||
return s;
|
||
}
|
||
|
||
/******************************************
|
||
* Generate symbol into which we can copy the contents of expression e.
|
||
*/
|
||
|
||
Symbol *symbol_genauto(elem *e)
|
||
{
|
||
return symbol_genauto(type_fake(e->Ety));
|
||
}
|
||
|
||
/******************************************
|
||
* Generate symbol into which we can copy the contents of expression e.
|
||
*/
|
||
|
||
Symbol *symbol_genauto(tym_t ty)
|
||
{
|
||
return symbol_genauto(type_fake(ty));
|
||
}
|
||
|
||
/****************************************
|
||
* Add in the variants for a function symbol.
|
||
*/
|
||
|
||
void symbol_func(symbol *s)
|
||
{
|
||
//printf("symbol_func(%s, x%x)\n", s->Sident, fregsaved);
|
||
symbol_debug(s);
|
||
s->Sfl = FLfunc;
|
||
// Interrupt functions modify all registers
|
||
#if TX86
|
||
// BUG: do interrupt functions really save BP?
|
||
#define mBP 0x20
|
||
// Note that fregsaved may not be set yet
|
||
s->Sregsaved = (s->Stype && tybasic(s->Stype->Tty) == TYifunc) ? mBP : fregsaved;
|
||
s->Sseg = UNKNOWN; // don't know what segment it is in
|
||
#endif
|
||
if (!s->Sfunc)
|
||
s->Sfunc = func_calloc();
|
||
}
|
||
|
||
/********************************
|
||
* Define symbol in specified symbol table.
|
||
* Returns:
|
||
* pointer to symbol
|
||
*/
|
||
|
||
#if SCPP
|
||
|
||
symbol * defsy(const char *p,symbol **parent)
|
||
{
|
||
symbol *s = symbol_calloc(p);
|
||
symbol_addtotree(parent,s);
|
||
return s;
|
||
}
|
||
|
||
#endif
|
||
|
||
/********************************
|
||
* Check integrity of symbol data structure.
|
||
*/
|
||
|
||
#ifdef DEBUG
|
||
|
||
void symbol_check(symbol *s)
|
||
{
|
||
//dbg_printf("symbol_check('%s',%p)\n",s->Sident,s);
|
||
symbol_debug(s);
|
||
if (s->Stype) type_debug(s->Stype);
|
||
assert((unsigned)s->Sclass < (unsigned)SCMAX);
|
||
#if SCPP
|
||
if (s->Sscope)
|
||
symbol_check(s->Sscope);
|
||
if (s->Scover)
|
||
symbol_check(s->Scover);
|
||
#endif
|
||
}
|
||
|
||
void symbol_tree_check(symbol *s)
|
||
{
|
||
while (s)
|
||
{ symbol_check(s);
|
||
symbol_tree_check(s->Sl);
|
||
s = s->Sr;
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
/********************************
|
||
* Insert symbol in specified symbol table.
|
||
*/
|
||
|
||
#if SCPP
|
||
|
||
void symbol_addtotree(symbol **parent,symbol *s)
|
||
{ symbol *rover;
|
||
signed char cmp;
|
||
size_t len;
|
||
const char *p;
|
||
char c;
|
||
|
||
//dbg_printf("symbol_addtotree('%s',%p)\n",s->Sident,*parent);
|
||
#ifdef DEBUG
|
||
symbol_tree_check(*parent);
|
||
assert(!s->Sl && !s->Sr);
|
||
#endif
|
||
symbol_debug(s);
|
||
p = s->Sident;
|
||
c = *p;
|
||
len = strlen(p);
|
||
p++;
|
||
rover = *parent;
|
||
while (rover != NULL) // while we haven't run out of tree
|
||
{ symbol_debug(rover);
|
||
if ((cmp = c - rover->Sident[0]) == 0)
|
||
{ cmp = memcmp(p,rover->Sident + 1,len); // compare identifier strings
|
||
if (cmp == 0) // found it if strings match
|
||
{
|
||
if (CPP)
|
||
{ symbol *s2;
|
||
|
||
switch (rover->Sclass)
|
||
{ case SCstruct:
|
||
s2 = rover;
|
||
goto case_struct;
|
||
|
||
case_struct:
|
||
if (s2->Sstruct->Sctor &&
|
||
!(s2->Sstruct->Sctor->Sfunc->Fflags & Fgen))
|
||
cpperr(EM_ctor_disallowed,p); // no ctor allowed for class rover
|
||
s2->Sstruct->Sflags |= STRnoctor;
|
||
goto case_cover;
|
||
|
||
case_cover:
|
||
// Replace rover with the new symbol s, and
|
||
// have s 'cover' the tag symbol s2.
|
||
// BUG: memory leak on rover if s2!=rover
|
||
assert(!s2->Scover);
|
||
s->Sl = rover->Sl;
|
||
s->Sr = rover->Sr;
|
||
s->Scover = s2;
|
||
*parent = s;
|
||
rover->Sl = rover->Sr = NULL;
|
||
return;
|
||
|
||
case SCenum:
|
||
s2 = rover;
|
||
goto case_cover;
|
||
|
||
case SCtemplate:
|
||
s2 = rover;
|
||
s2->Stemplate->TMflags |= STRnoctor;
|
||
goto case_cover;
|
||
|
||
case SCalias:
|
||
s2 = rover->Smemalias;
|
||
if (s2->Sclass == SCstruct)
|
||
goto case_struct;
|
||
if (s2->Sclass == SCenum)
|
||
goto case_cover;
|
||
break;
|
||
}
|
||
}
|
||
synerr(EM_multiple_def,p - 1); // symbol is already defined
|
||
//symbol_undef(s); // undefine the symbol
|
||
return;
|
||
}
|
||
}
|
||
parent = (cmp < 0) ? /* if we go down left side */
|
||
&(rover->Sl) : /* then get left child */
|
||
&(rover->Sr); /* else get right child */
|
||
rover = *parent; /* get child */
|
||
}
|
||
/* not in table, so insert into table */
|
||
*parent = s; /* link new symbol into tree */
|
||
L1:
|
||
;
|
||
}
|
||
|
||
#endif
|
||
|
||
/*************************************
|
||
* Search for symbol in multiple symbol tables,
|
||
* starting with most recently nested one.
|
||
* Input:
|
||
* p -> identifier string
|
||
* Returns:
|
||
* pointer to symbol
|
||
* NULL if couldn't find it
|
||
*/
|
||
|
||
#if 0
|
||
symbol * lookupsym(const char *p)
|
||
{
|
||
return scope_search(p,SCTglobal | SCTlocal);
|
||
}
|
||
#endif
|
||
|
||
/*************************************
|
||
* Search for symbol in symbol table.
|
||
* Input:
|
||
* p -> identifier string
|
||
* rover -> where to start looking
|
||
* Returns:
|
||
* pointer to symbol (NULL if not found)
|
||
*/
|
||
|
||
#if SCPP
|
||
|
||
symbol * findsy(const char *p,symbol *rover)
|
||
{
|
||
#if __INTSIZE == 2 && TX86 && !defined(_MSC_VER)
|
||
volatile int len;
|
||
__asm
|
||
{
|
||
push DS
|
||
mov DS,word ptr p+2
|
||
les DI,p
|
||
mov DX,word ptr p
|
||
mov BX,ES:[DI]
|
||
xor AL,AL
|
||
mov CX,0FFFFh
|
||
repne scasb
|
||
not CX
|
||
sub CX,2
|
||
mov len,CX
|
||
add DX,2
|
||
mov AX,BX
|
||
les BX,rover
|
||
jmp short L1
|
||
|
||
L38C: les BX,ES:symbol.Sl[BX]
|
||
L1: test BX,BX
|
||
je L3A5
|
||
cmp AL,ES:symbol.Sident[BX]
|
||
js L38C
|
||
je L2
|
||
les BX,ES:symbol.Sr[BX]
|
||
jmp L1
|
||
|
||
L2: cmp AH,ES:symbol.Sident+1[BX]
|
||
js L38C
|
||
je L3
|
||
les BX,ES:symbol.Sr[BX]
|
||
jmp L1
|
||
|
||
L3: mov SI,DX
|
||
lea DI,symbol.Sident+2[BX]
|
||
mov CX,len
|
||
rep cmpsb
|
||
js L38C
|
||
je L3A5
|
||
les BX,ES:symbol.Sr[BX]
|
||
jmp L1
|
||
|
||
L3A5: mov DX,ES
|
||
mov AX,BX
|
||
pop DS
|
||
}
|
||
#elif __INTSIZE == 4 && TX86 && !defined(_MSC_VER) && !M_UNIX
|
||
volatile int len;
|
||
__asm
|
||
{
|
||
#if !_WIN32
|
||
push DS
|
||
pop ES
|
||
#endif
|
||
mov EDI,p
|
||
xor AL,AL
|
||
|
||
mov BL,[EDI]
|
||
mov ECX,-1
|
||
|
||
repne scasb
|
||
|
||
not ECX
|
||
mov EDX,p
|
||
|
||
dec ECX
|
||
inc EDX
|
||
|
||
mov len,ECX
|
||
mov AL,BL
|
||
|
||
mov EBX,rover
|
||
mov ESI,EDX
|
||
|
||
test EBX,EBX
|
||
je L6
|
||
|
||
cmp AL,symbol.Sident[EBX]
|
||
js L2
|
||
|
||
lea EDI,symbol.Sident+1[EBX]
|
||
je L5
|
||
|
||
mov EBX,symbol.Sr[EBX]
|
||
jmp L3
|
||
|
||
L1: mov ECX,len
|
||
L2: mov EBX,symbol.Sl[EBX]
|
||
|
||
L3: test EBX,EBX
|
||
je L6
|
||
|
||
L4: cmp AL,symbol.Sident[EBX]
|
||
js L2
|
||
|
||
lea EDI,symbol.Sident+1[EBX]
|
||
je L5
|
||
|
||
mov EBX,symbol.Sr[EBX]
|
||
jmp L3
|
||
|
||
L5: rep cmpsb
|
||
|
||
mov ESI,EDX
|
||
js L1
|
||
|
||
je L6
|
||
|
||
mov EBX,symbol.Sr[EBX]
|
||
mov ECX,len
|
||
|
||
test EBX,EBX
|
||
jne L4
|
||
|
||
L6: mov EAX,EBX
|
||
}
|
||
#else
|
||
size_t len;
|
||
signed char cmp; /* set to value of strcmp */
|
||
char c = *p;
|
||
|
||
len = strlen(p);
|
||
p++; // will pick up 0 on memcmp
|
||
while (rover != NULL) // while we haven't run out of tree
|
||
{ symbol_debug(rover);
|
||
if ((cmp = c - rover->Sident[0]) == 0)
|
||
{ cmp = memcmp(p,rover->Sident + 1,len); /* compare identifier strings */
|
||
if (cmp == 0)
|
||
return rover; /* found it if strings match */
|
||
}
|
||
rover = (cmp < 0) ? rover->Sl : rover->Sr;
|
||
}
|
||
return rover; // failed to find it
|
||
#endif
|
||
}
|
||
|
||
#endif
|
||
|
||
/***********************************
|
||
* Create a new symbol table.
|
||
*/
|
||
|
||
#if SCPP
|
||
|
||
void createglobalsymtab()
|
||
{
|
||
assert(!scope_end);
|
||
if (CPP)
|
||
scope_push(NULL,(scope_fp)findsy, SCTcglobal);
|
||
else
|
||
scope_push(NULL,(scope_fp)findsy, SCTglobaltag);
|
||
scope_push(NULL,(scope_fp)findsy, SCTglobal);
|
||
}
|
||
|
||
|
||
void createlocalsymtab()
|
||
{
|
||
assert(scope_end);
|
||
if (!CPP)
|
||
scope_push(NULL,(scope_fp)findsy, SCTtag);
|
||
scope_push(NULL,(scope_fp)findsy, SCTlocal);
|
||
}
|
||
|
||
|
||
/***********************************
|
||
* Delete current symbol table and back up one.
|
||
*/
|
||
|
||
void deletesymtab()
|
||
{ symbol *root;
|
||
|
||
root = (symbol *)scope_pop();
|
||
if (root)
|
||
{
|
||
if (funcsym_p)
|
||
list_prepend(&funcsym_p->Sfunc->Fsymtree,root);
|
||
else
|
||
symbol_free(root); // free symbol table
|
||
}
|
||
|
||
if (!CPP)
|
||
{
|
||
root = (symbol *)scope_pop();
|
||
if (root)
|
||
{
|
||
if (funcsym_p)
|
||
list_prepend(&funcsym_p->Sfunc->Fsymtree,root);
|
||
else
|
||
symbol_free(root); // free symbol table
|
||
}
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
/*********************************
|
||
* Delete symbol from symbol table, taking care to delete
|
||
* all children of a symbol.
|
||
* Make sure there are no more forward references (labels, tags).
|
||
* Input:
|
||
* pointer to a symbol
|
||
*/
|
||
|
||
void meminit_free(meminit_t *m) /* helper for symbol_free() */
|
||
{
|
||
list_free(&m->MIelemlist,(list_free_fp)el_free);
|
||
MEM_PARF_FREE(m);
|
||
}
|
||
|
||
void symbol_free(symbol *s)
|
||
{
|
||
while (s) /* if symbol exists */
|
||
{ symbol *sr;
|
||
|
||
#ifdef DEBUG
|
||
if (debugy)
|
||
dbg_printf("symbol_free('%s',%p)\n",s->Sident,s);
|
||
symbol_debug(s);
|
||
assert(/*s->Sclass != SCunde &&*/ (int) s->Sclass < (int) SCMAX);
|
||
#endif
|
||
{ type *t = s->Stype;
|
||
|
||
if (t)
|
||
type_debug(t);
|
||
if (t && tyfunc(t->Tty) && s->Sfunc)
|
||
{
|
||
func_t *f = s->Sfunc;
|
||
|
||
debug(assert(f));
|
||
blocklist_free(&f->Fstartblock);
|
||
freesymtab(f->Flocsym.tab,0,f->Flocsym.top);
|
||
|
||
symtab_free(f->Flocsym.tab);
|
||
if (CPP)
|
||
{
|
||
if (f->Fflags & Fnotparent)
|
||
{ debug(debugy && dbg_printf("not parent, returning\n"));
|
||
return;
|
||
}
|
||
|
||
/* We could be freeing the symbol before it's class is */
|
||
/* freed, so remove it from the class's field list */
|
||
#if 1
|
||
if (f->Fclass)
|
||
{ list_t tl;
|
||
|
||
symbol_debug(f->Fclass);
|
||
tl = list_inlist(f->Fclass->Sstruct->Sfldlst,s);
|
||
if (tl)
|
||
list_setsymbol(tl,0);
|
||
}
|
||
#endif
|
||
if (f->Foversym && f->Foversym->Sfunc)
|
||
{ f->Foversym->Sfunc->Fflags &= ~Fnotparent;
|
||
f->Foversym->Sfunc->Fclass = NULL;
|
||
symbol_free(f->Foversym);
|
||
}
|
||
|
||
if (f->Fexplicitspec)
|
||
symbol_free(f->Fexplicitspec);
|
||
|
||
/* If operator function, remove from list of such functions */
|
||
if (f->Fflags & Foperator)
|
||
{ assert(f->Foper && f->Foper < OPMAX);
|
||
//if (list_inlist(cpp_operfuncs[f->Foper],s))
|
||
// list_subtract(&cpp_operfuncs[f->Foper],s);
|
||
}
|
||
|
||
list_free(&f->Fclassfriends,FPNULL);
|
||
list_free(&f->Ffwdrefinstances,FPNULL);
|
||
param_free(&f->Farglist);
|
||
param_free(&f->Fptal);
|
||
list_free(&f->Fexcspec,(list_free_fp)type_free);
|
||
#if SCPP
|
||
token_free(f->Fbody);
|
||
#endif
|
||
el_free(f->Fbaseinit);
|
||
if (f->Fthunk && !(f->Fflags & Finstance))
|
||
MEM_PH_FREE(f->Fthunk);
|
||
list_free(&f->Fthunks,(list_free_fp)symbol_free);
|
||
}
|
||
list_free(&f->Fsymtree,(list_free_fp)symbol_free);
|
||
func_free(f);
|
||
}
|
||
switch (s->Sclass)
|
||
{
|
||
#if SCPP
|
||
case SClabel:
|
||
if (!s->Slabel)
|
||
synerr(EM_unknown_label,s->Sident);
|
||
break;
|
||
#endif
|
||
case SCstruct:
|
||
#if SCPP
|
||
if (CPP)
|
||
{
|
||
struct_t *st = s->Sstruct;
|
||
assert(st);
|
||
list_free(&st->Sclassfriends,FPNULL);
|
||
list_free(&st->Sfriendclass,FPNULL);
|
||
list_free(&st->Sfriendfuncs,FPNULL);
|
||
list_free(&st->Scastoverload,FPNULL);
|
||
list_free(&st->Sopoverload,FPNULL);
|
||
list_free(&st->Svirtual,MEM_PH_FREEFP);
|
||
list_free(&st->Sfldlst,FPNULL);
|
||
symbol_free(st->Sroot);
|
||
baseclass_t *b,*bn;
|
||
|
||
for (b = st->Sbase; b; b = bn)
|
||
{ bn = b->BCnext;
|
||
list_free(&b->BCpublics,FPNULL);
|
||
baseclass_free(b);
|
||
}
|
||
for (b = st->Svirtbase; b; b = bn)
|
||
{ bn = b->BCnext;
|
||
baseclass_free(b);
|
||
}
|
||
for (b = st->Smptrbase; b; b = bn)
|
||
{ bn = b->BCnext;
|
||
list_free(&b->BCmptrlist,MEM_PH_FREEFP);
|
||
baseclass_free(b);
|
||
}
|
||
#if VBTABLES
|
||
for (b = st->Svbptrbase; b; b = bn)
|
||
{ bn = b->BCnext;
|
||
baseclass_free(b);
|
||
}
|
||
#endif
|
||
param_free(&st->Sarglist);
|
||
param_free(&st->Spr_arglist);
|
||
struct_free(st);
|
||
}
|
||
else
|
||
#endif
|
||
{
|
||
#ifdef DEBUG
|
||
if (debugy)
|
||
dbg_printf("freeing members %p\n",s->Sstruct->Sfldlst);
|
||
#endif
|
||
list_free(&s->Sstruct->Sfldlst,FPNULL);
|
||
symbol_free(s->Sstruct->Sroot);
|
||
struct_free(s->Sstruct);
|
||
}
|
||
#if 0 /* Don't complain anymore about these, ANSI C says */
|
||
/* it's ok */
|
||
if (t && t->Tflags & TFsizeunknown)
|
||
synerr(EM_unknown_tag,s->Sident);
|
||
#endif
|
||
break;
|
||
case SCenum:
|
||
/* The actual member symbols are either in a local */
|
||
/* table or on the member list of a class, so we */
|
||
/* don't free them here. */
|
||
assert(s->Senum);
|
||
list_free(&s->Senumlist,FPNULL);
|
||
MEM_PH_FREE(s->Senum);
|
||
s->Senum = NULL;
|
||
break;
|
||
|
||
#if SCPP
|
||
case SCtemplate:
|
||
{ template_t *tm = s->Stemplate;
|
||
|
||
list_free(&tm->TMinstances,FPNULL);
|
||
list_free(&tm->TMmemberfuncs,(list_free_fp)tmf_free);
|
||
list_free(&tm->TMexplicit,(list_free_fp)tme_free);
|
||
list_free(&tm->TMnestedexplicit,(list_free_fp)tmne_free);
|
||
list_free(&tm->TMnestedfriends,(list_free_fp)tmnf_free);
|
||
param_free(&tm->TMptpl);
|
||
param_free(&tm->TMptal);
|
||
token_free(tm->TMbody);
|
||
symbol_free(tm->TMpartial);
|
||
list_free(&tm->TMfriends,FPNULL);
|
||
MEM_PH_FREE(tm);
|
||
break;
|
||
}
|
||
case SCnamespace:
|
||
symbol_free(s->Snameroot);
|
||
list_free(&s->Susing,FPNULL);
|
||
break;
|
||
|
||
case SCmemalias:
|
||
case SCfuncalias:
|
||
case SCadl:
|
||
list_free(&s->Spath,FPNULL);
|
||
break;
|
||
#endif
|
||
case SCparameter:
|
||
case SCregpar:
|
||
case SCfastpar:
|
||
case SCregister:
|
||
case SCtmp:
|
||
case SCauto:
|
||
vec_free(s->Srange);
|
||
/* FALL-THROUGH */
|
||
#if 0
|
||
case SCconst:
|
||
if (s->Sflags & (SFLvalue | SFLdtorexp))
|
||
el_free(s->Svalue);
|
||
#endif
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if (s->Sflags & (SFLvalue | SFLdtorexp))
|
||
el_free(s->Svalue);
|
||
if (s->Sdt)
|
||
dt_free(s->Sdt);
|
||
type_free(t);
|
||
symbol_free(s->Sl);
|
||
#if SCPP
|
||
if (s->Scover)
|
||
symbol_free(s->Scover);
|
||
#endif
|
||
sr = s->Sr;
|
||
#ifdef DEBUG
|
||
s->id = 0;
|
||
#endif
|
||
mem_ffree(s);
|
||
}
|
||
s = sr;
|
||
}
|
||
}
|
||
|
||
/********************************
|
||
* Undefine a symbol.
|
||
* Assume error msg was already printed.
|
||
*/
|
||
|
||
#if 0
|
||
STATIC void symbol_undef(symbol *s)
|
||
{
|
||
s->Sclass = SCunde;
|
||
s->Ssymnum = -1;
|
||
type_free(s->Stype); /* free type data */
|
||
s->Stype = NULL;
|
||
}
|
||
#endif
|
||
|
||
/*****************************
|
||
* Add symbol to current symbol array.
|
||
*/
|
||
|
||
SYMIDX symbol_add(symbol *s)
|
||
{ SYMIDX sitop;
|
||
|
||
//printf("symbol_add('%s')\n", s->Sident);
|
||
#ifdef DEBUG
|
||
if (!s || !s->Sident[0])
|
||
{ dbg_printf("bad symbol\n");
|
||
assert(0);
|
||
}
|
||
#endif
|
||
symbol_debug(s);
|
||
if (pstate.STinsizeof)
|
||
{ symbol_keep(s);
|
||
return -1;
|
||
}
|
||
debug(assert(cstate.CSpsymtab));
|
||
sitop = cstate.CSpsymtab->top;
|
||
assert(sitop <= cstate.CSpsymtab->symmax);
|
||
if (sitop == cstate.CSpsymtab->symmax)
|
||
{
|
||
#ifdef DEBUG
|
||
#define SYMINC 1 /* flush out reallocation bugs */
|
||
#else
|
||
#define SYMINC 99
|
||
#endif
|
||
cstate.CSpsymtab->symmax += (cstate.CSpsymtab == &globsym) ? SYMINC : 1;
|
||
//assert(cstate.CSpsymtab->symmax * sizeof(symbol *) < 4096 * 4);
|
||
cstate.CSpsymtab->tab = symtab_realloc(cstate.CSpsymtab->tab, cstate.CSpsymtab->symmax);
|
||
}
|
||
cstate.CSpsymtab->tab[sitop] = s;
|
||
#if AUTONEST
|
||
if (pushcount)
|
||
{ s->Spush = pushcount;
|
||
pushcount = 0;
|
||
}
|
||
#endif
|
||
#ifdef DEBUG
|
||
if (debugy)
|
||
dbg_printf("symbol_add(%p '%s') = %d\n",s,s->Sident,cstate.CSpsymtab->top);
|
||
#endif
|
||
assert(s->Ssymnum == -1);
|
||
return s->Ssymnum = cstate.CSpsymtab->top++;
|
||
}
|
||
|
||
/****************************
|
||
* Free up the symbol table, from symbols n1 through n2, not
|
||
* including n2.
|
||
*/
|
||
|
||
void freesymtab(symbol **stab,SYMIDX n1,SYMIDX n2)
|
||
{ SYMIDX si;
|
||
|
||
if (!stab)
|
||
return;
|
||
#ifdef DEBUG
|
||
if (debugy)
|
||
dbg_printf("freesymtab(from %d to %d)\n",n1,n2);
|
||
#endif
|
||
assert(stab != globsym.tab || (n1 <= n2 && n2 <= globsym.top));
|
||
for (si = n1; si < n2; si++)
|
||
{ symbol *s;
|
||
|
||
s = stab[si];
|
||
if (s && s->Sflags & SFLfree)
|
||
{ stab[si] = NULL;
|
||
#ifdef DEBUG
|
||
if (debugy)
|
||
dbg_printf("Freeing %p '%s' (%d)\n",s,s->Sident,si);
|
||
symbol_debug(s);
|
||
#endif
|
||
s->Sl = s->Sr = NULL;
|
||
s->Ssymnum = -1;
|
||
symbol_free(s);
|
||
}
|
||
}
|
||
}
|
||
|
||
/****************************
|
||
* Create a copy of a symbol.
|
||
*/
|
||
|
||
symbol * symbol_copy(symbol *s)
|
||
{ symbol *scopy;
|
||
type *t;
|
||
|
||
symbol_debug(s);
|
||
/*dbg_printf("symbol_copy(%s)\n",s->Sident);*/
|
||
scopy = symbol_calloc(s->Sident);
|
||
memcpy(scopy,s,sizeof(symbol) - sizeof(s->Sident));
|
||
scopy->Sl = scopy->Sr = scopy->Snext = NULL;
|
||
scopy->Ssymnum = -1;
|
||
if (scopy->Sdt)
|
||
dtsymsize(scopy);
|
||
if (scopy->Sflags & (SFLvalue | SFLdtorexp))
|
||
scopy->Svalue = el_copytree(s->Svalue);
|
||
t = scopy->Stype;
|
||
if (t)
|
||
{ t->Tcount++; /* one more parent of the type */
|
||
type_debug(t);
|
||
}
|
||
return scopy;
|
||
}
|
||
|
||
/*******************************
|
||
* Search list for a symbol with an identifier that matches.
|
||
* Returns:
|
||
* pointer to matching symbol
|
||
* NULL if not found
|
||
*/
|
||
|
||
#if SCPP
|
||
|
||
symbol * symbol_searchlist(symlist_t sl,const char *vident)
|
||
{ symbol *s;
|
||
#ifdef DEBUG
|
||
int count = 0;
|
||
#endif
|
||
|
||
//dbg_printf("searchlist(%s)\n",vident);
|
||
for (; sl; sl = list_next(sl))
|
||
{ s = list_symbol(sl);
|
||
symbol_debug(s);
|
||
/*dbg_printf("\tcomparing with %s\n",s->Sident);*/
|
||
if (strcmp(vident,s->Sident) == 0)
|
||
return s;
|
||
#ifdef DEBUG
|
||
assert(++count < 300); /* prevent infinite loops */
|
||
#endif
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
/***************************************
|
||
* Search for symbol in sequence of symbol tables.
|
||
* Input:
|
||
* glbl !=0 if global symbol table only
|
||
*/
|
||
|
||
symbol *symbol_search(const char *id)
|
||
{
|
||
Scope *sc;
|
||
if (CPP)
|
||
{ unsigned sct;
|
||
|
||
sct = pstate.STclasssym ? SCTclass : 0;
|
||
sct |= SCTmfunc | SCTlocal | SCTwith | SCTglobal | SCTnspace | SCTtemparg | SCTtempsym;
|
||
return scope_searchx(id,sct,&sc);
|
||
}
|
||
else
|
||
return scope_searchx(id,SCTglobal | SCTlocal,&sc);
|
||
}
|
||
|
||
#endif
|
||
|
||
/*******************************************
|
||
* Hydrate a symbol tree.
|
||
*/
|
||
|
||
#if HYDRATE
|
||
void symbol_tree_hydrate(symbol **ps)
|
||
{ symbol *s;
|
||
|
||
while (isdehydrated(*ps)) /* if symbol is dehydrated */
|
||
{
|
||
s = symbol_hydrate(ps);
|
||
symbol_debug(s);
|
||
if (s->Scover)
|
||
symbol_hydrate(&s->Scover);
|
||
symbol_tree_hydrate(&s->Sl);
|
||
ps = &s->Sr;
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
/*******************************************
|
||
* Dehydrate a symbol tree.
|
||
*/
|
||
|
||
#if DEHYDRATE
|
||
void symbol_tree_dehydrate(symbol **ps)
|
||
{ symbol *s;
|
||
|
||
while ((s = *ps) != NULL && !isdehydrated(s)) /* if symbol exists */
|
||
{
|
||
symbol_debug(s);
|
||
symbol_dehydrate(ps);
|
||
#if DEBUG_XSYMGEN
|
||
if (xsym_gen && ph_in_head(s))
|
||
return;
|
||
#endif
|
||
symbol_dehydrate(&s->Scover);
|
||
symbol_tree_dehydrate(&s->Sl);
|
||
ps = &s->Sr;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/*******************************************
|
||
* Hydrate a symbol.
|
||
*/
|
||
|
||
#if HYDRATE
|
||
symbol *symbol_hydrate(symbol **ps)
|
||
{ symbol *s;
|
||
|
||
s = *ps;
|
||
if (isdehydrated(s)) /* if symbol is dehydrated */
|
||
{ type *t;
|
||
struct_t *st;
|
||
|
||
s = (symbol *) ph_hydrate(ps);
|
||
#ifdef DEBUG
|
||
debugy && dbg_printf("symbol_hydrate('%s')\n",s->Sident);
|
||
#endif
|
||
symbol_debug(s);
|
||
if (!isdehydrated(s->Stype)) // if this symbol is already dehydrated
|
||
return s; // no need to do it again
|
||
#if SOURCE_4SYMS
|
||
s->Ssrcpos.Sfilnum += File_Hydrate_Num; /* file number relative header build */
|
||
#endif
|
||
if (pstate.SThflag != FLAG_INPLACE && s->Sfl != FLreg)
|
||
s->Sxtrnnum = 0; // not written to .OBJ file yet
|
||
type_hydrate(&s->Stype);
|
||
//dbg_printf("symbol_hydrate(%p, '%s', t = %p)\n",s,s->Sident,s->Stype);
|
||
t = s->Stype;
|
||
if (t)
|
||
type_debug(t);
|
||
|
||
if (t && tyfunc(t->Tty) && ph_hydrate(&s->Sfunc))
|
||
{
|
||
func_t *f = s->Sfunc;
|
||
SYMIDX si;
|
||
|
||
debug(assert(f));
|
||
|
||
list_hydrate(&f->Fsymtree,(list_free_fp)symbol_tree_hydrate);
|
||
blocklist_hydrate(&f->Fstartblock);
|
||
|
||
ph_hydrate(&f->Flocsym.tab);
|
||
for (si = 0; si < f->Flocsym.top; si++)
|
||
symbol_hydrate(&f->Flocsym.tab[si]);
|
||
|
||
srcpos_hydrate(&f->Fstartline);
|
||
srcpos_hydrate(&f->Fendline);
|
||
|
||
symbol_hydrate(&f->F__func__);
|
||
|
||
if (CPP)
|
||
{
|
||
symbol_hydrate(&f->Fparsescope);
|
||
Classsym_hydrate(&f->Fclass);
|
||
symbol_hydrate(&f->Foversym);
|
||
symbol_hydrate(&f->Fexplicitspec);
|
||
symbol_hydrate(&f->Fsurrogatesym);
|
||
|
||
list_hydrate(&f->Fclassfriends,(list_free_fp)symbol_hydrate);
|
||
el_hydrate(&f->Fbaseinit);
|
||
token_hydrate(&f->Fbody);
|
||
symbol_hydrate(&f->Falias);
|
||
list_hydrate(&f->Fthunks,(list_free_fp)symbol_hydrate);
|
||
if (f->Fflags & Finstance)
|
||
symbol_hydrate(&f->Ftempl);
|
||
else
|
||
thunk_hydrate(&f->Fthunk);
|
||
param_hydrate(&f->Farglist);
|
||
param_hydrate(&f->Fptal);
|
||
list_hydrate(&f->Ffwdrefinstances,(list_free_fp)symbol_hydrate);
|
||
list_hydrate(&f->Fexcspec,(list_free_fp)type_hydrate);
|
||
}
|
||
}
|
||
if (CPP)
|
||
symbol_hydrate(&s->Sscope);
|
||
switch (s->Sclass)
|
||
{
|
||
case SCstruct:
|
||
if (CPP)
|
||
{
|
||
st = (struct_t *) ph_hydrate(&s->Sstruct);
|
||
assert(st);
|
||
symbol_tree_hydrate(&st->Sroot);
|
||
ph_hydrate(&st->Spvirtder);
|
||
list_hydrate(&st->Sfldlst,(list_free_fp)symbol_hydrate);
|
||
list_hydrate(&st->Svirtual,(list_free_fp)mptr_hydrate);
|
||
list_hydrate(&st->Sopoverload,(list_free_fp)symbol_hydrate);
|
||
list_hydrate(&st->Scastoverload,(list_free_fp)symbol_hydrate);
|
||
list_hydrate(&st->Sclassfriends,(list_free_fp)symbol_hydrate);
|
||
list_hydrate(&st->Sfriendclass,(list_free_fp)symbol_hydrate);
|
||
list_hydrate(&st->Sfriendfuncs,(list_free_fp)symbol_hydrate);
|
||
assert(!st->Sinlinefuncs);
|
||
|
||
baseclass_hydrate(&st->Sbase);
|
||
baseclass_hydrate(&st->Svirtbase);
|
||
baseclass_hydrate(&st->Smptrbase);
|
||
baseclass_hydrate(&st->Sprimary);
|
||
#if VBTABLES
|
||
baseclass_hydrate(&st->Svbptrbase);
|
||
#endif
|
||
|
||
ph_hydrate(&st->Svecctor);
|
||
ph_hydrate(&st->Sctor);
|
||
ph_hydrate(&st->Sdtor);
|
||
#if VBTABLES
|
||
ph_hydrate(&st->Sprimdtor);
|
||
ph_hydrate(&st->Spriminv);
|
||
ph_hydrate(&st->Sscaldeldtor);
|
||
#endif
|
||
ph_hydrate(&st->Sinvariant);
|
||
ph_hydrate(&st->Svptr);
|
||
ph_hydrate(&st->Svtbl);
|
||
ph_hydrate(&st->Sopeq);
|
||
ph_hydrate(&st->Sopeq2);
|
||
ph_hydrate(&st->Scpct);
|
||
ph_hydrate(&st->Sveccpct);
|
||
ph_hydrate(&st->Salias);
|
||
ph_hydrate(&st->Stempsym);
|
||
param_hydrate(&st->Sarglist);
|
||
param_hydrate(&st->Spr_arglist);
|
||
#if VBTABLES
|
||
ph_hydrate(&st->Svbptr);
|
||
ph_hydrate(&st->Svbptr_parent);
|
||
ph_hydrate(&st->Svbtbl);
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
ph_hydrate(&s->Sstruct);
|
||
symbol_tree_hydrate(&s->Sstruct->Sroot);
|
||
list_hydrate(&s->Sstruct->Sfldlst,(list_free_fp)symbol_hydrate);
|
||
}
|
||
break;
|
||
|
||
case SCenum:
|
||
assert(s->Senum);
|
||
ph_hydrate(&s->Senum);
|
||
if (CPP)
|
||
{ ph_hydrate(&s->Senum->SEalias);
|
||
list_hydrate(&s->Senumlist,(list_free_fp)symbol_hydrate);
|
||
}
|
||
break;
|
||
|
||
case SCtemplate:
|
||
{ template_t *tm;
|
||
|
||
tm = (template_t *) ph_hydrate(&s->Stemplate);
|
||
list_hydrate(&tm->TMinstances,(list_free_fp)symbol_hydrate);
|
||
list_hydrate(&tm->TMfriends,(list_free_fp)symbol_hydrate);
|
||
param_hydrate(&tm->TMptpl);
|
||
param_hydrate(&tm->TMptal);
|
||
token_hydrate(&tm->TMbody);
|
||
list_hydrate(&tm->TMmemberfuncs,(list_free_fp)tmf_hydrate);
|
||
list_hydrate(&tm->TMexplicit,(list_free_fp)tme_hydrate);
|
||
list_hydrate(&tm->TMnestedexplicit,(list_free_fp)tmne_hydrate);
|
||
list_hydrate(&tm->TMnestedfriends,(list_free_fp)tmnf_hydrate);
|
||
ph_hydrate(&tm->TMnext);
|
||
symbol_hydrate(&tm->TMpartial);
|
||
symbol_hydrate(&tm->TMprimary);
|
||
break;
|
||
}
|
||
|
||
case SCnamespace:
|
||
symbol_tree_hydrate(&s->Snameroot);
|
||
list_hydrate(&s->Susing,(list_free_fp)symbol_hydrate);
|
||
break;
|
||
|
||
case SCmemalias:
|
||
case SCfuncalias:
|
||
case SCadl:
|
||
list_hydrate(&s->Spath,(list_free_fp)symbol_hydrate);
|
||
case SCalias:
|
||
ph_hydrate(&s->Smemalias);
|
||
break;
|
||
|
||
default:
|
||
if (s->Sflags & (SFLvalue | SFLdtorexp))
|
||
el_hydrate(&s->Svalue);
|
||
break;
|
||
}
|
||
{ dt_t **pdt,*dt;
|
||
|
||
for (pdt = &s->Sdt; isdehydrated(*pdt); pdt = &dt->DTnext)
|
||
{
|
||
dt = (dt_t *) ph_hydrate(pdt);
|
||
switch (dt->dt)
|
||
{ case DT_abytes:
|
||
case DT_nbytes:
|
||
ph_hydrate(&dt->DTpbytes);
|
||
break;
|
||
case DT_xoff:
|
||
symbol_hydrate(&dt->DTsym);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (s->Scover)
|
||
symbol_hydrate(&s->Scover);
|
||
}
|
||
return s;
|
||
}
|
||
#endif
|
||
|
||
/*******************************************
|
||
* Dehydrate a symbol.
|
||
*/
|
||
|
||
#if DEHYDRATE
|
||
void symbol_dehydrate(symbol **ps)
|
||
{
|
||
symbol *s;
|
||
|
||
if ((s = *ps) != NULL && !isdehydrated(s)) /* if symbol exists */
|
||
{ type *t;
|
||
struct_t *st;
|
||
|
||
#ifdef DEBUG
|
||
if (debugy)
|
||
dbg_printf("symbol_dehydrate('%s')\n",s->Sident);
|
||
#endif
|
||
ph_dehydrate(ps);
|
||
#if DEBUG_XSYMGEN
|
||
if (xsym_gen && ph_in_head(s))
|
||
return;
|
||
#endif
|
||
symbol_debug(s);
|
||
t = s->Stype;
|
||
if (isdehydrated(t))
|
||
return;
|
||
type_dehydrate(&s->Stype);
|
||
|
||
if (tyfunc(t->Tty) && !isdehydrated(s->Sfunc))
|
||
{
|
||
func_t *f = s->Sfunc;
|
||
SYMIDX si;
|
||
|
||
debug(assert(f));
|
||
ph_dehydrate(&s->Sfunc);
|
||
|
||
list_dehydrate(&f->Fsymtree,(list_free_fp)symbol_tree_dehydrate);
|
||
blocklist_dehydrate(&f->Fstartblock);
|
||
assert(!isdehydrated(&f->Flocsym.tab));
|
||
|
||
#if DEBUG_XSYMGEN
|
||
if (!xsym_gen || !ph_in_head(f->Flocsym.tab))
|
||
|
||
#endif
|
||
for (si = 0; si < f->Flocsym.top; si++)
|
||
symbol_dehydrate(&f->Flocsym.tab[si]);
|
||
ph_dehydrate(&f->Flocsym.tab);
|
||
|
||
srcpos_dehydrate(&f->Fstartline);
|
||
srcpos_dehydrate(&f->Fendline);
|
||
symbol_dehydrate(&f->F__func__);
|
||
if (CPP)
|
||
{
|
||
symbol_dehydrate(&f->Fparsescope);
|
||
ph_dehydrate(&f->Fclass);
|
||
symbol_dehydrate(&f->Foversym);
|
||
symbol_dehydrate(&f->Fexplicitspec);
|
||
symbol_dehydrate(&f->Fsurrogatesym);
|
||
|
||
list_dehydrate(&f->Fclassfriends,FPNULL);
|
||
el_dehydrate(&f->Fbaseinit);
|
||
#if DEBUG_XSYMGEN
|
||
if (xsym_gen && s->Sclass == SCfunctempl)
|
||
ph_dehydrate(&f->Fbody);
|
||
else
|
||
#endif
|
||
token_dehydrate(&f->Fbody);
|
||
symbol_dehydrate(&f->Falias);
|
||
list_dehydrate(&f->Fthunks,(list_free_fp)symbol_dehydrate);
|
||
if (f->Fflags & Finstance)
|
||
symbol_dehydrate(&f->Ftempl);
|
||
else
|
||
thunk_dehydrate(&f->Fthunk);
|
||
#if !TX86 && DEBUG_XSYMGEN
|
||
if (xsym_gen && s->Sclass == SCfunctempl)
|
||
ph_dehydrate(&f->Farglist);
|
||
else
|
||
#endif
|
||
param_dehydrate(&f->Farglist);
|
||
param_dehydrate(&f->Fptal);
|
||
list_dehydrate(&f->Ffwdrefinstances,(list_free_fp)symbol_dehydrate);
|
||
list_dehydrate(&f->Fexcspec,(list_free_fp)type_dehydrate);
|
||
}
|
||
}
|
||
if (CPP)
|
||
ph_dehydrate(&s->Sscope);
|
||
switch (s->Sclass)
|
||
{
|
||
case SCstruct:
|
||
if (CPP)
|
||
{
|
||
st = s->Sstruct;
|
||
if (isdehydrated(st))
|
||
break;
|
||
ph_dehydrate(&s->Sstruct);
|
||
assert(st);
|
||
symbol_tree_dehydrate(&st->Sroot);
|
||
ph_dehydrate(&st->Spvirtder);
|
||
list_dehydrate(&st->Sfldlst,(list_free_fp)symbol_dehydrate);
|
||
list_dehydrate(&st->Svirtual,(list_free_fp)mptr_dehydrate);
|
||
list_dehydrate(&st->Sopoverload,(list_free_fp)symbol_dehydrate);
|
||
list_dehydrate(&st->Scastoverload,(list_free_fp)symbol_dehydrate);
|
||
list_dehydrate(&st->Sclassfriends,(list_free_fp)symbol_dehydrate);
|
||
list_dehydrate(&st->Sfriendclass,(list_free_fp)ph_dehydrate);
|
||
list_dehydrate(&st->Sfriendfuncs,(list_free_fp)ph_dehydrate);
|
||
assert(!st->Sinlinefuncs);
|
||
|
||
baseclass_dehydrate(&st->Sbase);
|
||
baseclass_dehydrate(&st->Svirtbase);
|
||
baseclass_dehydrate(&st->Smptrbase);
|
||
baseclass_dehydrate(&st->Sprimary);
|
||
#if VBTABLES
|
||
baseclass_dehydrate(&st->Svbptrbase);
|
||
#endif
|
||
|
||
ph_dehydrate(&st->Svecctor);
|
||
ph_dehydrate(&st->Sctor);
|
||
ph_dehydrate(&st->Sdtor);
|
||
#if VBTABLES
|
||
ph_dehydrate(&st->Sprimdtor);
|
||
ph_dehydrate(&st->Spriminv);
|
||
ph_dehydrate(&st->Sscaldeldtor);
|
||
#endif
|
||
ph_dehydrate(&st->Sinvariant);
|
||
ph_dehydrate(&st->Svptr);
|
||
ph_dehydrate(&st->Svtbl);
|
||
ph_dehydrate(&st->Sopeq);
|
||
ph_dehydrate(&st->Sopeq2);
|
||
ph_dehydrate(&st->Scpct);
|
||
ph_dehydrate(&st->Sveccpct);
|
||
ph_dehydrate(&st->Salias);
|
||
ph_dehydrate(&st->Stempsym);
|
||
param_dehydrate(&st->Sarglist);
|
||
param_dehydrate(&st->Spr_arglist);
|
||
#if VBTABLES
|
||
ph_dehydrate(&st->Svbptr);
|
||
ph_dehydrate(&st->Svbptr_parent);
|
||
ph_dehydrate(&st->Svbtbl);
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
symbol_tree_dehydrate(&s->Sstruct->Sroot);
|
||
list_dehydrate(&s->Sstruct->Sfldlst,(list_free_fp)symbol_dehydrate);
|
||
ph_dehydrate(&s->Sstruct);
|
||
}
|
||
break;
|
||
|
||
case SCenum:
|
||
assert(s->Senum);
|
||
if (!isdehydrated(s->Senum))
|
||
{
|
||
if (CPP)
|
||
{ ph_dehydrate(&s->Senum->SEalias);
|
||
list_dehydrate(&s->Senumlist,(list_free_fp)ph_dehydrate);
|
||
}
|
||
ph_dehydrate(&s->Senum);
|
||
}
|
||
break;
|
||
|
||
case SCtemplate:
|
||
{ template_t *tm;
|
||
|
||
tm = s->Stemplate;
|
||
if (!isdehydrated(tm))
|
||
{
|
||
ph_dehydrate(&s->Stemplate);
|
||
list_dehydrate(&tm->TMinstances,(list_free_fp)symbol_dehydrate);
|
||
list_dehydrate(&tm->TMfriends,(list_free_fp)symbol_dehydrate);
|
||
list_dehydrate(&tm->TMnestedfriends,(list_free_fp)tmnf_dehydrate);
|
||
param_dehydrate(&tm->TMptpl);
|
||
param_dehydrate(&tm->TMptal);
|
||
token_dehydrate(&tm->TMbody);
|
||
list_dehydrate(&tm->TMmemberfuncs,(list_free_fp)tmf_dehydrate);
|
||
list_dehydrate(&tm->TMexplicit,(list_free_fp)tme_dehydrate);
|
||
list_dehydrate(&tm->TMnestedexplicit,(list_free_fp)tmne_dehydrate);
|
||
ph_dehydrate(&tm->TMnext);
|
||
symbol_dehydrate(&tm->TMpartial);
|
||
symbol_dehydrate(&tm->TMprimary);
|
||
}
|
||
break;
|
||
}
|
||
|
||
case SCnamespace:
|
||
symbol_tree_dehydrate(&s->Snameroot);
|
||
list_dehydrate(&s->Susing,(list_free_fp)symbol_dehydrate);
|
||
break;
|
||
|
||
case SCmemalias:
|
||
case SCfuncalias:
|
||
case SCadl:
|
||
list_dehydrate(&s->Spath,(list_free_fp)symbol_dehydrate);
|
||
case SCalias:
|
||
ph_dehydrate(&s->Smemalias);
|
||
break;
|
||
|
||
default:
|
||
if (s->Sflags & (SFLvalue | SFLdtorexp))
|
||
el_dehydrate(&s->Svalue);
|
||
break;
|
||
}
|
||
{ dt_t **pdt,*dt;
|
||
|
||
for (pdt = &s->Sdt;
|
||
(dt = *pdt) != NULL && !isdehydrated(dt);
|
||
pdt = &dt->DTnext)
|
||
{
|
||
ph_dehydrate(pdt);
|
||
switch (dt->dt)
|
||
{ case DT_abytes:
|
||
case DT_nbytes:
|
||
ph_dehydrate(&dt->DTpbytes);
|
||
break;
|
||
case DT_xoff:
|
||
symbol_dehydrate(&dt->DTsym);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (s->Scover)
|
||
symbol_dehydrate(&s->Scover);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/***************************
|
||
* Dehydrate threaded list of symbols.
|
||
*/
|
||
|
||
#if DEHYDRATE
|
||
void symbol_symdefs_dehydrate(symbol **ps)
|
||
{
|
||
symbol *s;
|
||
|
||
for (; *ps; ps = &s->Snext)
|
||
{
|
||
s = *ps;
|
||
symbol_debug(s);
|
||
//dbg_printf("symbol_symdefs_dehydrate(%p, '%s')\n",s,s->Sident);
|
||
symbol_dehydrate(ps);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/***************************
|
||
* Hydrate threaded list of symbols.
|
||
* Input:
|
||
* *ps start of threaded list
|
||
* *parent root of symbol table to add symbol into
|
||
* flag !=0 means add onto existing stuff
|
||
* 0 means hydrate in place
|
||
*/
|
||
|
||
#if SCPP
|
||
|
||
void symbol_symdefs_hydrate(symbol **ps,symbol **parent,int flag)
|
||
{ symbol *s;
|
||
|
||
//printf("symbol_symdefs_hydrate(flag = %d)\n",flag);
|
||
#ifdef DEBUG
|
||
int count = 0;
|
||
|
||
if (flag) symbol_tree_check(*parent);
|
||
#endif
|
||
for (; *ps; ps = &s->Snext)
|
||
{
|
||
//dbg_printf("%p ",*ps);
|
||
#ifdef DEBUG
|
||
count++;
|
||
#endif
|
||
s = dohydrate ? symbol_hydrate(ps) : *ps;
|
||
|
||
//if (s->Sclass == SCstruct)
|
||
//dbg_printf("symbol_symdefs_hydrate(%p, '%s')\n",s,s->Sident);
|
||
symbol_debug(s);
|
||
#if 0
|
||
if (tyfunc(s->Stype->Tty))
|
||
{ Outbuffer buf;
|
||
char *p1;
|
||
|
||
p1 = param_tostring(&buf,s->Stype);
|
||
dbg_printf("'%s%s'\n",cpp_prettyident(s),p1);
|
||
}
|
||
#endif
|
||
type_debug(s->Stype);
|
||
if (flag)
|
||
{ char *p;
|
||
symbol **ps;
|
||
symbol *rover;
|
||
char c;
|
||
size_t len;
|
||
|
||
p = s->Sident;
|
||
c = *p;
|
||
|
||
// Put symbol s into symbol table
|
||
|
||
#if MMFIO
|
||
if (s->Sl || s->Sr) // avoid writing to page if possible
|
||
#endif
|
||
s->Sl = s->Sr = NULL;
|
||
len = strlen(p);
|
||
p++;
|
||
ps = parent;
|
||
while ((rover = *ps) != NULL)
|
||
{ signed char cmp;
|
||
|
||
if ((cmp = c - rover->Sident[0]) == 0)
|
||
{ cmp = memcmp(p,rover->Sident + 1,len); // compare identifier strings
|
||
if (cmp == 0)
|
||
{
|
||
if (CPP && tyfunc(s->Stype->Tty) && tyfunc(rover->Stype->Tty))
|
||
{ symbol **ps;
|
||
symbol *sn;
|
||
symbol *so;
|
||
|
||
so = s;
|
||
do
|
||
{
|
||
// Tack onto end of overloaded function list
|
||
for (ps = &rover; *ps; ps = &(*ps)->Sfunc->Foversym)
|
||
{ if (cpp_funccmp(so, *ps))
|
||
{ //printf("function '%s' already in list\n",so->Sident);
|
||
goto L2;
|
||
}
|
||
}
|
||
//printf("appending '%s' to rover\n",so->Sident);
|
||
*ps = so;
|
||
L2:
|
||
sn = so->Sfunc->Foversym;
|
||
so->Sfunc->Foversym = NULL;
|
||
so = sn;
|
||
} while (so);
|
||
//printf("overloading...\n");
|
||
}
|
||
else if (s->Sclass == SCstruct)
|
||
{
|
||
if (CPP && rover->Scover)
|
||
{ ps = &rover->Scover;
|
||
rover = *ps;
|
||
}
|
||
else
|
||
if (rover->Sclass == SCstruct)
|
||
{
|
||
if (!(s->Stype->Tflags & TFforward))
|
||
{ // Replace rover with s in symbol table
|
||
//printf("Replacing '%s'\n",s->Sident);
|
||
*ps = s;
|
||
s->Sl = rover->Sl;
|
||
s->Sr = rover->Sr;
|
||
rover->Sl = rover->Sr = NULL;
|
||
rover->Stype->Ttag = (Classsym *)s;
|
||
symbol_keep(rover);
|
||
}
|
||
else
|
||
s->Stype->Ttag = (Classsym *)rover;
|
||
}
|
||
}
|
||
goto L1;
|
||
}
|
||
}
|
||
ps = (cmp < 0) ? /* if we go down left side */
|
||
&rover->Sl :
|
||
&rover->Sr;
|
||
}
|
||
*ps = s;
|
||
if (s->Sclass == SCcomdef)
|
||
{ s->Sclass = SCglobal;
|
||
outcommon(s,type_size(s->Stype));
|
||
}
|
||
}
|
||
L1: ;
|
||
} // for
|
||
#ifdef DEBUG
|
||
if (flag) symbol_tree_check(*parent);
|
||
printf("%d symbols hydrated\n",count);
|
||
#endif
|
||
}
|
||
|
||
#endif
|
||
|
||
#if 0
|
||
|
||
/*************************************
|
||
* Put symbol table s into parent symbol table.
|
||
*/
|
||
|
||
void symboltable_hydrate(symbol *s,symbol **parent)
|
||
{
|
||
while (s)
|
||
{ symbol *sl,*sr;
|
||
char *p;
|
||
|
||
symbol_debug(s);
|
||
|
||
sl = s->Sl;
|
||
sr = s->Sr;
|
||
p = s->Sident;
|
||
|
||
//dbg_printf("symboltable_hydrate('%s')\n",p);
|
||
|
||
/* Put symbol s into symbol table */
|
||
{ symbol **ps;
|
||
symbol *rover;
|
||
int c = *p;
|
||
|
||
ps = parent;
|
||
while ((rover = *ps) != NULL)
|
||
{ int cmp;
|
||
|
||
if ((cmp = c - rover->Sident[0]) == 0)
|
||
{ cmp = strcmp(p,rover->Sident); /* compare identifier strings */
|
||
if (cmp == 0)
|
||
{
|
||
if (CPP && tyfunc(s->Stype->Tty) && tyfunc(rover->Stype->Tty))
|
||
{ symbol **ps;
|
||
symbol *sn;
|
||
|
||
do
|
||
{
|
||
// Tack onto end of overloaded function list
|
||
for (ps = &rover; *ps; ps = &(*ps)->Sfunc->Foversym)
|
||
{ if (cpp_funccmp(s, *ps))
|
||
goto L2;
|
||
}
|
||
s->Sl = s->Sr = NULL;
|
||
*ps = s;
|
||
L2:
|
||
sn = s->Sfunc->Foversym;
|
||
s->Sfunc->Foversym = NULL;
|
||
s = sn;
|
||
} while (s);
|
||
}
|
||
else
|
||
{
|
||
if (!typematch(s->Stype,rover->Stype,0))
|
||
{
|
||
// cpp_predefine() will define this again
|
||
if (type_struct(rover->Stype) &&
|
||
rover->Sstruct->Sflags & STRpredef)
|
||
{ s->Sl = s->Sr = NULL;
|
||
symbol_keep(s);
|
||
}
|
||
else
|
||
synerr(EM_multiple_def,p); // already defined
|
||
}
|
||
}
|
||
goto L1;
|
||
}
|
||
}
|
||
ps = (cmp < 0) ? /* if we go down left side */
|
||
&rover->Sl :
|
||
&rover->Sr;
|
||
}
|
||
{
|
||
s->Sl = s->Sr = NULL;
|
||
*ps = s;
|
||
}
|
||
}
|
||
L1:
|
||
symboltable_hydrate(sl,parent);
|
||
s = sr;
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
|
||
/************************************
|
||
* Hydrate/dehydrate an mptr_t.
|
||
*/
|
||
|
||
#if HYDRATE
|
||
STATIC void mptr_hydrate(mptr_t **pm)
|
||
{ mptr_t *m;
|
||
|
||
m = (mptr_t *) ph_hydrate(pm);
|
||
symbol_hydrate(&m->MPf);
|
||
symbol_hydrate(&m->MPparent);
|
||
}
|
||
#endif
|
||
|
||
#if DEHYDRATE
|
||
STATIC void mptr_dehydrate(mptr_t **pm)
|
||
{ mptr_t *m;
|
||
|
||
m = *pm;
|
||
if (m && !isdehydrated(m))
|
||
{
|
||
ph_dehydrate(pm);
|
||
#if DEBUG_XSYMGEN
|
||
if (xsym_gen && ph_in_head(m->MPf))
|
||
ph_dehydrate(&m->MPf);
|
||
else
|
||
#endif
|
||
symbol_dehydrate(&m->MPf);
|
||
symbol_dehydrate(&m->MPparent);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/************************************
|
||
* Hydrate/dehydrate a baseclass_t.
|
||
*/
|
||
|
||
#if HYDRATE
|
||
STATIC void baseclass_hydrate(baseclass_t **pb)
|
||
{ baseclass_t *b;
|
||
|
||
assert(pb);
|
||
while (isdehydrated(*pb))
|
||
{
|
||
b = (baseclass_t *) ph_hydrate(pb);
|
||
|
||
ph_hydrate(&b->BCbase);
|
||
ph_hydrate(&b->BCpbase);
|
||
list_hydrate(&b->BCpublics,(list_free_fp)symbol_hydrate);
|
||
#if VBTABLES
|
||
#else
|
||
symbol_hydrate(&b->param);
|
||
#endif
|
||
list_hydrate(&b->BCmptrlist,(list_free_fp)mptr_hydrate);
|
||
symbol_hydrate(&b->BCvtbl);
|
||
Classsym_hydrate(&b->BCparent);
|
||
|
||
pb = &b->BCnext;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/**********************************
|
||
* Dehydrate a baseclass_t.
|
||
*/
|
||
|
||
#if DEHYDRATE
|
||
STATIC void baseclass_dehydrate(baseclass_t **pb)
|
||
{ baseclass_t *b;
|
||
|
||
while ((b = *pb) != NULL && !isdehydrated(b))
|
||
{
|
||
ph_dehydrate(pb);
|
||
|
||
#if DEBUG_XSYMGEN
|
||
if (xsym_gen && ph_in_head(b))
|
||
return;
|
||
#endif
|
||
|
||
ph_dehydrate(&b->BCbase);
|
||
ph_dehydrate(&b->BCpbase);
|
||
list_dehydrate(&b->BCpublics,(list_free_fp)symbol_dehydrate);
|
||
#if VBTABLES
|
||
#else
|
||
symbol_dehydrate(&b->param);
|
||
#endif
|
||
list_dehydrate(&b->BCmptrlist,(list_free_fp)mptr_dehydrate);
|
||
symbol_dehydrate(&b->BCvtbl);
|
||
Classsym_dehydrate(&b->BCparent);
|
||
|
||
pb = &b->BCnext;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/***************************
|
||
* Look down baseclass list to find sbase.
|
||
* Returns:
|
||
* NULL not found
|
||
* pointer to baseclass
|
||
*/
|
||
|
||
baseclass_t *baseclass_find(baseclass_t *bm,Classsym *sbase)
|
||
{
|
||
symbol_debug(sbase);
|
||
for (; bm; bm = bm->BCnext)
|
||
if (bm->BCbase == sbase)
|
||
break;
|
||
return bm;
|
||
}
|
||
|
||
baseclass_t *baseclass_find_nest(baseclass_t *bm,Classsym *sbase)
|
||
{
|
||
symbol_debug(sbase);
|
||
for (; bm; bm = bm->BCnext)
|
||
{
|
||
if (bm->BCbase == sbase ||
|
||
baseclass_find_nest(bm->BCbase->Sstruct->Sbase, sbase))
|
||
break;
|
||
}
|
||
return bm;
|
||
}
|
||
|
||
/******************************
|
||
* Calculate number of baseclasses in list.
|
||
*/
|
||
|
||
#if VBTABLES
|
||
|
||
int baseclass_nitems(baseclass_t *b)
|
||
{ int i;
|
||
|
||
for (i = 0; b; b = b->BCnext)
|
||
i++;
|
||
return i;
|
||
}
|
||
|
||
#endif
|
||
|
||
|
||
/*****************************
|
||
* Go through symbol table preparing it to be written to a precompiled
|
||
* header. That means removing references to things in the .OBJ file.
|
||
*/
|
||
|
||
#if SCPP
|
||
|
||
void symboltable_clean(symbol *s)
|
||
{
|
||
while (s)
|
||
{
|
||
struct_t *st;
|
||
|
||
//printf("clean('%s')\n",s->Sident);
|
||
if (config.fulltypes != CVTDB && s->Sxtrnnum && s->Sfl != FLreg)
|
||
s->Sxtrnnum = 0; // eliminate debug info type index
|
||
switch (s->Sclass)
|
||
{
|
||
case SCstruct:
|
||
s->Stypidx = 0;
|
||
st = s->Sstruct;
|
||
assert(st);
|
||
symboltable_clean(st->Sroot);
|
||
//list_apply(&st->Sfldlst,(list_free_fp)symboltable_clean);
|
||
break;
|
||
|
||
case SCtypedef:
|
||
case SCenum:
|
||
s->Stypidx = 0;
|
||
break;
|
||
#if 1
|
||
case SCtemplate:
|
||
{ template_t *tm = s->Stemplate;
|
||
|
||
list_apply(&tm->TMinstances,(list_free_fp)symboltable_clean);
|
||
break;
|
||
}
|
||
#endif
|
||
case SCnamespace:
|
||
symboltable_clean(s->Snameroot);
|
||
break;
|
||
|
||
default:
|
||
if (s->Sxtrnnum && s->Sfl != FLreg)
|
||
s->Sxtrnnum = 0; // eliminate external symbol index
|
||
if (tyfunc(s->Stype->Tty))
|
||
{
|
||
func_t *f = s->Sfunc;
|
||
SYMIDX si;
|
||
|
||
debug(assert(f));
|
||
|
||
list_apply(&f->Fsymtree,(list_free_fp)symboltable_clean);
|
||
for (si = 0; si < f->Flocsym.top; si++)
|
||
symboltable_clean(f->Flocsym.tab[si]);
|
||
if (f->Foversym)
|
||
symboltable_clean(f->Foversym);
|
||
if (f->Fexplicitspec)
|
||
symboltable_clean(f->Fexplicitspec);
|
||
}
|
||
break;
|
||
}
|
||
if (s->Sl)
|
||
symboltable_clean(s->Sl);
|
||
if (s->Scover)
|
||
symboltable_clean(s->Scover);
|
||
s = s->Sr;
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
#if SCPP
|
||
|
||
/*
|
||
* Balance our symbol tree in place. This is nice for precompiled headers, since they
|
||
* will typically be written out once, but read in many times. We balance the tree in
|
||
* place by traversing the tree inorder and writing the pointers out to an ordered
|
||
* list. Once we have a list of symbol pointers, we can create a tree by recursively
|
||
* dividing the list, using the midpoint of each division as the new root for that
|
||
* subtree.
|
||
*/
|
||
|
||
struct Balance
|
||
{
|
||
unsigned nsyms;
|
||
symbol **array;
|
||
unsigned index;
|
||
};
|
||
|
||
static Balance balance;
|
||
|
||
STATIC void count_symbols(symbol *s)
|
||
{
|
||
while (s)
|
||
{
|
||
balance.nsyms++;
|
||
switch (s->Sclass)
|
||
{
|
||
case SCnamespace:
|
||
symboltable_balance(&s->Snameroot);
|
||
break;
|
||
|
||
case SCstruct:
|
||
symboltable_balance(&s->Sstruct->Sroot);
|
||
break;
|
||
}
|
||
count_symbols(s->Sl);
|
||
s = s->Sr;
|
||
}
|
||
}
|
||
|
||
STATIC void place_in_array(symbol *s)
|
||
{
|
||
while (s)
|
||
{
|
||
place_in_array(s->Sl);
|
||
balance.array[balance.index++] = s;
|
||
s = s->Sr;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Create a tree in place by subdividing between lo and hi inclusive, using i
|
||
* as the root for the tree. When the lo-hi interval is one, we've either
|
||
* reached a leaf or an empty node. We subdivide below i by halving the interval
|
||
* between i and lo, and using i-1 as our new hi point. A similar subdivision
|
||
* is created above i.
|
||
*/
|
||
STATIC symbol * create_tree(int i, int lo, int hi)
|
||
{
|
||
symbol *s = balance.array[i];
|
||
|
||
if (i < lo || i > hi) /* empty node ? */
|
||
return NULL;
|
||
|
||
assert((unsigned) i < balance.nsyms);
|
||
if (i == lo && i == hi) { /* leaf node ? */
|
||
s->Sl = NULL;
|
||
s->Sr = NULL;
|
||
return s;
|
||
}
|
||
|
||
s->Sl = create_tree((i + lo) / 2, lo, i - 1);
|
||
s->Sr = create_tree((i + hi + 1) / 2, i + 1, hi);
|
||
|
||
return s;
|
||
}
|
||
|
||
#define METRICS 0
|
||
|
||
#if METRICS
|
||
void symbol_table_metrics(void);
|
||
#endif
|
||
|
||
void symboltable_balance(symbol **ps)
|
||
{
|
||
Balance balancesave;
|
||
#if METRICS
|
||
long ticks;
|
||
|
||
dbg_printf("symbol table before balance:\n");
|
||
symbol_table_metrics();
|
||
ticks = clock();
|
||
#endif
|
||
balancesave = balance; // so we can nest
|
||
balance.nsyms = 0;
|
||
count_symbols(*ps);
|
||
//dbg_printf("Number of global symbols = %d\n",balance.nsyms);
|
||
|
||
#if __INTSIZE == 2
|
||
// Don't balance tree if we get 16 bit overflow
|
||
if (balance.nsyms >= (unsigned)(0x10000 / sizeof(symbol *)))
|
||
goto Lret;
|
||
#endif
|
||
|
||
// Use malloc instead of mem because of pagesize limits
|
||
balance.array = (symbol **) malloc(balance.nsyms * sizeof(symbol *));
|
||
if (!balance.array)
|
||
goto Lret; // no error, just don't balance
|
||
|
||
balance.index = 0;
|
||
place_in_array(*ps);
|
||
|
||
*ps = create_tree(balance.nsyms / 2, 0, balance.nsyms - 1);
|
||
|
||
free(balance.array);
|
||
#if METRICS
|
||
dbg_printf("time to balance: %ld\n", clock() - ticks);
|
||
dbg_printf("symbol table after balance:\n");
|
||
symbol_table_metrics();
|
||
#endif
|
||
Lret:
|
||
balance = balancesave;
|
||
}
|
||
|
||
#endif
|
||
|
||
/*****************************************
|
||
* Symbol table search routine for members of structs, given that
|
||
* we don't know which struct it is in.
|
||
* Give error message if it appears more than once.
|
||
* Returns:
|
||
* NULL member not found
|
||
* symbol* symbol matching member
|
||
*/
|
||
|
||
#if SCPP
|
||
|
||
struct Paramblock // to minimize stack usage in helper function
|
||
{ const char *id; // identifier we are looking for
|
||
symbol *sm; // where to put result
|
||
symbol *s;
|
||
};
|
||
|
||
STATIC void membersearchx(struct Paramblock *p,symbol *s)
|
||
{ symbol *sm;
|
||
list_t sl;
|
||
|
||
while (s)
|
||
{ symbol_debug(s);
|
||
|
||
switch (s->Sclass)
|
||
{ case SCstruct:
|
||
for (sl = s->Sstruct->Sfldlst; sl; sl = list_next(sl))
|
||
{ sm = list_symbol(sl);
|
||
symbol_debug(sm);
|
||
if ((sm->Sclass == SCmember || sm->Sclass == SCfield) &&
|
||
strcmp(p->id,sm->Sident) == 0)
|
||
{
|
||
if (p->sm && p->sm->Smemoff != sm->Smemoff)
|
||
synerr(EM_ambig_member,p->id,s->Sident,p->s->Sident); // ambiguous reference to id
|
||
p->s = s;
|
||
p->sm = sm;
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (s->Sl)
|
||
membersearchx(p,s->Sl);
|
||
s = s->Sr;
|
||
}
|
||
}
|
||
|
||
symbol *symbol_membersearch(const char *id)
|
||
{
|
||
list_t sl;
|
||
struct Paramblock pb;
|
||
Scope *sc;
|
||
|
||
pb.id = id;
|
||
pb.sm = NULL;
|
||
for (sc = scope_end; sc; sc = sc->next)
|
||
{
|
||
if (sc->sctype & (CPP ? (SCTglobal | SCTlocal) : (SCTglobaltag | SCTtag)))
|
||
membersearchx((struct Paramblock *)&pb,(symbol *)sc->root);
|
||
}
|
||
return pb.sm;
|
||
}
|
||
|
||
/*******************************************
|
||
* Generate debug info for global struct tag symbols.
|
||
*/
|
||
|
||
STATIC void symbol_gendebuginfox(symbol *s)
|
||
{
|
||
for (; s; s = s->Sr)
|
||
{
|
||
if (s->Sl)
|
||
symbol_gendebuginfox(s->Sl);
|
||
if (s->Scover)
|
||
symbol_gendebuginfox(s->Scover);
|
||
switch (s->Sclass)
|
||
{
|
||
case SCenum:
|
||
if (CPP && s->Senum->SEflags & SENnotagname)
|
||
break;
|
||
goto Lout;
|
||
case SCstruct:
|
||
if (s->Sstruct->Sflags & STRanonymous)
|
||
break;
|
||
goto Lout;
|
||
case SCtypedef:
|
||
Lout:
|
||
if (!s->Stypidx)
|
||
cv_outsym(s);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void symbol_gendebuginfo()
|
||
{ Scope *sc;
|
||
|
||
for (sc = scope_end; sc; sc = sc->next)
|
||
{
|
||
if (sc->sctype & (SCTglobaltag | SCTglobal))
|
||
symbol_gendebuginfox((symbol *)sc->root);
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
#endif /* !SPP */
|
||
|