/*** DEBSYM.C - symbol lookup routines for expression evaluator */ #include "debexpr.h" #include "debsym.h" #define WINDBG_POINTERS_MACROS_ONLY #include "sundown.h" #undef WINDBG_POINTERS_MACROS_ONLY // enum specifying return from IsDominated typedef enum { DOM_ambiguous, DOM_keep, DOM_replace } DOM_t; // Return values from SearchClassName typedef enum { SCN_error, // error, abort search SCN_notfound, // not found SCN_found, // found SCN_rewrite // found and this pointer inserted } SCN_t; // Return values from MatchMethod typedef enum { MTH_error, // error - abort search MTH_found, // found without error } MTH_t; typedef struct HSL_restart_t { search_t Name; HSYM hSym; HSYML_t state; ulong mask; } HSL_restart_t; static char *vtabptr = "#vptr#"; static HDEP hSymClass = 0; static psymclass_t pSymClass = NULL; static HDEP hVBDom = 0; static pdombase_t pVBDom = NULL; static HDEP hVBSearch = 0; static pdombase_t pVBSearch = NULL; static psearch_t pNameFirst = NULL; pnode_t AddETConst (pnode_t, UOFFSET, CV_typ_t); pnode_t AddETExpr (pnode_t, CV_typ_t, UOFFSET, UOFFSET, CV_typ_t); pnode_t AddETInit (pnode_t, CV_typ_t); bool_t AddHSYM (psearch_t, HSYM, PHSL_HEAD *, ulong, HDEP * ); SCN_t AddVBList (psymclass_t, pdombase_t *, HDEP *); SCN_t AddVBType (pdombase_t *, HDEP *, CV_typ_t); ulong AmbFromList (psearch_t); bool_t AmbToList (psearch_t); bool_t CheckDupAmb (psearch_t); bool_t DebLoadConst (peval_t, CONSTPTR, HSYM); SCN_t DupSymCl (psearch_t); SCN_t FindIntro (psearch_t); SCN_t GenQualExpr (psearch_t); HDEP GenQualName (psearch_t, psymclass_t); bool_t GrowTMList (void); SCN_t IncrSymBase (void); bool_t InitMod (psearch_t); DOM_t IsDominated (psymclass_t, psymclass_t); bool_t IsIntroVirtInMlist (ulong , CV_typ_t, UOFFSET *); bool_t IsIntroVirt (CV_typ_t); bool_t LineNumber (psearch_t); void MatchArgs (peval_t, psearch_t, CV_fldattr_t, UOFFSET, bool_t); HR_t FASTCALL MatchFunction (psearch_t); void MoveSymCl (HDEP hSymCl); SCN_t OverloadToAmbList (psearch_t, psymclass_t); SCN_t MethodsToAmbList (psearch_t, psymclass_t); bool_t ParseRegister (psearch_t); void PurgeAmbCl (psearch_t); SCN_t RecurseBase (psearch_t, CV_typ_t, CV_typ_t, UOFFSET, UOFFSET, CV_fldattr_t, bool_t); SCN_t RemoveAmb (psearch_t); SCN_t SearchAERule (psearch_t); SCN_t SearchBases (psearch_t); SCN_t SearchBType (psearch_t); SCN_t SearchClassName (psearch_t); bool_t SearchQualName (psearch_t, psymclass_t, HDEP, bool_t); SCN_t SearchRoot (psearch_t); SCN_t SetBase (psearch_t, CV_typ_t, CV_typ_t, UOFFSET, UOFFSET, CV_fldattr_t, bool_t); SCN_t SetBPValue (psearch_t); SCN_t SetValue (psearch_t); HR_t SymAmbToList (psearch_t); CV_typ_t SkipModifiers(HMOD mod, CV_typ_t type); bool_t SymToNode (psearch_t); bool_t VBSearched (CV_typ_t); bool_t VBaseFound (psearch_t); bool_t FASTCALL InsertThis (psearch_t); MTH_t MatchMethod (psearch_t, psymclass_t); // NOTE: OpName[0] MUST be the this string OPNAME OpName[] = { {"\x004""this"}, // OP_this {"\x00b""operator->*"}, // OP_Opmember {"\x00b""operator>>="}, // OP_Orightequal {"\x00b""operator<<="}, // OP_Oleftequal {"\x00a""operator()"}, // OP_Ofunction {"\x00a""operator[]"}, // OP_Oarray {"\x00a""operator+="}, // OP_Oplusequal {"\x00a""operator-="}, // OP_Ominusequal {"\x00a""operator*="}, // OP_Otimesequal {"\x00a""operator/="}, // OP_Odivequal {"\x00a""operator%="}, // OP_Opcentequal {"\x00a""operator&="}, // OP_Oandequal {"\x00a""operator^="}, // OP_Oxorequal {"\x00a""operator|="}, // OP_Oorequal {"\x00a""operator<<"}, // OP_Oshl {"\x00a""operator>>"}, // OP_Oshr {"\x00a""operator=="}, // OP_Oequalequal {"\x00a""operator!="}, // OP_Obangequal {"\x00a""operator<="}, // OP_Olessequal {"\x00a""operator>="}, // OP_Ogreatequal {"\x00a""operator&&"}, // OP_Oandand {"\x00a""operator||"}, // OP_Ooror {"\x00a""operator++"}, // OP_Oincrement {"\x00a""operator--"}, // OP_Odecrement {"\x00a""operator->"}, // OP_Opointsto {"\x009""operator+"}, // OP_Oplus {"\x009""operator-"}, // OP_Ominus {"\x009""operator*"}, // OP_Ostar {"\x009""operator/"}, // OP_Odivide {"\x009""operator%"}, // OP_Opercent {"\x009""operator^"}, // OP_Oxor {"\x009""operator&"}, // OP_Oand {"\x009""operator|"}, // OP_Oor {"\x009""operator~"}, // OP_Otilde {"\x009""operator!"}, // OP_Obang {"\x009""operator="}, // OP_Oequal {"\x009""operator<"}, // OP_Oless {"\x009""operator>"}, // OP_Ogreater {"\x009""operator,"}, // OP_Ocomma {"\x012""operator new"}, // OP_Onew {"\x015""operator delete"} // OP_Odelete }; // Symbol searching and search initialization routines /** InitSearchBase - initialize search for base class * InitSearchBase (bnOp, typD, typ, pName, pv) * Entry bnOp = based pointer to OP_cast node * bn = based pointer to cast string * typD = type of derived class * typB = type of desired base class * pName = pointer to symbol search structure * pv = pointer to value node * Exit search structure initialized for SearchSym * Returns pointer to search symbol structure */ void InitSearchBase ( bnode_t bnOp, CV_typ_t typD, CV_typ_t typB, psearch_t pName, peval_t pv ) { // set starting context for symbol search to current context memset (pName, 0, sizeof (*pName)); pName->initializer = INIT_base; pName->pv = pv; pName->typeIn = typD; pName->typeOut = typB; pName->scope = SCP_class; pName->CXTT = *pCxt; pName->bn = 0; pName->bnOp = bnOp; pName->state = SYM_bclass; pName->CurClass = typD; } #ifdef NEVER /** InitSearchtDef - initialize typedef symbol search * InitSearctDef (pName, iClass, tDef, scope, clsmask) * Entry iClass = initial class if explicit class reference * tDef = index of typedef * scope = mask describing scope of search * clsmask = mask describing permitted class elements * Exit search structure initialized for SearchSym * Returns pointer to search symbol structure */ void InitSearchtDef ( psearch_t pName, peval_t pv, ulong scope ) { char NullString = 0; // set starting context for symbol search to current context memset (pName, 0, sizeof (*pName)); pName->initializer = INIT_tdef; pName->sstr.lpName = &NullString; pName->sstr.cb = 0; pName->pfnCmp = TDCMP; pName->scope = scope; pName->CXTT = *pCxt; pName->pv = pv; pName->typeIn = EVAL_TYP (pv); pName->sstr.searchmask |= SSTR_symboltype | SSTR_NoHash; pName->sstr.symtype = S_UDT; pName->state = SYM_init; } #endif /** InitSearchAERule - initialize search for auto-expansion rule * InitSearchAErule (pName, pv, typ, hMod) * Entry pName = pointer to search structure * pv = pointer to eval_node to receive result * typ = type index of class to be auto-expanded * hMod = handle to module where typ is defined * Exit search structure initialized for SearchSym * Returns void */ void InitSearchAErule ( psearch_t pName, peval_t pv, CV_typ_t typ, HMOD hMod ) { // set starting context for symbol search to current context memset (pName, 0, sizeof (*pName)); pName->initializer = INIT_AErule; pName->pfnCmp = 0; pName->sstr.lpName = (uchar *) ""; pName->pv = pv; SHGetCxtFromHmod (hMod, &pName->CXTT); pName->state = SYM_init; // restrict searching to class scope pName->ExpClass = typ; pName->scope = SCP_class; } /** SearchCFlag - initialize compile flags symbol search * SearchCFlag (pName, iClass, scope, clsmask) * Entry pName = pointer to symbol search structure * Exit search structure initialized for SearchSym * Returns pointer to search symbol structure */ HSYM SearchCFlag (void) { search_t Name; CXT CXTTOut; // set starting context for symbol search to current context memset (&Name, 0, sizeof (Name)); Name.pfnCmp = (PFNCMP) CSCMP; Name.CXTT = *pCxt; Name.sstr.searchmask |= SSTR_symboltype; Name.sstr.symtype = S_COMPILE; if (InitMod (&Name) == TRUE) { SHGetCxtFromHmod (Name.hMod, &Name.CXTT); if ((Name.hSym = SHFindNameInContext (Name.hSym, &Name.CXTT, &Name.sstr, pExState->state.fCase, Name.pfnCmp, &CXTTOut)) != 0) { return (Name.hSym); } } // error in context initialization or compile flag symbol not found return (0); } /** SetAmbiant - set ambiant code or data model * mode = SetAmbiant (flag) * Entry flag = TRUE if ambiant data model * flag = FALSE if ambiant code model * Exit none * Returns ambiant model C7_... from the compile flags symbol * if the compile flags symbol is not found, C7_NEAR is returned */ CV_ptrtype_e SetAmbiant ( bool_t isdata ) { HSYM hCFlag; CFLAGPTR pCFlag; CV_ptrtype_e type; Unreferenced( isdata ); type = (TargetMachine == mptia64)? CV_PTR_64: CV_PTR_NEAR32; #if !defined(TARGMAC68K) if ((hCFlag = SearchCFlag ()) == 0) { // compile flag symbol not found, set model to near or near32 } else { pCFlag = (CFLAGPTR) MHOmfLock (hCFlag); switch (pCFlag->flags.ambdata) { default: DASSERT (FALSE); case CV_CFL_DNEAR: type = (TargetMachine == mptia64)? CV_PTR_64: CV_PTR_NEAR32; break; case CV_CFL_DFAR: type = CV_PTR_FAR32; break; case CV_CFL_DHUGE: type = CV_PTR_HUGE; break; } } MHOmfUnLock (hCFlag); #else Unreferenced(hCFlag); Unreferenced(pCFlag); #endif return (type); } /** GetHSYMList - get HSYM list for context * status = EEGetHSYMList (phSYMl, pCXT, mask, pRE, fEnableProlog) * Entry phSYML = pointer to handle to symbol list * pCXT = pointer to context * mask = selection mask * pRE = pointer to regular expression * fEnableProlog = FALSE if function scoped symbols only after prolog * fEnableProlog = TRUE if function scoped symbols during prolog * Exit *phMem = handle for HSYM list buffer * Returns EENOERROR if no error * status code if error */ EESTATUS GetHSYMList ( HDEP *phSYML, PCXT pCxt, ulong mask, uchar *pRE, SHFLAG fEnableProlog ) { search_t Name = {0}; CXT CXTTOut; HSYM hSym = 0; PHSL_HEAD pHSLHead; HSYML_t state; HSL_restart_t *pRestart; bool_t fRestart; bool_t isprolog; bool_t fCaseSensitive; if (mask & HSYMR_nocase) { mask &= ~HSYMR_nocase; fCaseSensitive = FALSE; } else fCaseSensitive = TRUE; if (*phSYML == 0) { // allocate and initialize buffer if ((*phSYML = MemAllocate (HSYML_SIZE)) == 0) { return (EECATASTROPHIC); } pHSLHead = (PHSL_HEAD) MemLock (*phSYML); memset (pHSLHead, 0, pHSLHead->size); pHSLHead->size = HSYML_SIZE; pHSLHead->remaining = pHSLHead->size - sizeof ( HSL_HEAD ); pHSLHead->pHSLList = (PHSL_LIST)(((uchar *)pHSLHead) + sizeof (HSL_HEAD)); state = HSYML_lexical; Name.initializer = INIT_RE; Name.pfnCmp = (PFNCMP) FNCMP; Name.sstr.searchmask |= SSTR_RE; Name.CXTT = *pCxt; Name.hMod = pCxt->hMod; if ( pCxt->hMod ) { Name.hExe = SHHexeFromHmod ( pCxt->hMod ); } else { // not valid to call SHHexeFromHmod with an Hmod of 0, // so set Hexe explicitly Name.hExe = 0; } if ( pRE && *pRE ) { Name.sstr.pRE = pRE; } fRestart = FALSE; } else { pHSLHead = (PHSL_HEAD) MemLock (*phSYML); pRestart = (HSL_restart_t *) MemLock (pHSLHead->restart); Name = pRestart->Name; mask = pRestart->mask; state = pRestart->state; hSym = pRestart->hSym; pHSLHead->blockcnt = 0; pHSLHead->symbolcnt = 0; pHSLHead->remaining = pHSLHead->size - sizeof ( HSL_HEAD ); pHSLHead->pHSLList = (PHSL_LIST)(((uchar *)pHSLHead) + sizeof (HSL_HEAD)); MemUnLock (pHSLHead->restart); memset ((uchar *)pHSLHead + sizeof (HSL_HEAD), 0, pHSLHead->size - sizeof (HSL_HEAD)); AddHSYM (&Name, hSym, &pHSLHead, state, phSYML); fRestart = TRUE; Name.hSym = hSym; } switch (state) { case HSYML_lexical: if (mask & HSYMR_lexical) { // search up the lexical scope to but not including the // function level while (SHIsCXTBlk (&Name.CXTT)) { while ((hSym = SHFindNameInContext (Name.hSym, &Name.CXTT, &Name.sstr, fCaseSensitive, (PFNCMP) FNCMP, &CXTTOut)) != 0) { if (AddHSYM (&Name, hSym, &pHSLHead, HSYMR_lexical, phSYML) == FALSE) { goto hsyml_exit; } Name.hSym = hSym; } // go to the parent scope SHGoToParent (&Name.CXTT, &CXTTOut); // reset current symbol Name.CXTT = CXTTOut; Name.hSym = 0; } mask &= ~HSYMR_lexical; } case HSYML_function: if (mask & HSYMR_function) { if (fRestart == FALSE) { Name.hSym = 0; Name.CXTT.hBlk = 0; } fRestart = FALSE; state = HSYML_function; if ( Name.CXTT.hMod != 0 ) { isprolog = SHIsInProlog (&Name.CXTT); } while (!SHIsCXTMod (&Name.CXTT) && Name.CXTT.hMod != 0) { while ((hSym = SHFindNameInContext ( Name.hSym, &Name.CXTT, &Name.sstr, fCaseSensitive, (PFNCMP) FNCMP, &CXTTOut)) != 0 ) { BOOL fAddSym = TRUE; if ((isprolog == TRUE) && (fEnableProlog == FALSE)) { // we want to reject bp_relative and register // stuff if we are in the prolog or epilog of // a function if (!fValidInProlog (hSym, FALSE)) { fAddSym = FALSE; } } if ( fAddSym ) { ulong len; SYMPTR pSym = (SYMPTR) MHOmfLock (hSym); switch (pSym->rectyp) { case S_BPREL32: if (((BPRELPTR32)pSym)->off >= 0) { // This is a formal argument len = ((BPRELPTR32)pSym)->name[0]; if ((len == 12) && (_tcsncmp((_TXCHAR *) ((BPRELPTR32)pSym)->name+1, "__$ReturnUdt", len) == 0)) { fAddSym = FALSE; } } break; case S_REGREL32: if (((LPREGREL32)pSym)->off >= 0) { // Formal parameter len = ((LPREGREL32)pSym)->name[0]; if ((len == 12) && (_tcsncmp((_TXCHAR *) ((LPREGREL32)pSym)->name+1, "__$ReturnUdt", len) == 0)) { fAddSym = FALSE; } } break; default: fAddSym = TRUE; break; } MHOmfUnLock (hSym); } if ( fAddSym ) { if (AddHSYM (&Name, hSym, &pHSLHead, HSYMR_function, phSYML) == FALSE) { goto hsyml_exit; } } Name.hSym = hSym; } // go to the parent scope SHGoToParent (&Name.CXTT, &CXTTOut); // reset current symbol Name.CXTT = CXTTOut; Name.hSym = 0; } mask &= ~HSYMR_function; } case HSYML_class: if (mask & HSYMR_class) { if (fRestart == FALSE) { Name.hSym = 0; if (ClassImp != 0) { Name.CurClass = ClassImp; } } fRestart = FALSE; if ((Name.CurClass != 0)) { DASSERT (FALSE); // need to do equivalent of EEGetChild on this } mask &= ~HSYMR_class; } case HSYML_module: if (mask & HSYMR_module) { if (fRestart == FALSE) { SHGetCxtFromHmod (Name.hMod, &Name.CXTT); Name.hSym = 0; } fRestart = FALSE; Name.state = (symstate_t) HSYML_module; while ((hSym = SHFindNameInContext (Name.hSym, &Name.CXTT, &Name.sstr, fCaseSensitive, Name.pfnCmp, &CXTTOut)) != 0) { if (AddHSYM (&Name, hSym, &pHSLHead, HSYMR_module, phSYML) == FALSE) { goto hsyml_exit; } Name.hSym = hSym; } mask &= ~HSYMR_module; } case HSYML_global: // search global symbol table if (mask & HSYMR_global) { if (fRestart == FALSE) { Name.hSym = 0; } fRestart = FALSE; Name.state = (symstate_t) HSYML_global; Name.sstr.searchmask |= SSTR_NoHash; while ((hSym = SHFindNameInGlobal (Name.hSym, &Name.CXTT, &Name.sstr, fCaseSensitive, Name.pfnCmp, &CXTTOut)) != 0) { if (AddHSYM (&Name, hSym, &pHSLHead, HSYMR_global, phSYML) == FALSE) { goto hsyml_exit; } Name.hSym = hSym; } mask &= ~HSYMR_global; } case HSYML_exe: if (mask & HSYMR_exe) { Name.state = (symstate_t) HSYML_exe; if (fRestart == FALSE) { Name.hModCur = SHGetNextMod (Name.hExe, Name.hMod); Name.hSym = 0; } fRestart = FALSE; Name.sstr.searchmask |= SSTR_NoHash; do { SHGetCxtFromHmod (Name.hModCur, &Name.CXTT); while ((hSym = SHFindNameInContext (Name.hSym, &Name.CXTT, &Name.sstr, fCaseSensitive, Name.pfnCmp, &CXTTOut)) != 0) { if (AddHSYM (&Name, hSym, &pHSLHead, HSYMR_exe, phSYML) == FALSE) { goto hsyml_exit; } Name.hSym = hSym; } } while (Name.hSym = 0, (Name.hModCur = SHGetNextMod (Name.hExe, Name.hModCur)) != Name.hMod); mask &= ~HSYMR_exe; } case HSYML_public: if (mask & HSYMR_public && Name.hExe) { if (fRestart == FALSE) { hSym = 0; } fRestart = FALSE; Name.state = (symstate_t) HSYML_public; Name.sstr.searchmask |= SSTR_NoHash; while ((hSym = PHFindNameInPublics (hSym, Name.hExe, &Name.sstr, fCaseSensitive, Name.pfnCmp)) != 0) { if (AddHSYM (&Name, hSym, &pHSLHead, HSYMR_public, phSYML) == FALSE) { goto hsyml_exit; } Name.hSym = hSym; } mask &= ~HSYMR_public; } } pHSLHead->status.endsearch = TRUE; MemUnLock (*phSYML); return (EENOERROR); hsyml_exit: if (pHSLHead->restart == 0) { // allocate restart buffer if ((pHSLHead->restart = MemAllocate (sizeof (HSL_restart_t))) == 0) { pHSLHead->status.fatal = TRUE; MemUnLock (*phSYML); return (EENOMEMORY); } } pRestart = (HSL_restart_t *) MemLock (pHSLHead->restart); pRestart->Name = Name; pRestart->mask = mask; pRestart->state = state; pRestart->hSym = hSym; MemUnLock (pHSLHead->restart); MemUnLock (*phSYML); return (EENOERROR); } bool_t GrowHSL( HDEP *phSYML, PHSL_HEAD *ppHSLHead ) { unsigned int bias; int newsize; HDEP h; bias = (unsigned int)((uchar *)(*ppHSLHead)->pHSLList - (uchar *)(*ppHSLHead)); newsize = (*ppHSLHead)->size + HSYML_SIZE; MemUnLock(*phSYML); h = MemReAlloc(*phSYML, newsize); if (!h) { return FALSE; } *phSYML = h; *ppHSLHead = MemLock(h); (*ppHSLHead)->size += HSYML_SIZE; (*ppHSLHead)->remaining += HSYML_SIZE; (*ppHSLHead)->pHSLList = (PHSL_LIST) ( (uchar *)(*ppHSLHead) + bias ); return TRUE; } bool_t AddHSYM ( psearch_t pName, HSYM hSym, PHSL_HEAD *ppHSLHead, ulong request, HDEP *phSYML ) { PHSL_LIST pHSLList; pHSLList = (*ppHSLHead)->pHSLList; // check usability of current block if (pHSLList->status.isused == TRUE) { // block has been used, check for same context if (memcmp (&pHSLList->Cxt, &pName->CXTT, sizeof (CXT)) != 0) { // context has changed pHSLList->status.complete = TRUE; // Allocate a new HSL_LIST at the end of the list. // grow the list if it is full. if ((*ppHSLHead)->remaining < sizeof(HSL_LIST) + sizeof(HSYM)) { if (!GrowHSL(phSYML, ppHSLHead)) { return FALSE; } } // this will be decremented in the !hascxt code below //(*ppHSLHead)->remaining -= sizeof( HSL_LIST ); // Point the pointer to the new list: (*ppHSLHead)->pHSLList = (PHSL_LIST)( (uchar *)((*ppHSLHead)->pHSLList) + sizeof ( HSL_LIST ) + (*ppHSLHead)->pHSLList->symbolcnt * sizeof ( HSYM ) ); pHSLList = (*ppHSLHead)->pHSLList; } } if (pHSLList->status.hascxt == FALSE) { (*ppHSLHead)->blockcnt++; (*ppHSLHead)->remaining -= sizeof (HSL_LIST); pHSLList->status.hascxt = TRUE; pHSLList->Cxt = pName->CXTT; pHSLList->request = request; } // grow the list if it is full. if ((*ppHSLHead)->remaining < sizeof (HSYM)) { if (!GrowHSL(phSYML, ppHSLHead)) { return FALSE; } else { pHSLList = (*ppHSLHead)->pHSLList; } } pHSLList->status.isused = TRUE; pHSLList->hSym[pHSLList->symbolcnt++] = hSym; (*ppHSLHead)->remaining -= sizeof (HSYM); return (TRUE); } // search for the base sym of the base pointer // Entry pName = structure describing the base pointer name // Exit pName.eval reflects the bound base info // Returns HR_ if base sym found HR_t SearchBasePtrBase ( psearch_t pName ) { search_t lName = *pName; plfPointer pType; SYMPTR pSym; unsigned short lrectyp; eval_t eval; peval_t lpv = &eval; ulong savefEProlog = pExState->state.fEProlog; HR_t retval = HR_notfound; pExState->state.fEProlog = TRUE; // KLUDGE to get around CXT complications eval = *pName->pv; CLEAR_EVAL_FLAGS (lpv); // an enregistered primitive EVAL_IS_REG (lpv) = EVAL_IS_REG(pName->pv); EVAL_IS_BPREL (lpv) = EVAL_IS_BPREL(pName->pv); lName.hSym = 0; // start search at beginning of CXT lName.pv = lpv; DASSERT(!CV_IS_PRIMITIVE (EVAL_TYP(lpv))); DASSERT (EVAL_MOD (lpv) != 0); EVAL_TYPDEF (lpv) = THGetTypeFromIndex (EVAL_MOD (lpv), EVAL_TYP(lpv)); DASSERT (EVAL_TYPDEF (lpv) != 0); memset (&lpv->data, 0, sizeof (lpv->data)); // MOOFUTURE: This may change as new register-handling // code is developed. // "reg" used to be a union member of "data" but now // it is a separate struct in the evaluation node (so // that we can keep type information for non-trivial // enregistered values). For the time, clear the reg // field whenever the data field is cleared, in order to // be compatible with the old EE register handling code memset (&lpv->reg, 0, sizeof (lpv->reg)); pType = (plfPointer)(&((TYPPTR)(MHOmfLock (EVAL_TYPDEF(lpv))))->leaf); DASSERT(pType->leaf == LF_POINTER); DASSERT((pType->attr.ptrtype >= CV_PTR_BASE_VAL) && (pType->attr.ptrtype <= CV_PTR_BASE_SEGADDR)); pSym = (SYMPTR)(&((plfPointer)pType)->pbase.Sym); PTR_BSYMTYPE (pName->pv) = pSym->rectyp; emiAddr (PTR_ADDR (pName->pv)) = pCxt->addr.emi; switch (pSym->rectyp) { case S_BPREL16: lName.sstr.lpName = &((BPRELPTR16)pSym)->name[1]; lName.sstr.cb = ((BPRELPTR16)pSym)->name[0]; if (SearchSym(&lName) != HR_found) { goto ReturnNotFound;; } PopStack(); SetAddrSeg (&PTR_ADDR (pName->pv), 0); pSym = (SYMPTR)MHOmfLock(lName.hSym); if (((BPRELPTR16)pSym)->rectyp == S_BPREL16) { SetAddrOff (&PTR_ADDR (pName->pv), ((BPRELPTR16)pSym)->off); ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = FALSE; ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = FALSE; ADDR_IS_LI (PTR_ADDR (pName->pv)) = FALSE; PTR_STYPE (pName->pv) = ((BPRELPTR16)pSym)->typind; } else { goto ReturnNotFound;; } pExState->state.bprel = TRUE; break; case S_LDATA16: case S_GDATA16: lName.sstr.lpName = &((DATAPTR16)pSym)->name[1]; lName.sstr.cb = ((DATAPTR16)pSym)->name[0]; lrectyp = pSym->rectyp; do { if (SearchSym(&lName) != HR_found) { goto ReturnNotFound;; } PopStack(); pSym = (SYMPTR)MHOmfLock(lName.hSym); } while (pSym->rectyp != lrectyp); pExState->state.fLData = TRUE; SetAddrSeg (&PTR_ADDR (pName->pv), ((DATAPTR16)pSym)->seg); SetAddrOff (&PTR_ADDR (pName->pv), ((DATAPTR16)pSym)->off); ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = FALSE; ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = FALSE; ADDR_IS_LI (PTR_ADDR (pName->pv)) = TRUE; PTR_STYPE (pName->pv) = ((DATAPTR16)pSym)->typind; break; case S_BPREL32: lName.sstr.lpName = &((BPRELPTR32)pSym)->name[1]; lName.sstr.cb = ((BPRELPTR32)pSym)->name[0]; if (SearchSym(&lName) != HR_found) { goto ReturnNotFound;; } PopStack(); SetAddrSeg (&PTR_ADDR (pName->pv), 0); if (((BPRELPTR32)pSym)->off != 0) { SE_SetAddrOff(&PTR_ADDR (pName->pv), ((BPRELPTR32)pSym)->off); ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = TRUE; ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = TRUE; ADDR_IS_LI (PTR_ADDR (pName->pv)) = FALSE; PTR_STYPE (pName->pv) = ((BPRELPTR32)pSym)->typind; } else { goto ReturnNotFound;; } pExState->state.bprel = TRUE; break; case S_LDATA32: case S_GDATA32: case S_LTHREAD32: case S_GTHREAD32: lName.sstr.lpName = &((DATAPTR32)pSym)->name[1]; lName.sstr.cb = ((DATAPTR32)pSym)->name[0]; lrectyp = pSym->rectyp; do { if (SearchSym(&lName) != HR_found) { goto ReturnNotFound;; } PopStack(); pSym = (SYMPTR)MHOmfLock(lName.hSym); } while (pSym->rectyp != lrectyp); pExState->state.fLData = TRUE; SetAddrSeg (&PTR_ADDR (pName->pv), ((DATAPTR32)pSym)->seg); SE_SetAddrOff(&PTR_ADDR (pName->pv), ((DATAPTR32)pSym)->off); ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = TRUE; ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = TRUE; ADDR_IS_LI (PTR_ADDR (pName->pv)) = TRUE; PTR_STYPE (pName->pv) = ((DATAPTR32)pSym)->typind; break; case S_REGISTER: break; default: DASSERT(FALSE); break; } retval = HR_found; ReturnNotFound: pExState->state.fEProlog = savefEProlog; return(retval); } /** SearchSym - search for symbol * status = SearchSym (pName) * Entry pName = structure describing state of search * pName->CXTT = context to start search from * pName->scope = mask that restricts search to specific scope * pName->clsmask = mask for searching in classes. * Typical entry values for specific kinds of search: * Symbol Search (pName->initializer = INIT_sym): * pName->sstr = symbol name * pName->bn = based ptr to symbol node in the expr. tree * pName->pfnCmp = ptr to "compare symbols" function * Right Search (pName->initializer = INIT_right): * (Searches for a symbol at the right of an operator like * '::', '->' or '.') * pName->sstr = symbol name * pName->bn = based ptr to symbol node in the expr. tree * pName->bnOp = based ptr to operator node * pName->pfnCmp = ptr to "compare symbols" function * Base Class Search (pName->initializer = INIT_base): * (Looks for a base class, given the base class type -- * e.g., when casting a "Derived *" to a "Base *" * pName->typeOut = Base class type * pName->typeIn = Derived class type * pName->pfnCmp = 0 (no comparison function needed) * TypeDef Search (pName->initializer = INIT_tdef) * (Looks for a UDT symbol of a given type) * pName->typeIn = type of UDT to search for * pName->pfnCmp = ptr to "compare typedef" funciton * Qualified-Name Search (pName->initializer = INIT_qual) * (Special kind of symbol search that looks for a qualified * name) * pName->sstr = symbol name * pName->pfnCmp = ptr to "compare symbols" function * Regular Expression Search (pName->initializer = INIT_RE) * (Search for a symbol name that matches a reg. expression) * pName->sstr = reg. expression * pName->pfnCmp = ptr to "compare symbols" function * Exit pName updated to reflect search results * pName->hSym = handle of symbol * pName->CXTT = context where symbol was found * pName->pv = loaded symbol node * Side-effects: * (1) In all searches except typedef search the loaded * symbol node is pushed on the stack. The caller should * pop ST in case the push was unnecessary. * (2) A tree rewrite may occur during a class search by * inserting the "this" pointer in the expression tree, when * the expression refers to a class member without naming * the class explicitly. In that case HR_rewrite is returned. * (3) A tree extension may occur during a class search in * order to include a qualified expression for adjusting the * this pointer during evaluation. (The tree extension is done * by GenQualExpr, called by SearchClassName, and in that * case the return value of SearchSym is HR_found.) * (4) In both cases of tree rewrite and tree extension,the * evaluation tree may be reallocated, rendering all non-based * pointers to nodes invalid. Therefore the caller should * not assume that the tree has not changed or moved, even * if the return value of this function does not indicate * a tree rewrite. * Returns HR_error : error in search * HR_notfound : symbol was not found * HR_found : symbol was found * HR_rewrite : symbol found but tree rewrite required * HR_ambiguous: symbol found but ambiguous * HR_end : end of search (indicates completion of * adding symbols to the backpatch list while binding bp's) */ HR_t SearchSym ( psearch_t pName ) { CXT CXTTOut; HSYM hSym = 0; SCN_t retval; // NOTE: this routine may be called recursively through MatchFunction if ((hBPatch != 0) && (pExState->ambiguous != 0) && (pExState->ambiguous == pName->bn)) { // this is a request for a symbol that was previously found to // be ambiguous. Pop the next ambiguous symbol off the list and // return it to the caller. return ((HR_t) AmbFromList (pName)); } if ((pName->sstr.cb == 1 ) && *(pName->sstr.lpName) == '.') { EVAL_STATE( pName->pv ) = EV_rvalue; EVAL_TYP( pName->pv ) = T_PCHAR; EVAL_IS_PTR( pName->pv ) = TRUE; EVAL_IS_CURPC( pName->pv ) = TRUE; PushStack (pName->pv); return (HR_found); } #if 0 // currently not use - be here in case of future needs SearchWithSuffix = ( Suffix && !(((LPSSTR)pName)->searchmask & SSTR_RE) ); if ( SearchWithSuffix ) { cbNew = cbOld+1; memcpy( NameNew, NameOld, cbOld ); NameNew[ cbOld ] = Suffix; NameNew[ cbNew ] = '\0'; } #endif // this routine will terminate on the following conditions: // 1. A symbol is found that is not a function address // 2. A symbol is found that is a function and is not a method // and the end of the symbol table is reached // 3. A symbol is found that is a method and the end of the // inheritance tree for the class is reached. // If BindingBP is set, all function/method addresses that match // the expression are entered into the TMList pointed to by pTMList for (;;) { switch (pName->state) { case SYM_bclass: // this state is a special entry for searching for the base // class of a class when only the type of the base is known if (InitMod (pName) == FALSE) { // error in context return (HR_notfound); } pName->state = SYM_class; continue; case SYM_init: if (InitMod (pName) == FALSE) { // error in context so we will allow check for registers return ((HR_t) ParseRegister (pName)); } if ((pName->scope & ~SCP_class) && *pName->sstr.lpName == '@') { //search for @register, @linenumber, fastcall routine if (_istdigit ((_TUCHAR)*(pName->sstr.lpName + 1))) { return ((HR_t) LineNumber (pName)); } else if ((hSym = PHFindNameInPublics (NULL, pName->hExe, &pName->sstr, pExState->state.fCase, pName->pfnCmp)) != 0) { goto found; } else if (ParseRegister (pName) == HR_found) { return (HR_found); } else { return (HR_notfound); } } else if (*pName->sstr.lpName == HSYM_MARKER) { // search for handle to symbol. The handle to // symbol comes from CV when a specific symbol // is to be searched. The most common case is // when a specific variable is to be displayed // in the locals window hSym = GetHSYMFromHSYMCode( (char *) pName->sstr.lpName + 1 ); DASSERT (hSym); goto found; } // start normal symbol search pName->state = SYM_lexical; case SYM_lexical: if (pName->scope & SCP_lexical) { // search up the lexical scope to the function level // but do not search the module level because of the // class search required for method functions while (!SHIsCXTMod (&pName->CXTT) ) { if ((hSym = SHFindNameInContext (pName->hSym, &pName->CXTT, &pName->sstr, pExState->state.fCase, (PFNCMP) FNCMP, &CXTTOut)) != 0) { goto foundsave; } // go to the parent scope SHGoToParent (&pName->CXTT, &CXTTOut); // reset current symbol pName->hSym = 0; pName->CXTT = CXTTOut; } } pName->state = SYM_class; if (pName->scope & SCP_class) { if (pName->ExpClass != 0) { // search an explicit class pName->CurClass = pName->ExpClass; } else if (ClassImp != 0) { pName->CurClass = ClassImp; } } case SYM_class: if ((pName->CurClass != 0) && (pName->scope & SCP_class)) { retval = SearchClassName (pName); switch (retval) { case SCN_found: // the symbol is a member of the class. If // an explict class was not specified and // the current context is implicitly a class, // then we rewrote the tree to change the // symbol reference to this->symbol DASSERT (pName->hFound == 0); DASSERT (pName->hAmbCl == 0); if (EVAL_TYP (pName->pv) != T_NOTYPE) { if (PushStack (pName->pv) == FALSE) return (HR_error); goto nopush; } else { pExState->err_num = ERR_BADOMF; return (HR_error); } case SCN_rewrite: return (HR_rewrite); case SCN_error: return (HR_error); default: DASSERT (pName->hFound == 0); DASSERT (pName->hAmbCl == 0); if (pName->initializer == INIT_base) { // we were searching for the base class of // a class which was not found. return (HR_notfound); } break; } } SHGetCxtFromHmod (pName->hMod, &pName->CXTT); pName->hSym = 0; pName->state = SYM_module; case SYM_module: if (pName->scope & SCP_module) { if ((hSym = SHFindNameInContext (pName->hSym, &pName->CXTT, &pName->sstr, pExState->state.fCase, pName->pfnCmp, &CXTTOut)) != 0) { goto foundsave; } } pName->state = SYM_global; pName->hSym = 0; case SYM_global: // users specified a context on a break point command // we have already searched the module specified so end the search // here // sps - 7/24/92 if (pBindBPCxt && pBindBPCxt->hMod &&(pBindBPCxt->hMod != pName->hModCur) && (pExState->ambiguous != 0) && (pExState->ambiguous == pName->bn)) { return(HR_end); } // search global symbol table if (pName->scope & SCP_global) { if ((hSym = SHFindNameInTypes (&pName->CXTT, &pName->sstr, pExState->state.fCase, pName->pfnCmp, &CXTTOut)) != 0) { goto foundsave; } if ((hSym = SHFindNameInGlobal (pName->hSym, &pName->CXTT, &pName->sstr, pExState->state.fCase, pName->pfnCmp, &CXTTOut)) != 0) { goto foundsave; } } pName->hModCur = SHGetNextMod (pName->hExe, pName->hMod); pName->hSym = 0; pName->state = SYM_exe; case SYM_exe: if (pName->scope & SCP_global) { #ifdef LOADALL do { SHGetCxtFromHmod (pName->hModCur, &pName->CXTT); if ((hSym = SHFindNameInContext (pName->hSym, &pName->CXTT, &pName->sstr, pExState->state.fCase, pName->pfnCmp, &CXTTOut)) != 0) { goto foundsave; } } while (pName->hSym = 0, (pName->hModCur = SHGetNextMod (pName->hExe, pName->hModCur)) != pName->hMod); #else pName->CXTT.hGrp = pName->CXTT.hMod; pName->CXTT.hMod = 0; if ((hSym = SHFindNameInContext (pName->hSym, &pName->CXTT, &pName->sstr, pExState->state.fCase, pName->pfnCmp, &CXTTOut) ) != 0) { goto foundsave; } pName->CXTT.hMod = pName->CXTT.hGrp; #endif } // we are at the end of the normal symbol search. If the // symbol has not been found, we will search the public // symbol table. if (!BindingBP) { // if we are not binding breakpoints and we have // found a symbol in previous calls, return. Otherwise, // we will look in the publics table. Note that // finding a symbol in the publics table has a // large probability of finding one with a type of // zero which will limit it's usefulness if (pName->hSym != 0) { if (pName->possibles > 1) { pExState->err_num = ERR_AMBIGUOUS; return (HR_ambiguous); } return (HR_notfound); } } else { // we are binding breakpoints. We need to see if // one or more symbols have matched. If so, we // are done with the symbol search. If we have // not found the symbol, we search the publics table. // For breakpoints, we do not need type information, // only the address, so symbols found in the publics // table are much more useful. if ((pExState->ambiguous != 0) && (pExState->ambiguous == pName->bn)) { // we have found at least one symbol to this // point. this is indicated by SymAmbToList // setting the node of the function's symbol // into the expression state structure. By // this point all ambiguous symbols have been // added to the back patch list. If we have // not found any symbol yet, we search the // publics table. Note also that there cannot // be any ambiguity in the publics table because // the function names have to be unique in the // publics table. return (HR_end); } } // search public symbol table pName->state = SYM_public; case SYM_public: // some searches such as finding a UDT by type // do not require a symbol if (pName->scope & SCP_global) { hSym = PHFindNameInPublics (NULL, pName->hExe, &pName->sstr, pExState->state.fCase, pName->pfnCmp); if (!hSym) { unsigned char oldmask = pName->sstr.searchmask; pName->sstr.searchmask |= SSTR_FuzzyPublic; pName->sstr.searchmask |= SSTR_NoHash; hSym = PHFindNameInPublics (NULL, pName->hExe, &pName->sstr, pExState->state.fCase, pName->pfnCmp); pName->sstr.searchmask = oldmask; } if (hSym != 0) { if (hSym == pName->hSym) { // We found this symbol last call! There // are no more to be found (or worth finding). return HR_notfound; } // What's this all about???? BryanT 3/11/96 if ((TargetMachine == mptmips) || (TargetMachine == mptdaxp)) { goto found; } else { goto foundsave; } } } if (EVAL_IS_REG (pName->pv)) { return (HR_notfound); // found it last time - quit looking } else if ((pName->scope & ~SCP_class) && ParseRegister (pName) == HR_found) { return (HR_found); } ErrUnknownSymbol(&pName->sstr); return (HR_notfound); } } foundsave: EVAL_CXTT(pName->pv) = pName->CXTT = CXTTOut; found: pName->hSym = hSym; EVAL_HSYM (pName->pv) = pName->hSym; #ifdef NEVER if (pName->initializer == INIT_tdef) { // the routines that search for UDTs only need the // hsym and the stack pointer may not be valid at this // point (FormatUDT for example), so return now return (HR_found); } #endif if (SymToNode (pName) == FALSE) { return (HR_notfound); } #ifdef NEVER // This is now handled by SetNodeType if (EVAL_IS_PTR(pName->pv) && (EVAL_PTRTYPE(pName->pv) >= CV_PTR_BASE_VAL) && (EVAL_PTRTYPE(pName->pv) <= CV_PTR_BASE_SEGADDR)){ if (SearchBasePtrBase(pName) != HR_found) { return(HR_notfound); } } #endif if (PushStack (pName->pv) == FALSE) return (HR_error); nopush: if (!EVAL_IS_FCN (ST)) { // if this symbol is not a function and we have not processed // a function previously, then the search is done if (pExState->ambiguous == 0) { return (HR_found); } else if (pExState->ambiguous == pName->bn) { pExState->err_num = ERR_SYMCONFLICT; return (HR_error); } else { return (HR_found); } } else if (EVAL_IS_METHOD (ST)) { // ambiguous methods were entered into the ambiguous breakpoint // list by SetBPValue which was called in SearchClassName return (HR_found); } else if (pName->state == SYM_public) { // we will take the first function symbol found in the // publics table since the names have to be unique in the // publics table return (HR_found); } else if ((BindingBP == TRUE) && (bArgList == 0)) { // if we are binding breakpoints and there is not an // argument list, we will enter all functions found with // this name into the breakpoint ambiguity list. return (SymAmbToList (pName)); } else { // the found symbol is non-member function. Continue // search to end of symbols to find the best function. // in the case of a breakpoint with argument list, there // must be an exact match on the argument types EVAL_MOD (pName->pv) = SHHMODFrompCXT (&pName->CXTT); if (pName->scope & SCP_nomatchfn) return (HR_found); return (MatchFunction (pName)); } } bool_t InitMod ( psearch_t pName ) { if (((pName->hMod = SHHMODFrompCXT (&pName->CXTT)) == 0) || ((pName->hExe = SHHexeFromHmod (pName->hMod)) == 0)) { // error in context return (FALSE); } return (TRUE); } // Class searching and main support routines /*** SearchClassName - Search a class and bases for element by name * flag = SearchClassName (pName) * Entry pName = pointer to struct describing search * Exit pName updated to reflect type * Returns SCN_... enum describing result */ SCN_t SearchClassName ( psearch_t pName ) { SCN_t retval; ulong max; CV_fldattr_t attr = {0}; // allocate and initialize list of dominated virtual bases if (hVBDom == 0) { if ((hVBDom = MemAllocate (sizeof (dombase_t) + DOMBASE_DEFAULT * sizeof (CV_typ_t))) == 0) { pExState->err_num = ERR_NOMEMORY; return (SCN_error); } pVBDom = (pdombase_t) MemLock (hVBDom); pVBDom->MaxIndex = DOMBASE_DEFAULT; } else { pVBDom = (pdombase_t) MemLock (hVBDom); } pVBDom->CurIndex = 0; // allocate and initialize list of searched virtual bases if (hVBSearch == 0) { if ((hVBSearch = MemAllocate (sizeof (dombase_t) + DOMBASE_DEFAULT * sizeof (CV_typ_t))) == 0) { pExState->err_num = ERR_NOMEMORY; MemUnLock (hVBDom); return (SCN_error); } pVBSearch = (pdombase_t) MemLock (hVBSearch); pVBSearch->MaxIndex = DOMBASE_DEFAULT; } else { pVBSearch = (pdombase_t) MemLock (hVBSearch); } pVBSearch->CurIndex = 0; // allocate and initialize structure for recursive base searches if (hSymClass == 0) { if ((hSymClass = MemAllocate (sizeof (symclass_t) + SYMBASE_DEFAULT * sizeof (symbase_t))) == 0) { pExState->err_num = ERR_NOMEMORY; MemUnLock (hVBDom); MemUnLock (hVBSearch); return (SCN_error); } pSymClass = (psymclass_t) MemLock (hSymClass); pSymClass->MaxIndex = SYMBASE_DEFAULT; } else { pSymClass = (psymclass_t) MemLock (hSymClass); } pSymClass->CurIndex = 0; pSymClass->hNext = 0; max = pSymClass->MaxIndex; memset (pSymClass, 0, max * sizeof (symbase_t) + sizeof (symclass_t)); pSymClass->MaxIndex = max; // recurse through the inheritance tree searching for the feature if ((retval = RecurseBase (pName, pName->CurClass, 0, 0, 0, attr, FALSE)) != SCN_error) { // at this point we need to check for dominance and then clean // up the allocated memory and return the search results if (pName->possibles == 0) { // if the count was zero, the handle of found list must be zero DASSERT (pName->hFound == 0); retval = SCN_notfound; } else if (pName->cFound == 0) { if (pName->hFound == 0) { DASSERT (pSymClass->viable == TRUE); // the found value is in the permanent stack. This means // the feature was found in the most derived class retval = SetValue (pName); } } else if (pName->cFound == 1) { // the feature was not found in the most derived class // but no other matching feature was found. Move the feature // descriptor pointed to by pName->hFound into the permanent // feature descriptor pSymClass. An important thing to remember // here is that there can only be one feature descriptor pSymClass // when calling SetValue unless we are binding breakpoints. // If we are binding breakpoints we can have multiple feature // descriptors in pSymClass and the list pointed to by // pName->hAmbCl. If we have an argument list, these must // resolve to one feature. If we do not have an argument // list, all of the features are valid and must be added // to the breakpoint list. MoveSymCl (pName->hFound); pName->hFound = 0; pName->cFound--; DASSERT (pSymClass->viable == TRUE); retval = SetValue (pName); } else { // since two or more features were found, we need to cull the // feature list to remove dominated features and features which // are the same static item. Ambiguity is removed strictly on // the name of the feature. Overloaded methods are resolved later. if ((retval = RemoveAmb (pName)) == SCN_found) { retval = SetValue (pName); } } } MemUnLock (hVBDom); MemUnLock (hVBSearch); MemUnLock (hSymClass); DASSERT (pName->hAmbCl == 0); return (retval); } /*** RecurseBase - Search a class and its bases for element by name * status = RecurseBase (pName, type, vbptr, vbpoff, thisadjust, attr, virtual) * Entry pName = pointer to struct describing search * type = type index of class * vbptr = type index of virtual base pointer * vbpoff = offset of virtual base pointer from address point * thisadjust = offset of base from previous class * thisadjust = virtual base index if virtual base * attr = attribute of base class * virtual = TRUE if this is a virtual base * Exit pName updated to reflect type * Returns SCN_... enum describing result */ SCN_t RecurseBase ( psearch_t pName, CV_typ_t type, CV_typ_t vbptr, UOFFSET vbpoff, UOFFSET thisadjust, CV_fldattr_t attr, bool_t fVirtual ) { SCN_t retval; // save offset of base from address point for this pointer adjustment if (SetBase (pName, type, vbptr, vbpoff, thisadjust, attr, fVirtual) != SCN_found) { return (SCN_error); } if (pName->initializer == INIT_base) { retval = SearchBType (pName); } else if (pName->initializer == INIT_AErule ) { retval = SearchAERule (pName); } else { retval = SearchRoot (pName); } switch (retval) { case SCN_found: if (((pName->clsmask & CLS_virtintro) == FALSE) && (pName->initializer != INIT_AErule)) { // add virtual bases to searched and dominated base lists // if we were searching for the introducing virtual function or auto-expand // class name the fact that we found one is sufficient. if ((pSymClass->isvbase == TRUE) && (VBaseFound (pName) == TRUE)) { // the found feature is a previously found // virtual base class. pSymClass->isdupvbase = TRUE; } if ((retval = AddVBList (pSymClass, &pVBSearch, &hVBSearch)) != SCN_error) { retval = AddVBList (pSymClass, &pVBDom, &hVBDom); } } case SCN_error: return (retval); case SCN_notfound: // we did not find the element in the root of this class // so we search the inheritance tree. if (pExState->state.fSupBase == FALSE) { return (SearchBases (pName)); } else { return (SCN_notfound); } default: return (SCN_error); } } /** VBaseFound - search to see if virtual base already found * status = VBaseFound (pName) * Entry pName = structure describing search * pSymClass = structure describing most recent class search * Exit pName updated to reflect search * pSymClass updated to unambiguous feature * Returns TRUE if duplicate virtual base found * FALSE if not duplicate virtual base */ bool_t VBaseFound ( psearch_t pName ) { psymclass_t pSymCl; HDEP hSymCl; CV_typ_t type = EVAL_TYP (&pSymClass->evalP); hSymCl = pName->hFound; while (hSymCl != 0) { pSymCl = (psymclass_t) MemLock (hSymCl); if (pSymCl == pSymClass) { return (FALSE); } if ((pSymCl->isvbase == TRUE) && (type == EVAL_TYP (&pSymCl->evalP))) { // the virtual base is already in the list return (TRUE); } } return (FALSE); } /** RemoveAmb - remove ambiguity * status = RemoveAmb (pName) * Entry pName = structure describing search * pSymClass = structure describing most recent class search * Exit pName updated to reflect search * pSymClass updated to unambiguous feature * Returns SCN_found if unambiguous feature found * SCN_error otherwise */ SCN_t RemoveAmb ( psearch_t pName ) { psymclass_t pSymCl; // we know that at this point two or more features were found // the list of features are pointed to by pName->hFound. // The permanent stack cannot contain a viable feature DASSERT (pSymClass->viable == FALSE); MoveSymCl (pName->hFound); pName->hFound = pSymClass->hNext; while (pName->hFound != 0) { // lock and check next list element pSymCl = (psymclass_t) MemLock (pName->hFound); switch (IsDominated (pSymClass, pSymCl)) { case DOM_ambiguous: // the new feature does not dominate the current best MemUnLock (pName->hFound); if (BindingBP == FALSE) { pExState->err_num = ERR_AMBIGUOUS; return (SCN_error); } // feature is ambiguous and we are setting breakpoints // save the feature in the ambiguous list and advance to // the next feature pSymClass->hNext = pSymCl->hNext; pSymCl->hNext = pName->hAmbCl; pName->hAmbCl = pName->hFound; MemUnLock (pName->hAmbCl); pName->hFound = pSymClass->hNext; break; case DOM_replace: // decrement the number of possible matches by the // count in the current best structure pName->possibles -= pSymClass->possibles; pName->cFound--; MemUnLock (pName->hFound); MoveSymCl (pName->hFound); pName->hFound = pSymClass->hNext; PurgeAmbCl (pName); break; case DOM_keep: // decrement the number of possible matches by the // count in the structure being discarded pName->possibles -= pSymCl->possibles; pName->cFound--; pSymClass->hNext = pSymCl->hNext; MemUnLock (pName->hFound); pName->hFound = pSymClass->hNext; break; } } // decrement the count of found features to account for the one we kept pName->cFound--; return (SCN_found); } /*** SearchBases - Search for an element in the bases of a class * flag = SearchBases (pName, pvClass) * Entry pName = pointer to struct describing search * Exit pName updated to reflect type * Returns enum describing search state */ SCN_t SearchBases ( psearch_t pName ) { ulong cnt; // count of number of elements in struct HTYPE hField; // handle to type record for struct field list char *pField; // pointer to field list uint fSkip = 0; // offset in the field list SCN_t retval = SCN_notfound; CV_typ_t newindex; CV_typ_t vbptr; UOFFSET offset; UOFFSET vbpoff; CV_fldattr_t attr; CV_fldattr_t vattr; peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base; bool_t fVirtual; // Set to head of type record and search the base classes in order if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), CLASS_FIELD (pvBase))) == 0) { // set error and stop search DASSERT (FALSE); pExState->err_num = ERR_BADOMF; return (SCN_error); } pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) { fSkip += SkipPad(((uchar *)pField) + fSkip); newindex = 0; switch (((plfEasy)(pField + fSkip))->leaf) { case LF_INDEX: // switch to next part of type record newindex = ((plfIndex)(pField + fSkip))->index; MHOmfUnLock (hField); if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) { DASSERT (FALSE); pExState->err_num = ERR_INTERNAL; return (SCN_error); } pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); fSkip = 0; // the LF_INDEX is not part of the field count cnt++; break; case LF_BCLASS: // read type index of base class offset of base pointer // from address point attr = ((plfBClass)(pField + fSkip))->attr; newindex = ((plfBClass)(pField + fSkip))->index; fSkip += sizeof (struct lfBClass); offset = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip); vbptr = 0; vbpoff = 0; fVirtual = FALSE; goto foo; case LF_VBCLASS: // read type index of base class, type index of virtual // base pointer, offset of virtual base pointer from // address point and offset of virtual base displacement // from virtual base table vattr = ((plfVBClass)(pField + fSkip))->attr; newindex = ((plfVBClass)(pField + fSkip))->index; vbptr = ((plfVBClass)(pField + fSkip))->vbptr; fVirtual = TRUE; fSkip += sizeof (struct lfVBClass); vbpoff = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip); offset = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip); if ((pName->clsmask & CLS_virtintro) == FALSE) { // if we are searching for the introducing virtual method // then we want to search all bases if (VBSearched (newindex) == TRUE) { break; } retval = AddVBType (&pVBSearch, &hVBSearch, newindex); } foo: // check base class MHOmfUnLock (hField); // Advance to next base class structure if (IncrSymBase () != SCN_found) { return (SCN_error); } retval = RecurseBase (pName, newindex, vbptr, vbpoff, offset, attr, fVirtual); switch (retval) { case SCN_error: // if we got an error, abort the search newindex = 0; break; case SCN_found: // we have found the feature in a base class. // Dup the class search structure and continue the // search to the end of the inheritance tree if ((pName->clsmask & CLS_virtintro) == FALSE && (pName->initializer != INIT_AErule)) { if ((retval = DupSymCl (pName)) != SCN_found) { // if we got an error duping, abort the search newindex = 0; } // set not found, so the unwinding of the call stack // does not reduplicate the class search structure retval = SCN_notfound; } else { // we were searching for the introducing virtual // method. Since there can be only one in the // tree above the virtual method, we can terminate // the search immediately Or we are searching for a // class to autoexpand the node. The first match we found is // what we will use in this case. return (retval); } break; default: break; } pSymClass->CurIndex--; MHOmfLock (hField); break; default: // we have reached the end of the base classes. // exit loop and check search results. break; } if (newindex == 0) { // all base classes must appear first in the field list. break; } } MHOmfUnLock (hField); return (retval); } /*** SearchBType - Search for an base by type * flag = SearchBType (pName) * Entry pName = pointer to struct describing search * pSymClass = pointer to base class path list structure * Exit pName updated to reflect search * Return enum describing search * If the base class is found, the base class value is stored in the * the symbase[], not in pSymClass->evalP. This is to simplify the * GenQualExpr code. */ INLINE BOOL getBaseDefnFromDecl( CV_typ_t typeIn, peval_t pv, CV_typ_t* ptypeOut ) { peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base; Unreferenced (pv); return getDefnFromDecl (typeIn, pvBase, ptypeOut); } bool_t getDefnFromDecl( CV_typ_t typeIn, peval_t pv, CV_typ_t* ptypeOut ) { HTYPE hType; uint skip; TYPPTR pType; eval_t localEval; neval_t nv = &localEval; *nv = *pv; DASSERT (!CV_IS_PRIMITIVE (typeIn)); if ((hType = THGetTypeFromIndex (EVAL_MOD (nv), typeIn)) == 0) { pExState->err_num = ERR_BADOMF; return FALSE; } pType = (TYPPTR)MHOmfLock(hType); switch (pType->leaf) { case LF_STRUCTURE: case LF_CLASS: { plfClass pClass = (plfClass)(&pType->leaf); if (pClass->property.fwdref) { skip = offsetof (lfClass, data); RNumLeaf (((char *)(&pClass->leaf)) + skip, &skip); // forward ref - look for the definition of the UDT if ((*ptypeOut = GetUdtDefnTindex (typeIn, nv, ((char *)&(pClass->leaf)) + skip)) == T_NOTYPE) { goto failed; } } else *ptypeOut = typeIn; break; } case LF_UNION: { plfUnion pUnion = (plfUnion)(&pType->leaf); if (pUnion->property.fwdref) { skip = offsetof (lfUnion, data); RNumLeaf (((char *)(&pUnion->leaf)) + skip, &skip); // forward ref - look for the definition of the UDT if ((*ptypeOut = GetUdtDefnTindex (typeIn, nv, ((char *)&(pUnion->leaf)) + skip)) == T_NOTYPE) { goto failed; } } else *ptypeOut = typeIn; break; } case LF_ENUM: { plfEnum pEnum = (plfEnum)(&pType->leaf); if (pEnum->property.fwdref) { // forward ref - look for the definition of the UDT if ((*ptypeOut = GetUdtDefnTindex (typeIn, nv, (char *) pEnum->Name)) == T_NOTYPE) { goto failed; } } else *ptypeOut = typeIn; break; } default: *ptypeOut = typeIn; } MHOmfUnLock (hType); return TRUE; failed: MHOmfUnLock (hType); pExState->err_num = ERR_BADOMF; return FALSE; } SCN_t SearchBType ( psearch_t pName ) { ulong cnt; // count of number of elements in struct HTYPE hField; // handle to type record for struct field list char *pField; // pointer to field list uint fSkip = 0; // offset in the field list ulong anchor = 0; // offset in the field list to start of type CV_typ_t newindex; CV_typ_t vbptr; SCN_t retval = SCN_notfound; UOFFSET offset; UOFFSET vbpoff; bool_t termflag = FALSE; CV_fldattr_t attr; CV_fldattr_t vattr; peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base; // set hField to the handle of the field list for the class if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), CLASS_FIELD (pvBase))) == 0) { pExState->err_num = ERR_BADOMF; return (SCN_error); } pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); // walk field list for the class for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) { fSkip += SkipPad(((uchar *)pField) + fSkip); switch (((plfEasy)(pField + fSkip))->leaf) { case LF_INDEX: // switch to new type record because compiler split it up newindex = ((plfIndex)(pField + fSkip))->index; MHOmfUnLock (hField); if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) { pExState->err_num = ERR_INTERNAL; return (SCN_error); } pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); fSkip = 0; // the LF_INDEX is not part of the field count cnt++; break; case LF_BCLASS: attr = ((plfBClass)(pField + fSkip))->attr; if (!getBaseDefnFromDecl(((plfBClass)(pField + fSkip))->index, pName->pv, &newindex)) return SCN_error; fSkip += offsetof (lfBClass, offset); offset = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip); if (pName->typeOut == newindex) { // base has been found, set result values MHOmfUnLock (hField); if (IncrSymBase () != SCN_found) { return (SCN_error); } // save offset of base from address point for this // pointer adjustment if (SetBase (pName, newindex, 0, 0, offset, attr, FALSE) != SCN_found) { return (SCN_error); } pSymClass->viable = TRUE; pName->possibles++; return (SCN_found); } break; case LF_VBCLASS: vattr = ((plfVBClass)(pField + fSkip))->attr; if (!getBaseDefnFromDecl(((plfVBClass)(pField + fSkip))->index, pName->pv, &newindex)) return SCN_error; vbptr = ((plfVBClass)(pField + fSkip))->vbptr; fSkip += offsetof (lfVBClass, vbpoff); vbpoff = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip); offset = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip); if (pName->typeOut == newindex) { // base has been found, set result values MHOmfUnLock (hField); if (IncrSymBase () != SCN_found) { return (SCN_error); } // save offset of base from address point for this // pointer adjustment if (SetBase (pName, newindex, vbptr, vbpoff, offset, attr, TRUE) != SCN_found) { return (SCN_error); } pSymClass->viable = TRUE; pName->possibles++; return (SCN_found); } break; default: termflag = TRUE; break; } if (termflag == TRUE) { break; } } MHOmfUnLock (hField); return (retval); } /*** SearchAERule - Search for auto-expansion rule * flag = SearchAERule (pName) * Description: * The objective is to find an appropriate * auto-expansion rule for a class that has no * expansion rule associated with it. The idea * is to use the expansion rule of a base class * if one exists. * The expansion rule is treated as a feature and * the usual conventions apply regarding dominance * and ambiguity. * Entry pName = pointer to struct describing search * Exit pName updated to reflect search * Return enum describing search */ SCN_t SearchAERule ( psearch_t pName ) { peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base; CV_typ_t type; peval_t pvF = &pSymClass->evalP; LSZ lsz; SCN_t retval = SCN_notfound; static char buf[256]; type = EVAL_TYP (pvBase); lsz = GetTypeName (type, EVAL_MOD (pvBase)); if (LoadAERule (lsz, buf, sizeof (buf))) { EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT); pvF->CXTT = pName->CXTT; SetNodeType (pvF, type); EVAL_STATE (pvF) = EV_type; pSymClass->possibles = 1; pName->possibles++; pSymClass->viable = TRUE; retval = SCN_found; } return retval; } /*** SearchRoot - Search for an element of a class * flag = SearchRoot (pName) * Entry pName = pointer to struct describing search * pvBase = pointer to value describing base to be searched * Exit pName updated to reflect search * Return enum describing search */ SCN_t SearchRoot ( psearch_t pName ) { ulong cnt; // count of number of elements in struct HTYPE hField; // handle to type record for struct field list char *pField; // pointer to field list HTYPE hBase; // handle to type record for base class uint fSkip = 0; // offset in the field list uint anchor; // offset in the field list to start of type uint tSkip; // temporary offset in the field list bool_t cmpflag = 1; CV_typ_t newindex; CV_typ_t vbptr; SCN_t retval = SCN_notfound; char *pc; UQUAD value; UOFFSET offset; UOFFSET vbpoff; CV_fldattr_t access; int count; CV_typ_t vfpType = T_NOTYPE; peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base; CV_typ_t type; peval_t pvF = &pSymClass->evalP; UOFFSET vtabind; ulong vbind; // set hField to the handle of the field list for the class if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), CLASS_FIELD (pvBase))) == 0) { pExState->err_num = ERR_BADOMF; return (SCN_error); } pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); // walk field list for the class for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) { fSkip += SkipPad(((uchar *)pField) + fSkip); anchor = fSkip; switch (((plfEasy)(pField + fSkip))->leaf) { case LF_INDEX: // switch to new type record because compiler split it up newindex = ((plfIndex)(pField + fSkip))->index; MHOmfUnLock (hField); if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) { pExState->err_num = ERR_BADOMF; return (SCN_error); } pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); fSkip = 0; // the LF_INDEX is not part of the field count cnt++; break; case LF_MEMBER: fSkip += offsetof (lfMember, offset); offset = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip); access = ((plfMember)(pField + anchor))->attr; pc = pField + fSkip; fSkip += (*(pField + fSkip) + sizeof (char)); if (pName->clsmask & CLS_member) { if ((cmpflag = fnCmp (pName, NULL, pc, pExState->state.fCase)) == 0) { type = ((plfMember)(pField + anchor))->index; MHOmfUnLock (hField); hField = 0; EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT); SetNodeType (pvF, type); EVAL_STATE (pvF) = EV_lvalue; // save the casting data for the this pointer pSymClass->offset = offset; pSymClass->access = access; pSymClass->possibles = 1; pName->possibles++; } } break; case LF_ENUMERATE: access = ((plfEnumerate)(pField + fSkip))->attr; fSkip += offsetof (lfEnumerate, value); value = RNumLeaf (pField + fSkip, &fSkip); pc = pField + fSkip; fSkip += *(pField + fSkip) + sizeof (char); if (pName->clsmask & CLS_enumerate) { if ((cmpflag = fnCmp (pName, NULL, pc, pExState->state.fCase)) == 0) { pSymClass->possibles = 1; pName->possibles++; } } break; case LF_STMEMBER: type = ((plfSTMember)(pField + anchor))->index; fSkip += offsetof (lfSTMember, Name); if (pName->clsmask & CLS_member) { if ((cmpflag = fnCmp (pName, NULL, pField + fSkip, pExState->state.fCase)) == 0) { pSymClass->access = ((plfSTMember)(pField + anchor))->attr; MHOmfUnLock (hField); hField = 0; EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT); SetNodeType (pvF, type); EVAL_STATE (pvF) = EV_lvalue; EVAL_IS_STMEMBER (pvF) = TRUE; pSymClass->possibles = 1; pName->possibles++; } } fSkip += *(pField + fSkip) + sizeof (char); break; case LF_BCLASS: type = ((plfBClass)(pField + anchor))->index; access = ((plfBClass)(pField + anchor))->attr; fSkip += offsetof (lfBClass, offset); newindex = ((plfBClass)(pField + anchor))->index; offset = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip); if ((pName->clsmask & CLS_bclass) != 0) { // switch to the base class type record to check the name MHOmfUnLock (hField); if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) { pExState->err_num = ERR_BADOMF; return (SCN_error); } pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->leaf); tSkip = offsetof (lfClass, data); RNumLeaf (pField + tSkip, &tSkip); pc = pField + tSkip; cmpflag = fnCmp (pName, NULL, pc, pExState->state.fCase); MHOmfUnLock (hBase); // reset to original field list if (cmpflag == 0) { // element has been found, set result values pSymClass->isbase = TRUE; pSymClass->isvbase = FALSE; pSymClass->offset += offset; EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT); SetNodeType (pvF, type); EVAL_STATE (pvF) = EV_type; pSymClass->access = access; pSymClass->possibles = 1; pName->possibles++; } pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); } break; case LF_VBCLASS: type = ((plfBClass)(pField + anchor))->index; access = ((plfVBClass)(pField + anchor))->attr; newindex = ((plfVBClass)(pField + anchor))->index; vbptr = ((plfVBClass)(pField + anchor))->vbptr; fSkip += offsetof (lfVBClass, vbpoff); vbpoff = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip); vbind = (ulong)RNumLeaf (pField + fSkip, &fSkip); if ((pName->clsmask & CLS_bclass) != 0) { // switch to the base class type record to check the name MHOmfUnLock (hField); if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) { pExState->err_num = ERR_BADOMF; return (SCN_error); } pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->leaf); tSkip = offsetof (lfClass, data); RNumLeaf (pField + tSkip, &tSkip); pc = pField + tSkip; cmpflag = fnCmp (pName, NULL, pc, pExState->state.fCase); MHOmfUnLock (hBase); // reset to original field list if (cmpflag == 0) { // element has been found, set result values pSymClass->isbase = FALSE; pSymClass->isvbase = TRUE; pSymClass->vbind = vbind; pSymClass->vbpoff = vbpoff; pSymClass->vbptr = vbptr; EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT); SetNodeType (pvF, type); EVAL_STATE (pvF) = EV_type; pSymClass->access = access; pSymClass->possibles = 1; pName->possibles++; } pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); } break; case LF_IVBCLASS: fSkip += offsetof (lfVBClass, vbpoff); RNumLeaf (pField + fSkip, &fSkip); RNumLeaf (pField + fSkip, &fSkip); break; case LF_FRIENDCLS: newindex = ((plfFriendCls)(pField + fSkip))->index; fSkip += sizeof (struct lfFriendCls); if ((pName->clsmask & CLS_fclass) != 0) { DASSERT (FALSE); // switch to the base class type record to check the name MHOmfUnLock (hField); if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) { pExState->err_num = ERR_INTERNAL; return (SCN_error); } pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->data); tSkip = offsetof (lfClass, data); RNumLeaf (pField + tSkip, &tSkip); pc = pField + tSkip; cmpflag = fnCmp (pName, NULL, pc, pExState->state.fCase); MHOmfUnLock (hBase); // reset to original field list pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); if (cmpflag == 0) { // element has been found, set result values pName->typeOut = newindex; } } break; case LF_FRIENDFCN: newindex = ((plfFriendFcn)(pField + fSkip))->index; fSkip += sizeof (struct lfFriendFcn) + ((plfFriendFcn)(pField + fSkip))->Name[0]; if ((pName->clsmask & CLS_frmethod) != 0) { DASSERT (FALSE); } break; case LF_VFUNCTAB: fSkip += sizeof (struct lfVFuncTab); // save the type of the virtual function pointer vfpType = ((plfVFuncTab)(pField + anchor))->type; pc = vfuncptr; if (pName->clsmask & CLS_vfunc) { if ((cmpflag = fnCmp (pName, NULL, pc, pExState->state.fCase)) == 0) { MHOmfUnLock (hField); hField = 0; EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT); SetNodeType (pvF, vfpType); EVAL_STATE (pvF) = EV_lvalue; // save the casting data for the this pointer if (pName->bnOp != 0) { pSymClass->offset = 0; pSymClass->access.access = CV_public; } pSymClass->possibles = 1; pName->possibles++; } } break; case LF_ONEMETHOD: count = 1; newindex = ((plfOneMethod)(pField + fSkip))->index; pc = pbNameInLfOneMethod((plfOneMethod)(pField + fSkip)); fSkip += uSkipLfOneMethod((plfOneMethod)(pField + fSkip)); if (pName->clsmask & CLS_method) { if ((cmpflag = fnCmp (pName, NULL, pc, pExState->state.fCase)) == 0) { // note that the OMF specifies that the vfuncptr will // be emitted as the first field after the bases if (pName->clsmask & CLS_virtintro) { // we are looking for the introducing virtual // method. We need to find a method with the // correct name of the correct type index that // is introducing. MHOmfUnLock (hField); if (IsIntroVirt (newindex) == FALSE) { cmpflag = 1; pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); } else { pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); if (FCN_VFPTYPE (pvF) == T_NOTYPE) { FCN_VFPTYPE (pvF) = vfpType; FCN_VFPTYPE (pName->pv) = vfpType; FCN_VTABIND (pvF) = vtabind; FCN_VTABIND (pName->pv) = *((plfOneMethod)(pField + anchor))->vbaseoff; } cmpflag = 0; } } else { type = ((plfOneMethod)(pField + anchor))->index; access = ((plfOneMethod)(pField + anchor))->attr; FCN_VTABIND (pvF) = fIntroducingVirtual(access.mprop) ? *((plfOneMethod)(pField + anchor))->vbaseoff : 0; MHOmfUnLock (hField); hField = 0; EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT); SetNodeType (pvF, type); EVAL_STATE (pvF) = EV_lvalue; pSymClass->possibles = 1; pName->possibles = 1; pSymClass->mlist = type; pSymClass->access = access; pSymClass->vfpType = vfpType; } } } break; case LF_METHOD: count = ((plfMethod)(pField + fSkip))->count; cnt -= count - 1; newindex = ((plfMethod)(pField + fSkip))->mList; pc = pField + anchor + offsetof (lfMethod, Name); fSkip += sizeof (struct lfMethod) + *pc; if (pName->clsmask & CLS_method) { if ((cmpflag = fnCmp (pName, NULL, pc, pExState->state.fCase)) == 0) { // note that the OMF specifies that the vfuncptr will // be emitted as the first field after the bases if (pName->clsmask & CLS_virtintro) { // we are looking for the introducing virtual // method. We need to find a method with the // correct name of the correct type index that // is introducing. MHOmfUnLock (hField); if (IsIntroVirtInMlist (count, newindex, &vtabind) == FALSE) { cmpflag = 1; } else { if (FCN_VFPTYPE (pvF) == T_NOTYPE) { FCN_VFPTYPE (pvF) = vfpType; FCN_VFPTYPE (pName->pv) = vfpType; FCN_VTABIND (pvF) = vtabind; FCN_VTABIND (pName->pv) = vtabind; } cmpflag = 0; } pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); } else { // save the type index of the method list, the // count of methods overloaded on this name, // the type index of the vfuncptr. Also, // increment the number of possible features by // the overload count pSymClass->possibles = count; pName->possibles += count; pSymClass->mlist = newindex; pSymClass->vfpType = vfpType; } } } break; case LF_NESTTYPE: newindex = ((plfNestType)(pField + fSkip))->index; fSkip += offsetof (lfNestType, Name); pc = pField + fSkip; fSkip += *(pField + fSkip) + sizeof (char); if (pName->clsmask & CLS_ntype) { if ((cmpflag = fnCmp (pName, NULL, pc, pExState->state.fCase)) == 0) { // set type of typedef symbol pSymClass->possibles = 1; pName->possibles++; EVAL_STATE (pvF) = EV_type; EVAL_TYP(pvF) = newindex; } else if (pName->clsmask & CLS_enumerate) { // check if the nested type is an enum. if it is // we gotta search thru its field list for a matching // enumerate // sps - 9/14/92 HTYPE hEnum, hEnumField; // nested handle plfEnum pEnum; char *pEnumField; // field list of the enum record ulong enumCount; uint fSkip = 0; // offset in the field list uint anchor; // offset in the field list to start of type if (CV_IS_PRIMITIVE(newindex)) { break; } if ((hEnum = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) { pExState->err_num = ERR_BADOMF; return (SCN_error); } pEnum = (plfEnum) (&((TYPPTR)MHOmfLock (hEnum))->leaf); if (pEnum->leaf == LF_ENUM) { if (pEnum->property.fwdref) { eval_t localeval = *pvBase; neval_t nv = &localeval; // forward ref - look for the definition of the UDT if ((newindex = GetUdtDefnTindex (newindex, pvBase, (char *)&(pEnum->Name[0]))) != T_NOTYPE) { if ((hEnum = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) { pExState->err_num = ERR_BADOMF; return (SCN_error); } pEnum = (plfEnum) (&((TYPPTR)MHOmfLock (hEnum))->leaf); } else break; // No Fwd ref found... no CVInfo for nested type... proceed with search [rm] } if ((hEnumField = THGetTypeFromIndex (EVAL_MOD (pvBase), pEnum->field)) == 0) { if ( BindingBP ) { break; } else { pExState->err_num = ERR_BADOMF; return (SCN_error); } } pEnumField = (char *)(&((TYPPTR)MHOmfLock (hEnumField))->data); for (enumCount = pEnum->count; enumCount > 0; enumCount--) { fSkip += SkipPad(((uchar *)pEnumField) + fSkip); anchor = fSkip; DASSERT ((((plfEasy)(pEnumField + fSkip))->leaf) == LF_ENUMERATE); access = ((plfEnumerate)(pEnumField + fSkip))->attr; fSkip += offsetof (lfEnumerate, value); value = RNumLeaf (pEnumField + fSkip, &fSkip); pc = pEnumField + fSkip; fSkip += *(pEnumField + fSkip) + sizeof (char); if ((cmpflag = fnCmp (pName, NULL, pc, pExState->state.fCase)) == 0) { EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT); SetNodeType (pvF, pEnum->utype); EVAL_STATE (pvF) = EV_constant; EVAL_QUAD (pvF) = value; // save the casting data for the this pointer pSymClass->access = access; pSymClass->possibles = 1; pName->possibles++; break; } } MHOmfUnLock (hEnumField); } MHOmfUnLock (hEnum); } } break; default: pExState->err_num = ERR_BADOMF; retval = SCN_notfound; } #ifdef NEVER // if ((cnt == 0) && ** (pName->tTypeDef != 0)) { if ((cnt == 0) && (pName->tTypeDef != 0)) { // we found a typedef name that was not hidden by // a member or method name } #endif if (cmpflag == 0) { pSymClass->viable = TRUE; retval = SCN_found; break; } } if (hField != 0) { MHOmfUnLock (hField); } return (retval); } /** SetBPValue - set the breakpoint list from a class search * status = SetBPValue (pName) * Entry pName = pointer to structure describing search * pSymCl = pointer to class element * Exit pName updated to reflect found feature * this pointer inserted in bind tree if feature is part of * the class pointed to by this pointer of method * Returns SCN_rewrite if this pointer inserted (rebind required) * SCN_found if no error * SCN_error otherwise */ SCN_t SetBPValue ( psearch_t pName ) { peval_t pv; DASSERT ((pName->cFound == 0) && (pName->hFound == 0)); if (pSymClass->mlist != T_NOTYPE) { if ((pName->possibles == 1) || (bArgList != 0)) { switch (MatchMethod (pName, pSymClass)) { default: DASSERT (FALSE); case MTH_error: return (SCN_error); case MTH_found: break; } } else { // we have a list of functions and no argument list. // This means that we have an ambiguous breakpoint // and need to add the functions to the breakpoint // list for user disambiguation. Basically what // we are going to do is force all of the methods // into the breakpoint list and let later // binding resolve any errors. return (OverloadToAmbList (pName, pSymClass)); } } // at this point, the following values are set // pName->addr = address of method if not virtual method // pName->typeOut = type index of method // pName->hSym = handle of symbol for function pv = &pSymClass->evalP; if (fAnyVirtual(FCN_ATTR (pv).mprop)) { pExState->err_num = ERR_NOVIRTUALBP; return (SCN_error); } pv = pName->pv; *pv = pSymClass->evalP; EVAL_ACCESS (pv) = (uchar)(pSymClass->access.access); pName->typeOut = EVAL_TYP (pv); // save the offset of a class member // (caviar #1756) --gdp 9-10-92 if (pName->bnOp) { peval_t pvOp = &pName->bnOp->v[0]; EVAL_IS_MEMBER(pvOp) = TRUE; MEMBER_OFFSET(pvOp) = pName->initializer == INIT_right ? pSymClass->offset : 0; } return (SCN_found); } SCN_t OverloadToAmbList ( psearch_t pName, psymclass_t pSymCl ) { SCN_t retval; // add the first list of methods if ((retval = MethodsToAmbList (pName, pSymCl)) != SCN_found) { return (retval); } // loop through the remaining class descriptors adding them to the list while (pName->hAmbCl != 0) { MoveSymCl (pName->hAmbCl); if ((retval = MethodsToAmbList (pName,pSymCl)) != SCN_found) { return (retval); } } if (pExState->ambiguous == 0) { // no instantiated function has been found return (SCN_notfound); } SymToNode (pName); DASSERT (EVAL_TYP (pName->pv) != T_NOTYPE); return (SCN_found); } /** MethodsToAmbList - add a list of methods to ambiguous breakpoints * flag = MethodsToAmbList (pName, pSymCl) * Entry pName = pointer to search descriptor * pSymCl = pointer to symbol class structure * Exit methods added to list of ambiguous breakpoints * Returns SCN_found if methods added * SCN_error if error during addition */ SCN_t MethodsToAmbList ( psearch_t pName, psymclass_t pSymCl ) { HTYPE hMethod; pmlMethod pMethod; uint skip; CV_fldattr_t attr; CV_typ_t type; UOFFSET vtabind; HDEP hQual; peval_t pvF; ulong count = pSymCl->possibles; peval_t pvB; HMOD hMod; HDEP hTemp; psearch_t pTemp; bool_t retval; pvB = &pSymCl->symbase[pSymCl->CurIndex].Base; hMod = EVAL_MOD (pvB); // we now walk the list of methods adding each method to the list of // ambiguous breakpoints if ((hMethod = THGetTypeFromIndex (hMod, pSymCl->mlist)) == NULL) { DASSERT (FALSE); return (SCN_error); } // set the number of methods overloaded on this name and the index into // the method list skip = 0; while (count-- > 0) { // lock the omf record, extract information for the current entry in // the method list and increment to field for next method pMethod = (pmlMethod)((&((TYPPTR)MHOmfLock (hMethod))->leaf) + 1); pMethod = (pmlMethod)((uchar *)pMethod + skip); attr = pMethod->attr; type = pMethod->index; skip += sizeof (mlMethod); if (fIntroducingVirtual(pMethod->attr.mprop)) { vtabind = pMethod->vbaseoff[0]; skip += sizeof(pMethod->vbaseoff[0]); } else { vtabind = 0; } MHOmfUnLock (hMethod); // now add the method to the list pvF = &pSymCl->evalP; EVAL_MOD (pvF) = hMod; DASSERT (type != T_NOTYPE); if (SetNodeType (pvF, type) == FALSE) { return (SCN_error); } else { FCN_ATTR (pvF) = attr; FCN_VTABIND (pvF) = vtabind; FCN_VFPTYPE (pvF) = pSymCl->vfpType; pName->best.match = type; // If we have an expression such as pFoo->vFunc we // should not be setting a bp on CFoo::vFunc where // CFoo is the static type to which pFoo points. // We have to exclude the case where we are explicitly // setting a bp on CFoo::vfunc of course. if (BindingBP && (NODE_OP(pName->bnOp) != OP_bscope) && fAnyVirtual(FCN_ATTR(pvF).mprop)) { pExState->err_num = ERR_NOVIRTUALBP; return (SCN_error); } if (((hQual = GenQualName (pName, pSymCl)) == 0) || (SearchQualName (pName, pSymCl, hQual, TRUE) == FALSE)) { if (hQual != 0) { MemFree (hQual); } return (SCN_error); } MemFree (hQual); } if (FCN_NOTPRESENT (pvF) == FALSE) { if (pExState->ambiguous == 0) { // we have found the first function. We need to set all of // the return values in the pointer to the search entry pExState->ambiguous = pName->bn; // at this point, the following values are set // pName->addr = address of method if not virtual method // pName->typeOut = type index of method // pName->hSym = handle of symbol for function *pName->pv = pSymClass->evalP; EVAL_ACCESS (pName->pv) = (uchar)(pSymClass->access.access); pName->typeOut = EVAL_TYP (pName->pv); pName->hSym = EVAL_HSYM (pvF); } else { if ((hTemp = MemAllocate (sizeof (search_t))) == 0) { pExState->err_num = ERR_NOMEMORY; return (SCN_error); } pTemp = (psearch_t) MemLock (hTemp); *pTemp = *pName; pTemp->hSym = pvF->hSym; retval = AmbToList (pTemp); MemUnLock (hTemp); MemFree (hTemp); if (retval == FALSE) { return (SCN_error); } } } } return (SCN_found); } /** SetValue - set the result of the class search * status = SetValue (pName) * Entry pName = pointer to structure describing search * pSymClass = pointer to class element * Exit pName updated to reflect found feature * this pointer inserted in bind tree if feature is part of * the class pointed to by this pointer of method * Returns SCN_rewrite if this pointer inserted (rebind required) * SCN_found if no error * SCN_error otherwise */ SCN_t SetValue ( psearch_t pName ) { peval_t pv; peval_t pvOp; SCN_t retval; HDEP hQual; // When we get here, the situation is a bit complex. // If we are not binding breakpoints, the following conditions // must be true: // pName->hAmbCl = 0 (only one feature can remain after dominance) // pName->cFound = 0 // pName->hFound = 0 // pSymClass->viable = TRUE // If the feature is a data item (pSymClass->mlist == T_NOTYPE), then // pName->possibles = 1 // If the feature is a method, then // pName->possibles = number of overloads on name // pSymClass->mlist = type index of member list // bArgList = based pointer to argument list tree (cannot be 0) // Argument matching must result in a best match to a single method // If we are binding breakpoints, the following conditions must be true // pName->cFound = 0 // pName->hFound = 0 // pName->possibles = total number of methods in pSymClass and // pName->hAmbCl // pName->hAmbCl > 0 if two or more features survived dominance // Each of the features in pSymClass and the pName->hAmbCl list // must be a method list (pSymClass->mlist != T_NOTYPE) // If we do not have an argument list, then we accept all methods in // pSymClass->mlist and pName->hAmbCl.mlist. The number of methods is // pName->possibles. // If we do have an argument list, then we accept all methods in // pSymClass->mlist and pName->hAmbCl.mlist that are exact matches // for the argument list. Implicit conversions are not considered. // The number of methods must less than 1 + number of elements in the // list pName->hAmbCl and must be less than or equal to pName->possibles. if (BindingBP == TRUE) { // call the set of routines that will process breakpoints on methods // of a class, the inheritance tree of the class and the derivation // tree of the class. If the routine returns without error, pName // describes the first function breakpoint and hTMList describes the // remainder of the list of methods that match the function and // signature if one is specified. return (SetBPValue (pName)); } // At this point, there must be only one class after dominance resolution, // the count of the found items must be zero, and the handle of the found // item list must be null. Otherwise there was a failure in dominance // resolution. DASSERT ((pName->hAmbCl == 0) && (pName->cFound == 0) && (pName->hFound == 0) && (pSymClass->viable == TRUE)); if (pSymClass->mlist == T_NOTYPE) { DASSERT (pName->possibles == 1); } else if ((pName->possibles > 1) && (bArgList == 0)) { pExState->err_num = ERR_NOARGLIST; return (SCN_error); } // if we are processing C++, then we can allow for overloaded methods // which is specified by the type index of the method list not being // zero. If this is true, then we select the best of the overloaded // methods. if (pSymClass->mlist != T_NOTYPE) { switch (MatchMethod (pName, pSymClass)) { default: DASSERT (FALSE); case MTH_error: return (SCN_error); case MTH_found: // at this point, the following values are set // pName->addr = address of method if not virtual method // pName->typeOut = type index of method // pName->hSym = handle of symbol for function pv = &pSymClass->evalP; if (fNonIntroVirtual(FCN_ATTR (pv).mprop)) { // search to introducing virtual method if ((retval = FindIntro (pName)) != SCN_found) { return (retval); } } break; } } if (pName->initializer == INIT_AErule) { pv = pName->pv; *pv = pSymClass->evalP; pName->typeOut = EVAL_TYP (pv); return SCN_found; } // the symbol is a data member of the class (C or C++). If an // explict class was not specified and the current context is // implicitly a class (we are in the scope of the method of the class), // then we rewrite the tree to change the symbol reference to this->symbol if ((pName->initializer != INIT_base) && (pName->initializer != INIT_sym) && (pName->ExpClass == 0)) { //DASSERT (FALSE); pExState->err_num = ERR_INTERNAL; return (SCN_error); } else if ((pName->ExpClass == 0) && (ClassImp != 0) && (pName->initializer != INIT_base) && !EVAL_IS_STMEMBER(&pSymClass->evalP)) { // CUDA #4030: handle access to static members from // inside a static member function w/o referring to "this" // don't run this code for static members because "this" // might not be available [rm] // if we are looking at a nested enumerate - don't need the // rewrite // sps 9/15/92 // or if we are looking at a base class or nested class type // we don't need to rewrite // rm 5/6/93 ulong state = EVAL_STATE(&(pSymClass->evalP)); if (state == EV_constant || state == EV_type) { *pName->pv = pSymClass->evalP; return(SCN_found); } // if the feature is a member of *this class of a method, then // we need to rewrite // feature // to // this->feature // The calling routine will need to rebind the expression InsertThis (pName); return (SCN_rewrite); } // CUDA #4030: do minimal setup of *pv in the INIT_sym case so that we do // the right search in the static member access case. Otherwise // the initializer for the search must be INIT_right or INIT_base. // by the time we get to here we know that bnOp is the based pointer to // the node that will receive the casting expression and pv points // to the feature node. pv = pName->pv; pvOp = &pName->bnOp->v[0]; switch (pName->initializer) { case INIT_right: *pv = pSymClass->evalP; EVAL_ACCESS (pv) = (uchar)(pSymClass->access.access); pName->typeOut = EVAL_TYP (pv); EVAL_IS_MEMBER (pvOp) = TRUE; MEMBER_TYPE (pvOp) = EVAL_TYP (pv); MEMBER_OFFSET (pvOp) = pSymClass->offset; MEMBER_ACCESS (pvOp) = pSymClass->access; if ((pSymClass->isvbase == TRUE) || (pSymClass->isivbase == TRUE)) { MEMBER_VBASE (pvOp) = pSymClass->isvbase; MEMBER_IVBASE (pvOp) = pSymClass->isivbase; MEMBER_VBPTR (pvOp) = pSymClass->vbptr; MEMBER_VBPOFF (pvOp) = pSymClass->vbpoff; MEMBER_VBIND (pvOp) = pSymClass->vbind; } break; case INIT_base: *pv = pSymClass->symbase[pSymClass->CurIndex].Base; EVAL_ACCESS (pv) = (uchar)(pSymClass->symbase[pSymClass-> CurIndex].attrBC.access); pName->typeOut = EVAL_TYP (pv); EVAL_IS_MEMBER (pvOp) = TRUE; EVAL_ACCESS (pvOp) = (uchar)(pSymClass->symbase[pSymClass-> CurIndex].attrBC.access); MEMBER_OFFSET (pvOp) = 0; break; case INIT_sym: // CUDA #4030: handle access to static members from // inside a static member function w/o referring to "this" [rm] // symbol MUST BE a static member, just setup *pv... DASSERT(EVAL_IS_STMEMBER(&pSymClass->evalP)); *pv = pSymClass->evalP; break; default: DASSERT (FALSE); return (SCN_error); } if (EVAL_IS_STMEMBER (pv) == FALSE) { // the feature is not a static data member of the class return (GenQualExpr (pName)); } else { // the feature is a static member so we need to generate the // qualified path and search for a symbol of the correct type // so we can set the address if (((hQual = GenQualName (pName, pSymClass)) == 0) || (SearchQualName (pName, pSymClass, hQual, FALSE) == FALSE)) { if (hQual != 0) { MemFree (hQual); } return (SCN_error); } *pv = pSymClass->evalP; EVAL_STATE (pv) = EV_lvalue; MemFree (hQual); return (SCN_found); } } // Support routines /** AddETConst - add evalthisconst node * pn = AddETConst (pnP, off, btype) * Entry pnP = pointer to previous node * Exit OP_evalthisconst node added to bind tree * current node linked to pnP as left child if pnP != NULL * pTree->node_next advanced * btype = type of the base class * Returns pointer to node just allocated */ pnode_t AddETConst ( pnode_t pnP, UOFFSET off, CV_typ_t btype ) { pnode_t pn; padjust_t pa; pn = (pnode_t)(((char *)pTree) + pTree->node_next); pa = (padjust_t)(&pn->v[0]); memset (pn, 0, sizeof (node_t) + sizeof (adjust_t)); NODE_OP (pn) = OP_thisconst; pa->btype = btype; pa->disp = off; if (pnP != NULL) { NODE_LCHILD (pnP) = (bnode_t)pn; } pTree->node_next += sizeof (node_t) + sizeof (adjust_t); return (pn); } /** AddETInit - add evalthisinit node * pn = AddETInit (pnP, btype) * Entry pnP = pointer to previous node * Exit OP_evalthisinit node added to bind tree * current node linked to pnP as left child if pnP != NULL * pTree->node_next advanced * btype = type of the base class * Returns pointer to node just allocated */ pnode_t AddETInit ( pnode_t pnP, CV_typ_t btype ) { pnode_t pn; padjust_t pa; pn = (pnode_t)(((char *)pTree) + pTree->node_next); pa = (padjust_t)(&pn->v[0]); memset (pn, 0, sizeof (node_t) + sizeof (adjust_t)); NODE_OP (pn) = OP_thisinit; pa->btype = btype; if (pnP != NULL) { NODE_LCHILD (pnP) = (bnode_t)pn; } pTree->node_next += sizeof (node_t) + sizeof (adjust_t); return (pn); } /** AddETExpr - add evalthisexpr node * pn = AddETExpr (pnP, vbptr, vbpoff, vbind, btype) * Entry pnP = pointer to previous node * vbptr = type index of virtual base pointer * vboff = offset of vbptr from address point * vbdisp = offset of displacement in virtual base table * btype = type of the base class * Exit OP_evalthisconst node added to bind tree * current node linked to pnP as left child if pnP != NULL * pTree->node_next advanced * Returns pointer to node just allocated * The evaluation of this node will result in * ab = (ap * vbpoff) + *(*(ap +vbpoff) + vbdisp) * where * ab = address of base class * ap = current address point */ pnode_t AddETExpr ( pnode_t pnP, CV_typ_t vbptr, UOFFSET vbpoff, UOFFSET vbdisp, CV_typ_t btype ) { pnode_t pn; padjust_t pa; pn = (pnode_t)(((char *)pTree) + pTree->node_next); pa = (padjust_t)(&pn->v[0]); memset (pn, 0, sizeof (node_t) + sizeof (adjust_t)); NODE_OP (pn) = OP_thisexpr; pa->btype = btype; pa->disp = vbdisp; pa->vbpoff = vbpoff; pa->vbptr = vbptr; if (pnP != NULL) { NODE_LCHILD (pnP) = (bnode_t)pn; } pTree->node_next += sizeof (node_t) + sizeof (adjust_t); return (pn); } /*** AddVBList - Add virtual bases to searched or dominated list * status = AddVBList (pSymClass, ppList, phMem) * Entry pSymClass = pointer to base class path list structure * ppList = pointer to dominated or searched list * phMem = pointer to handle for ppList * Exit virtual bases added to list * Return SCN_found if all bases added to list * SCN_error if bases could not be added */ SCN_t AddVBList ( psymclass_t pSymClass, pdombase_t *ppList, HDEP * phList ) { ulong cnt; // count of number of elements in struct HTYPE hField; // handle to type record for struct field list char *pField; // pointer to field list uint fSkip = 0; // offset in the field list uint anchor; // offset in the field list to start of type CV_typ_t newindex; SCN_t retval = SCN_found; bool_t termflag = FALSE; peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base; // set hField to the handle of the field list for the class if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), CLASS_FIELD (pvBase))) == 0) { pExState->err_num = ERR_BADOMF; return (SCN_error); } pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); // walk field list for the class for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) { fSkip += SkipPad(((uchar *)pField) + fSkip); anchor = fSkip; switch (((plfEasy)(pField + fSkip))->leaf) { case LF_INDEX: // switch to new type record because compiler split it up newindex = ((plfIndex)(pField + fSkip))->index; MHOmfUnLock (hField); if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) { pExState->err_num = ERR_INTERNAL; return (SCN_error); } pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data); fSkip = 0; // the LF_INDEX is not part of the field count cnt++; break; case LF_BCLASS: // skip direct base class fSkip += offsetof (lfBClass, offset); RNumLeaf (pField + fSkip, &fSkip); break; case LF_VBCLASS: case LF_IVBCLASS: newindex = ((plfVBClass)(pField + fSkip))->index; if ((retval = AddVBType (ppList, phList, newindex)) == SCN_error) { termflag = TRUE; break; } fSkip += offsetof (lfVBClass, vbpoff); RNumLeaf (pField + fSkip, &fSkip); RNumLeaf (pField + fSkip, &fSkip); break; default: termflag = TRUE; break; } if (termflag == TRUE) { break; } } MHOmfUnLock (hField); return (retval); } /*** AddVBType - Add virtual base to list * status = AddVBType (ppList, phList, type) * Entry ppList = pointer to dominated or searched list * phList = pointer to handle for ppList * type = type index * Exit type added to list * Return SCN_found if all bases added to list * SCN_error if bases could not be added */ SCN_t AddVBType ( pdombase_t *ppList, HDEP *phList, CV_typ_t type ) { ulong i; bool_t add = TRUE; ulong len; pdombase_t pList = *ppList; HDEP hList; for (i = 0; i < pList->CurIndex; i++) { if (type == pList->dom[i]) { add = FALSE; break; } } if (add == TRUE) { if (pList->CurIndex >= pList->MaxIndex) { len = sizeof (dombase_t) + (pList->MaxIndex + 10) * sizeof (CV_typ_t); MemUnLock (*phList); if ((hList = MemReAlloc (*phList, len)) == 0) { pExState->err_num = ERR_NOMEMORY; pList = (pdombase_t) MemLock (*phList); return (SCN_error); } else { *phList = hList; *ppList = pList = (pdombase_t) MemLock (*phList); pList->MaxIndex += 10; } } pList->dom[pList->CurIndex++] = type; } return (SCN_found); } /** AmbFromList - add get next ambiguous symbol from list * status = AmbFromList (pName) * Entry pName = pointer to list describing search * Exit breakpoint added to list of breakpoints * pName reset to continue breakpoint search * Returns HR_found if breakpoint added * HR_error if breakpoint could not be added to list */ ulong AmbFromList ( psearch_t pName ) { psearch_t pBPatch; pBPatch = (psearch_t) MemLock (hBPatch); *pName = *pBPatch; MemUnLock (hBPatch); pName->pv = &pName->bn->v[0]; EVAL_HSYM (pName->pv) = pName->hSym; if ((SymToNode (pName) == TRUE) && (PushStack (pName->pv) == TRUE)) { return (HR_found); } else { return (HR_error); } } /** AmbToList - add ambiguous symbol to list * fSuccess = AmbToList (pName) * Entry pName = pointer to list describing search * Exit ambiguous symbol added to list pointed to by pTMList * pTMLbp * Returns TRUE if symbol added * FALSE if error */ bool_t AmbToList ( psearch_t pName ) { HDEP hBPatch; psearch_t pBPatch; if (iBPatch >= pTMLbp->cTMListMax) { // the back patch list has filled the TM list if (!GrowTMList ()) { pExState->err_num = ERR_NOMEMORY; return (FALSE); } } if ((hBPatch = MemAllocate (sizeof (search_t))) != 0) { pTMList[iBPatch++] = hBPatch; pBPatch = (psearch_t) MemLock (hBPatch); *pBPatch = *pName; // save address of function in order to check for // duplicates pBPatch->typeOut = EVAL_TYP(pName->pv); pBPatch->addr = EVAL_SYM(pName->pv); MemUnLock (hBPatch); return (TRUE); } else { pExState->err_num = ERR_NOMEMORY; return (FALSE); } } /** DupSymCl - duplicate symbol class structure and link to list * DupSymCl (pName); * Entry pName = handle of structure describing search * *pSymClass = symbol class structure * Exit *pSymClass = duplicated and linked to list pName->hFound * pSymClass->viable = FALSE * Returns SCN_found if pSymClass duplicated * SCN_error if unable to allocate memory for duplication */ SCN_t DupSymCl ( psearch_t pName ) { HDEP hSymCl; psymclass_t pSymCl; ulong size; size = (ulong ) (sizeof (symclass_t) + (pSymClass->CurIndex + 1) * sizeof (symbase_t)); if ((hSymCl = MemAllocate (size)) == 0) { pExState->err_num = ERR_NOMEMORY; return (SCN_error); } pSymCl = (psymclass_t) MemLock (hSymCl); memmove (pSymCl, pSymClass, size); pSymCl->MaxIndex = (ulong )(pSymCl->CurIndex + 1); pSymCl->hNext = pName->hFound; pName->hFound = hSymCl; pName->cFound++; pSymClass->viable = FALSE; MemUnLock (hSymCl); return (SCN_found); } /** FindIntro - find introducing virtual method * status = FindIntro (pName) * Entry pName = structure describing search * pSymClass = structure describing class search * Exit pSymClass updated to reflect introducing virtual method * Returns SCN_found if introducing virtual method found * SCN_error if introducing virtual method not found */ SCN_t FindIntro ( psearch_t pName ) { ulong oldmask; SCN_t retval; bool_t fSupBaseSaved; unsigned char cbNameSaved; oldmask = pName->clsmask; cbNameSaved = pName->sstr.cb; fSupBaseSaved = pExState->state.fSupBase; // CV400 #2863 look at all bases [rm] pExState->state.fSupBase = FALSE; // CV400 #2863 // destructor's don't have same name look only for the '~' [rm] if (pName->sstr.lpName[0] == '~') pName->sstr.cb = 1; // limit searches to introducing virtual methods // the CLS_vfunc is set so that we pick up the vfuncptr information pName->clsmask = CLS_virtintro | CLS_vfunc | CLS_method; retval = SearchBases (pName); pName->clsmask = oldmask; // restore name length and fSupBase [rm] pExState->state.fSupBase = fSupBaseSaved; pName->sstr.cb = cbNameSaved; return (retval); } /*** GenQualName - generate qualified method name * handle = GenQualName (pName, pSymClass) * Entry pSymCLass = pointer to struct describing search * Exit qualified function name generated * Returns 0 if name string not generated * handle if name string generated */ HDEP GenQualName ( psearch_t pName, psymclass_t pSymCl ) { HDEP hQual; char *pQual; uint buflen = 255; uint len; uint fSkip; char *pField; // pointer to field list HTYPE hBase; // handle to type record for base class char *pc; int i; peval_t pL; if ((hQual = MemAllocate (buflen + 1)) == 0) { // unable to allocate memory pExState->err_num = ERR_NOMEMORY; return (0); } pQual = (char *) MemLock (hQual); memset (pQual, 0, 256); // walk up list of search structures adding qualifiers for (i = 0; i <= pSymCl->CurIndex; i++) { if (CLASS_PROP (&pSymCl->symbase[i].Base).cnested != 0) { NOTTESTED (FALSE); } if ((pSymCl->symbase[i].clsmask & CLS_virtintro) == CLS_virtintro) { // if the search turned into a search for the introducing virtual // function, break out of this loop so that the method name is // correct break; } pL = &pSymCl->symbase[i].Base; } // copy name of last class encountered if ((hBase = THGetTypeFromIndex (EVAL_MOD (pL), EVAL_TYP (pL))) == 0) { pExState->err_num = ERR_INTERNAL; return (0); } pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->leaf); switch (((plfClass)pField)->leaf) { case LF_CLASS: case LF_STRUCTURE: fSkip = offsetof (lfClass, data); RNumLeaf (pField + fSkip, &fSkip); pc = pField + fSkip; break; case LF_UNION: fSkip = offsetof (lfUnion, data); RNumLeaf (pField + fSkip, &fSkip); pc = pField + fSkip; break; default: DASSERT (FALSE); MHOmfUnLock (hBase); MemUnLock (hQual); return (hQual); } len = *pc++; if ((len + 2) <= buflen) { memcpy (pQual, pc, len); pQual += len; *pQual++ = ':'; *pQual++ = ':'; buflen -= len + 2; } memcpy (pQual, pName->sstr.lpName, pName->sstr.cb); MHOmfUnLock (hBase); MemUnLock (hQual); return (hQual); } /*** pvThisFromST - generate expression for null path to qualified name * status = pvThisFromST (bnOp) * Entry bnOp = node to add init expression to * Exit qualified path expression generated * Returns TRUE if expression generated * FALSE if no memory */ bool_t pvThisFromST ( bnode_t bnOp ) { uint len; pnode_t Parent; peval_t pvOp; int diff; if (ST == NULL) { return (FALSE); } // we need to generate an expression tree attached to the operator node // which will compute the null this pointer adjustment from ST. This // routine is used for pClass->Class::member len = sizeof (node_t) + sizeof (adjust_t); if ((diff = pTree->size - pTree->node_next - len) < 0) { if (!GrowETree ((uint) (-diff))) { pExState->err_num = ERR_NOMEMORY; return (FALSE); } if (bnCxt != 0) { // the context was pointing into the expression tree. // since the expression tree could have been reallocated, // we must recompute the context pointer pCxt = SHpCXTFrompCXF ((PCXF)&((pnode_t)bnCxt)->v[0]); } } pvOp = &bnOp->v[0]; EVAL_IS_MEMBER (pvOp) = TRUE; MEMBER_THISEXPR (pvOp) = pTree->node_next; Parent = NULL; // now add the node that causes pvThis to be initialized with the // value of ST. AddETInit (Parent, EVAL_TYP (ST)); return (TRUE); } /*** GenQualExpr - generate expression for path to qualified name * status = GenQualExpr (pName) * Entry pName = pointer to struct describing search * pSymClass = pointer to class path structure * Exit qualified path expression generated * Returns SCN_found is expression generated * SCN_error if no memory */ SCN_t GenQualExpr ( psearch_t pName ) { int i; peval_t pvOp; uint len; pnode_t Parent; int diff; peval_t pvB; CV_typ_t btype; UOFFSET off; uint pvOff = 0; // we need to generate an expression tree attached to the operator node // which will compute the this pointer adjustment. The number // of nodes is potentially the number of base classes + an // initializer. // M00OPTIMIZE - if the final base is a direct or indirect virtual base // M00OPTIMIZE - of the inital class, then the entire expression can be // M00OPTIMIZE - reduced to one node + the initializer len = (pSymClass->CurIndex + 2) * (sizeof (node_t) + sizeof (adjust_t)); pvOp = &pName->bnOp->v[0]; if ((diff = pTree->size - pTree->node_next - len) < 0) { if (((char *)(pName->pv) >= (char *)pTree) && ((char *)(pName->pv) < ((char *)pTree) + pTree->size)) { pvOff = (uint)(((char *)pName->pv) - ((char *)pTree)); } if (!GrowETree ((uint) (-diff))) { pExState->err_num = ERR_NOMEMORY; return (SCN_error); } if (bnCxt != 0) { // the context was pointing into the expression tree. // since the expression tree could have been reallocated, // we must recompute the context pointer pCxt = SHpCXTFrompCXF ((PCXF)&((pnode_t)bnCxt)->v[0]); } if (pvOff != 0) { pName->pv = (peval_t)(((char *)pTree) + pvOff); } pvOp = &pName->bnOp->v[0]; } // walk the path backwards generating the expression required to do // the adjustment. The backwards walk is because evaluation is depth // first. MEMBER_THISEXPR (pvOp) = pTree->node_next; Parent = NULL; for (i = pSymClass->CurIndex; i > 0; i--) { pvB = &pSymClass->symbase[i].Base; btype = EVAL_TYP (pvB); off = pSymClass->symbase[i].thisadjust; if (pSymClass->symbase[i].fVirtual == TRUE) { Parent = AddETExpr (Parent, pSymClass->symbase[i].vbptr, pSymClass->symbase[i].vbpoff, off, btype); } else { Parent = AddETConst (Parent, off, btype); } } // add the first real adjustment if necessary. What is really happening // here is that the the expression was of the form x.CLASS::member and // we need an adjustment from the object to the start of the base class pvB = &pSymClass->evalP; btype = EVAL_TYP (pvB); if ((EVAL_STATE (pvB) == EV_type) && EVAL_IS_CLASS (pvB)) { Parent = AddETConst (Parent, pSymClass->offset, btype); } // now add the node that causes pvThis to be initialized with the // value of ST. pvB = &pSymClass->symbase[i].Base; btype = EVAL_TYP (pvB); Parent = AddETInit (Parent, btype); return (SCN_found); } /** GetArgType - get type of argument to function * fSuccess = GetArgType (pvF, argn, ptype); * Entry pvF = pointer to function description * argn = argument index (0-based) * ptype = pointer to location to store type * Exit *ptype = type of argument * *ptype = 0 if vararg * Returns FARG_error if error * FARG_none if no arguments * FARG_vararg if varargs allowed * FARG_exact if exact list */ farg_t GetArgType ( peval_t pvF, int argn, CV_typ_t *type ) { HTYPE hList; // handle of the type list plfArgList pList = NULL; register farg_t retval; if (FCN_PCOUNT (pvF) == 0) { // there are no formals. We need to check for varargs *type = 0; if (FCN_VARARGS (pvF) == TRUE) { return (FARG_vararg); } else { return (FARG_none); } } // set hList to the handle of the type list if ((hList = THGetTypeFromIndex (EVAL_MOD (pvF), FCN_PINDEX (pvF))) == NULL) { DASSERT (FALSE); return (FARG_error); } if (argn >= FCN_PCOUNT (pvF) - 1) { // this argument can possibly be a vararg. if (FCN_VARARGS (pvF) == TRUE) { *type = 0; retval = FARG_vararg; } else if (argn > FCN_PCOUNT (pvF)) { // varargs are not allowed and the maximum arg count is exceeded retval = FARG_error; } else { // varargs are not allowed and this is the last argument pList = (plfArgList)(&((TYPPTR)MHOmfLock (hList))->leaf); *type = pList->arg[argn]; retval = FARG_exact; } } else { // this is before the last argument so it cannot be a vararg // load type list and store type of argument pList = (plfArgList)(&((TYPPTR)MHOmfLock (hList))->leaf); *type = pList->arg[argn]; retval = FARG_exact; } if (pList != NULL) { MHOmfUnLock (hList); } return (retval); } /** VBSearched - check to see if virtual base hase already been searched * flag = VBSearched (type) * Entry type = type index of virtual base * Exit none * Returns TRUE if virtual base has already been searched * FALSE if virtual base has not been searched */ bool_t VBSearched ( CV_typ_t type ) { ulong i; for (i = 0; i < pVBSearch->CurIndex; i++) { if (pVBSearch->dom[i] == type) { return (TRUE); } } return (FALSE); } /** GrowTMList - grow TML * fSuccess = GrowTMList (void) * Entry pTMLbp = pointer to TML * pTMList = pointer to TM list * Exit TML grown * pTMList = pointer to locked table * Returns TRUE if table grown * FALSE if out of memory */ bool_t GrowTMList ( void ) { register bool_t retval = FALSE; HDEP hTMList; MemUnLock (pTMLbp->hTMList); if ((hTMList = MemReAlloc (pTMLbp->hTMList, (pTMLbp->cTMListMax + TMLISTCNT) * sizeof (HTM))) != 0) { pTMLbp->hTMList = hTMList; pTMLbp->cTMListMax += TMLISTCNT; retval = TRUE; } // lock list to maintain lock/unlock synchronization pTMList = (HDEP *) MemLock (pTMLbp->hTMList); return (retval); } /** IncrSymBase - increment symbase_t index and grow if necessary * status = IncrSymbase (); * Entry none * Exit *pSymClass->CurIndex incremented * pSymBase grown if necessary * Returns SCN_found if pSymClass->CurIndex incremented * SCN_error if unable to allocate memory for duplication */ SCN_t IncrSymBase ( void ) { uint size; HDEP hNew; if (++pSymClass->CurIndex >= pSymClass->MaxIndex) { size = sizeof (symclass_t) + (pSymClass->CurIndex + 5) * sizeof (symbase_t); MemUnLock (hSymClass); if ((hNew = MemReAlloc (hSymClass, size)) == 0) { pExState->err_num = ERR_NOMEMORY; pSymClass = (psymclass_t) MemLock (hSymClass); pSymClass->CurIndex--; return (SCN_error); } hSymClass = hNew; pSymClass = (psymclass_t) MemLock (hSymClass); pSymClass->MaxIndex += 5; } return (SCN_found); } /** IsDominated - check to see of feature is dominated * fStatus = IsDominated (pSymBest, pSymTest) * Entry pName = structure describing search * pSymClass = structure describing most recent class search * Exit pName updated to reflect search * pSymClass updated to unambiguous feature * Returns DOM_replace if pSymBest is dominated by pSymTest * DOM_keep if pSymBest is exactly equivalent to pSymTest * DOM_ambiguous if pSymBest is equal to pSymTest * DOM_keep if pSymTest is duplicate virtual base */ DOM_t IsDominated ( psymclass_t pSymBest, psymclass_t pSymTest ) { int i; int j; if (pSymBest->isdupvbase == TRUE) { return (DOM_replace); } if (pSymTest->isdupvbase == TRUE) { return (DOM_keep); } // check all of the base classes for a dominated virtual base for (i = 0; i <= pSymBest->CurIndex; i++) { if (pSymBest->symbase[i].fVirtual == TRUE) { for (j = pVBDom->CurIndex; j >= 0; j--) { if (pVBDom->dom[j] == EVAL_TYP (&pSymBest->symbase[i].Base)) { return (DOM_replace); } } } } for (i = 0; i <= pSymTest->CurIndex; i++) { if (pSymTest->symbase[i].fVirtual == TRUE) { for (j = pVBDom->CurIndex; j >= 0; j--) { if (pVBDom->dom[j] == EVAL_TYP (&pSymTest->symbase[i].Base)) { return (DOM_keep); } } } } // we have two paths to potentially two different features. We now check // to see if the features are identical. This is done by checking for // static data members that have identical addresses and types if (!EVAL_IS_STMEMBER (&pSymBest->evalP) || !EVAL_IS_STMEMBER (&pSymTest->evalP) || (EVAL_TYP (&pSymBest->evalP) != EVAL_TYP (&pSymTest->evalP)) || (EVAL_SYM_SEG (&pSymBest->evalP) != EVAL_SYM_SEG (&pSymTest->evalP)) || (EVAL_SYM_OFF (&pSymBest->evalP) != EVAL_SYM_OFF (&pSymTest->evalP))) { return (DOM_ambiguous); } return (DOM_keep); } /** IsIntroVirt - is this the introducing virtual method * Entry mlist = type index of lf mfunc * pvtabind = pointer to virtual function table index * Exit *pvtabind = virtual fuction table index * Returns TRUE if the introducing virtual method is found * FALSE otherwise */ bool_t IsIntroVirt( CV_typ_t tiMfunc ) { HTYPE hMethod; HMOD hMod; bool_t retval; peval_t pvF; plfMFunc pMFunc; pvF = &pSymClass->evalP; hMod = EVAL_MOD (pvF); if ((hMethod = THGetTypeFromIndex (hMod, tiMfunc)) == NULL) { DASSERT (FALSE); return (FALSE); } pMFunc = (plfMFunc)((&((TYPPTR)MHOmfLock (hMethod))->leaf)); retval = (pMFunc->rvtype == FCN_RETURN (pvF)) && (pMFunc->arglist == FCN_PINDEX (pvF)); MHOmfUnLock (hMethod); return retval == TRUE; } /** IsIntroVirtInMlist - is this the introducing virtual method in this mlist * fSuccess = IsIntroVirtInMlist (count, mlist, pvtabindex) * Entry count = number of methods in list * mlist = type index of method list * pvtabind = pointer to virtual function table index * Exit *pvtabind = virtual fuction table index * Returns TRUE if the introducing virtual method is found * FALSE otherwise */ bool_t IsIntroVirtInMlist( ulong count, CV_typ_t mlist, UOFFSET *pvtabind ) { HTYPE hMethod; pmlMethod pMethod; uint cbSkip; bool_t Mmatch = 0; peval_t pvF; HMOD hMod; pvF = &pSymClass->evalP; hMod = EVAL_MOD (pvF); // we now walk the list of methods looking for a method with the same // return type and argument list type if ((hMethod = THGetTypeFromIndex (hMod, mlist)) == NULL) { DASSERT (FALSE); return (FALSE); } // set the number of methods overloaded on this name and the index into // the method list cbSkip = 0; *pvtabind = 0; while (count-- > 0) { // lock the omf record, extract information for the current entry in // the method list and increment to field for next method plfMethodList plfMList; plfMList = (plfMethodList) &((TYPPTR) MHOmfLock(hMethod))->leaf; pMethod = (pmlMethod) &plfMList->mList[cbSkip]; cbSkip += sizeof (mlMethod); if (fIntroducingVirtual(pMethod->attr.mprop)) { cbSkip += sizeof(pMethod->vbaseoff[0]); if (IsIntroVirt(pMethod->index)) { *pvtabind = pMethod->vbaseoff[0]; MHOmfUnLock(hMethod); return TRUE; } } MHOmfUnLock (hMethod); } return (FALSE); } /** MatchArgs - match a method against argument list * flag = MatchArgs (pv, pName, fattr, vtabind, fForce) * Entry pv = pointer to function descriptor * pName = pointer to search structure * attr = attribute if method * vtabind = offset into vtable if virtual method * fForce = TRUE if match on first (only) method is forced * This is the case if bp method, no args and single * method. * BindingBP = TRUE if call is via ParseBP API entry * if BindingBP is true, then only exact matches are allowed * bArgList = based pointer to argument list * Exit ST = resolved address of method * Returns TRUE if a match was found or ambiguous references are allowed * FALSE if no match or ambiguity not allowed */ void MatchArgs ( peval_t pvM, psearch_t pName, CV_fldattr_t attr, UOFFSET vtabind, bool_t fForce ) { pnode_t pnT; pargd_t pa; bool_t update = FALSE; argcounters current; int argc; CV_typ_t Ftype; bool_t argmatch; eval_t evalArg; peval_t pvArg = &evalArg; // walk down the formal list specified by pvM and the actual list // specified by bArgList. Initialize the conversion counters to // zero and set the index to varargs parameter to zero argc = 0; current.exact = 0; current.implicit = 0; current.varargs = 0; argmatch = FALSE; pnT = (pnode_t)bArgList; (pName->overloadCount)++; if (fForce == TRUE) { argmatch = TRUE; update = TRUE; } else if (!N_EVAL_IS_FCN(pvM)) { argmatch = TRUE; current.exact = 0; } else while (TRUE) { if (NODE_OP (pnT) == OP_endofargs) { if ((argc == FCN_PCOUNT (pvM)) || ((argc >= (FCN_PCOUNT (pvM) - 1)) && (FCN_VARARGS (pvM) == TRUE))) { argmatch = TRUE; } break; } if ((argc > FCN_PCOUNT (pvM)) && (FCN_VARARGS (pvM) == FALSE)) { // this function cannot possibly be a match because the // number of actuals is greater than the number of formals // and the method does not allow varargs. break; } // pa points to the argument descriptor array in the OP_arg node pa = (pargd_t)&(pnT->v[0]); switch (GetArgType (pvM, argc, &Ftype)) { case FARG_error: DASSERT (FALSE); return; case FARG_none: // special case foo(void) // sps 2/20/92 if ((argc == 0) && (pa->actual == T_VOID)) { argmatch = TRUE; goto argmatchloop; } return; case FARG_vararg: // varargs are allowed unless we are binding breakpoints if (BindingBP == TRUE) { return; } break; case FARG_exact: if ((argc + 1) > FCN_PCOUNT (pvM)) { // we must exactly match the argument count and we // have more arguments return; } break; } argc++; if (Ftype == 0) { // all arguments from this point on are vararg current.varargs = argc; pa->current = OM_vararg; } else { CV_typ_t Atype = pa->actual; eval_t vA, vF; peval_t pvA = &vA; peval_t pvF = &vF; if (pa->flags.istype) { // If we have a type want identical type indices // (This helps with class dumps) #if CC_LAZYTYPES if ( THAreTypesEqual( EVAL_MOD( pvM ), Atype, Ftype ) ) #else if ( Atype == Ftype ) #endif { current.exact++; pa->current = OM_exact; pnT = (pnode_t)NODE_RCHILD (pnT); continue; } else { pExState->err_num = ERR_NONE; break; } } Ftype = SkipModifiers(EVAL_MOD(pvM), Ftype); Atype = SkipModifiers(EVAL_MOD(pvM), Atype); *pvF = *pvM; if (!SetNodeType(pvF, Ftype)) { // error (not valid type) break; } // Update Ftype (SetNodeType must have resolved potential fwd refs) Ftype = EVAL_TYP (pvF); // if we are calling a 32 bit func we must promote all const // int2's to int4's if (EVAL_SYM_IS32(pvM) && (EVAL_STATE((peval_t)(&((pnode_t)NODE_LCHILD (pnT))->v[0])) == EV_constant) && ((Atype == T_INT2) || (Atype == T_UINT2)) ) { Atype++; } *pvA = *pvM; if (!SetNodeType(pvA, Atype)) { // error (not valid type) break; } if (EVAL_IS_PTR(pvA) && EVAL_IS_REF(pvA)) { Atype = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE(pvA)); } #if CC_LAZYTYPES if ( THAreTypesEqual( EVAL_MOD( pvM ), Atype, Ftype ) ) #else if (Atype == Ftype) #endif { current.exact++; pa->current = OM_exact; pnT = (pnode_t)NODE_RCHILD (pnT); continue; } if (EVAL_IS_PTR(pvF)) { *pvA = *pvM; if (!SetNodeType(pvA, Atype)) { // error (not valid type) break; } if (!EVAL_IS_REF(pvF)) { if (!EVAL_IS_PTR(pvA)) { // do not cast a non-pointer to pointer break; } PTR_UTYPE(pvA) = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE(pvA)); PTR_UTYPE(pvF) = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE(pvF)); if (EVAL_PTRTYPE(pvA) == EVAL_PTRTYPE(pvF) && #if CC_LAZYTYPES THAreTypesEqual( EVAL_MOD( pvA ), PTR_UTYPE(pvA), PTR_UTYPE(pvA) ) && #else PTR_UTYPE(pvA) == PTR_UTYPE(pvF) && #endif !EVAL_IS_BASED(pvA) && !EVAL_IS_BASED(pvF)) { // we don't match based pointers. if we want to // do this we must examine additional information // we allow mathcing a pointer with an array // however all arrays are considered far // since codeview information does not distinguish // between far or near arrays. --gdp 10/16/92 current.exact++; pa->current = OM_exact; pnT = (pnode_t)NODE_RCHILD (pnT); continue; } } else { // special handling of a reference CV_typ_t Utype; Utype = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE (pvF)); #if CC_LAZYTYPES if ( THAreTypesEqual( EVAL_MOD( pvM ), Utype, Atype ) ) #else if (Utype == Atype) #endif { current.exact++; pa->current = OM_exact; pnT = (pnode_t)NODE_RCHILD (pnT); continue; } else { break; } } } // see if we can cast the type of the actual to the type of // the formal if we are not binding breakpoints. If we are // binding breakpoints, only exact matches are allowed *pvArg = *pvM; SetNodeType (pvArg, pa->actual); if (EVAL_IS_BITF (pvArg)) { SetNodeType (pvArg, BITF_UTYPE (pvArg)); } if (CastNode (pvArg, Ftype, Ftype)) { pa->current = OM_implicit; current.implicit++; } else { pExState->err_num = ERR_NONE; break; } } pnT = (pnode_t)NODE_RCHILD (pnT); } argmatchloop: if (argmatch == TRUE) { // check current against best match if (pName->best.match == 0) { // we have a first time match update = TRUE; pName->possibles++; } else if (fForce == FALSE) { // we have already matched on some function so we now // check to see if the current is better than the best if (current.varargs == 0) { // there are no varargs in this method therefor it is // better than any previous match with varargs if (pName->best.varargs != 0) { update = TRUE; pName->best = current; pName->possibles = 1; } else if (current.exact > pName->best.exact) { // this function has more exact matches than the // best one so far update = TRUE; pName->possibles = 1; } #if CC_LAZYTYPES else if ( !THAreTypesEqual( EVAL_MOD( pvM ), EVAL_TYP (pvM), pName->best.match ) && #else else if (EVAL_TYP (pvM) != pName->best.match && #endif current.exact == pName->best.exact) { // this function is a good as the best one. // this means the call is ambiguous pName->possibles++; } } else { if (pName->best.varargs != 0) { // both the current and the best functions have // varargs if (current.varargs < pName->best.varargs) { // this function uses fewer varargs which // makes it a better one update = TRUE; pName->possibles = 1; } else if (current.varargs == pName->best.varargs) { // this function uses the same number of varargs // pick the one with more exact matches if (current.exact > pName->best.exact) { update = TRUE; pName->possibles = 1; } #if CC_LAZYTYPES else if ( !THAreTypesEqual( EVAL_MOD( pvM ), EVAL_TYP (pvM), pName->best.match ) && #else else if (EVAL_TYP (pvM) != pName->best.match && #endif current.exact == pName->best.exact) { pName->possibles++; } } } } } if (update == TRUE) { if (fForce == FALSE) { // the current match is better for (pnT = (pnode_t)bArgList; NODE_OP (pnT) != OP_endofargs; pnT = (pnode_t)NODE_RCHILD (pnT)) { pa = (pargd_t)&(pnT->v[0]); pa->best = pa->current; } { //M00KLUDGE - hack for compiler DS != SS bug argcounters *pcurrent = ¤t; pName->best = *pcurrent; } } pName->best.match = EVAL_TYP (pvM); pName->best.attr = attr; pName->best.vtabind = vtabind; pName->best.hSym = pName->hSym; pName->best.CXTT = pName->CXTT; } } } CV_typ_t SkipModifiers( HMOD mod, CV_typ_t type ) { HTYPE hType; plfModifier pType; if (!CV_IS_PRIMITIVE (type)) { hType = THGetTypeFromIndex (mod, type); pType = (plfModifier)((&((TYPPTR)MHOmfLock (hType))->leaf)); while (pType->leaf == LF_MODIFIER) { type = pType->type; if (CV_IS_PRIMITIVE (type)) { break; } MHOmfUnLock (hType); hType = THGetTypeFromIndex (mod, type); pType = (plfModifier)((&((TYPPTR)MHOmfLock (hType))->leaf)); } } MHOmfUnLock (hType); return type; } /** MatchFunction - match a function against argument list * flag = MatchFunction (pName) * Entry pName = pointer to search status * BindingBP = TRUE if call is via ParseBP API entry * bArgList = based pointer to argument list * Exit pv = resolved address of method * Returns HR_... describing match result */ HR_t FASTCALL MatchFunction ( psearch_t pName ) { HR_t retval; CV_fldattr_t attr = {0}; CV_typ_t type; ADDR addr = {0}; bool_t dupfcn; if (bArgList == NULL) { // if there is no argument list, assume we are assigning to a // function pointer and take the first function found. Let the // user beware. return (HR_found); } // save the function address and type. Then if a subsequent match has // the same address and type (i.e., comdat code), we can ignore it. addr = EVAL_SYM (ST); type = EVAL_TYP (ST); // pop the entry that SearchSym has added to the evaluation stack // the best match will be pushed back on later pName->scope |= SCP_nomatchfn; PopStack (); MatchArgs (pName->pv, pName, attr, 0, FALSE); while ((retval = SearchSym (pName)) != HR_notfound) { DASSERT (retval != HR_end); dupfcn = FALSE; if (retval == HR_found) { // Mips publics for C functions are not decorated so don't // bother with type-check, just see if the addresses are the same if (memcmp (&addr, &EVAL_SYM (ST), sizeof (addr)) == 0) { dupfcn = TRUE; } PopStack (); if (dupfcn == FALSE) { MatchArgs (pName->pv, pName, attr, 0, FALSE); } } else { return (retval); } } pName->scope &= ~SCP_nomatchfn; // clear the symbol not found error from the recursive symbol search pExState->err_num = ERR_NONE; if (pName->best.match == 0) { pExState->err_num = ERR_ARGLIST; return (HR_error); } else if (pName->possibles > 1) { PushStack (pName->pv); pExState->err_num = ERR_AMBIGUOUS; EVAL_IS_AMBIGUOUS (ST) = TRUE; return (HR_ambiguous); } else if (pName->overloadCount > 1 && pName->best.implicit > 0) { // overloaded function that involves implicit casts pExState->err_num = ERR_AMBIGUOUS; return (HR_ambiguous); } else { pName->hSym = pName->best.hSym; pName->CXTT = pName->best.CXTT; if ((SymToNode (pName) == FALSE) || (PushStack (pName->pv) == FALSE)) { return (HR_notfound); } else { return (HR_found); } } } /** MatchMethod - match a method against argument list * flag = MatchMethod (pName, pSymCl) * Entry pName = pointer to search descriptor * pSymCl = pointer tp symbol class structure * select = selection masj * BindingBP = TRUE if call is via ParseBP API entry * if BindingBP is true, then only exact matches allowed * bArgList = based pointer to argument list * Exit pName->pv = resolved address of method * Returns MTH_found if a match was found or ambiguous references are allowed * MTH_error if error or ambiguity not allowed */ static bool_t setupMatchArgs( psearch_t pName, CV_fldattr_t attr, UOFFSET vtabind, bool_t fForce, CV_typ_t type, HMOD hMod ) { eval_t evalM; peval_t pvM = &evalM; // now compare the actual and formal argument lists for the function // pvM will be initialized to be a function node whose type index is // type. CLEAR_EVAL (pvM); EVAL_MOD (pvM) = hMod; if (SetNodeType (pvM, type) == FALSE) { // the type record for the method was not found DASSERT (FALSE); return FALSE; } MatchArgs (pvM, pName, attr, vtabind, fForce); return TRUE; } MTH_t MatchMethod ( psearch_t pName, psymclass_t pSymCl ) { HTYPE hMethod; pmlMethod pMethod; uint skip; CV_fldattr_t attr; CV_typ_t type; UOFFSET vtabind; bool_t Mmatch = 0; HDEP hQual; peval_t pvF; ulong count = pSymCl->possibles; peval_t pvB; HMOD hMod; bool_t fForce = FALSE; TYPPTR ptype; pvB = &pSymClass->symbase[pSymClass->CurIndex].Base; hMod = EVAL_MOD (pvB); pName->possibles = 0; pvF = &pSymCl->evalP; // we now walk the list of methods looking for an argument match // For now, we require an exact match except that we assume any // primitive type can be cast to any other primitive type. A cast from // pointer to derived to pointer to base is an implicit conversion if ((hMethod = THGetTypeFromIndex (hMod, pSymCl->mlist)) == NULL) { DASSERT (FALSE); return (MTH_error); } // set the number of methods overloaded on this name and the index into // the method list skip = 0; if (bArgList == NULL) { if (count == 1) { fForce = TRUE; } else { // there is not an argument list. We allow breakpoints if a single // method by that name exists. Otherwise, we require an argument // list pExState->err_num = ERR_NOARGLIST; return (MTH_error); } } ptype = (TYPPTR)MHOmfLock (hMethod); if (ptype->leaf == LF_METHODLIST) { MHOmfUnLock (hMethod); while (count-- > 0) { // lock the omf record, extract information for the current entry in // the method list and increment to field for next method pMethod = (pmlMethod)((&((TYPPTR)MHOmfLock (hMethod))->leaf) + 1); pMethod = (pmlMethod)((uchar *)pMethod + skip); attr = pMethod->attr; type = pMethod->index; skip += sizeof (mlMethod); if (fIntroducingVirtual(pMethod->attr.mprop)) { vtabind = pMethod->vbaseoff[0]; skip += sizeof(pMethod->vbaseoff[0]); } else { vtabind = 0; } MHOmfUnLock (hMethod); if (!setupMatchArgs(pName, attr, vtabind, fForce, type, hMod)) return (MTH_error); } } else { DASSERT(ptype->leaf == LF_MFUNCTION); DASSERT(count <= 1); MHOmfUnLock (hMethod); if (!setupMatchArgs(pName, pSymCl->access, FCN_VTABIND (pvF) , fForce, pSymCl->mlist, hMod)) return (MTH_error); } // since the name was found at this level, it hides all other methods // by the same name above it in the inheritance tree. Therefore we must // either have a match or an error because there is no match or two or // methods match after conversions are considered if (pName->best.match == 0) { pExState->err_num = ERR_ARGLIST; return (MTH_error); } else if (pName->possibles > 1) { pExState->err_num = ERR_AMBIGUOUS; EVAL_IS_AMBIGUOUS (pName->pv) = TRUE; return (MTH_error); } else if (pName->overloadCount > 1 && pName->best.implicit > 0) { // we have an overloaded method // in this case the EE requires exact matches only pExState->err_num = ERR_AMBIGUOUS; EVAL_IS_AMBIGUOUS (pName->pv) = TRUE; return (MTH_error); } else { // we have found a non-ambiguous match EVAL_MOD (pvF) = hMod; if (SetNodeType (pvF, pName->best.match) == FALSE) { return (MTH_error); } else { pSymCl->access.access = pName->best.attr.access; FCN_ATTR (pvF) = pName->best.attr; FCN_VTABIND (pvF) = pName->best.vtabind; FCN_VFPTYPE (pvF) = pSymCl->vfpType; if (NODE_OP (pName->bnOp) == OP_bscope) { // binary scoping switches off virtual function evaluation FCN_PROPERTY (pvF) = CV_MTvanilla; } if ((FCN_PROPERTY (pvF) == CV_MTvirtual) || (FCN_PROPERTY (pvF) == CV_MTintro)) { // do nothing. address will have to be found at evaluation } else { if (((hQual = GenQualName (pName, pSymClass)) == 0) || (SearchQualName (pName, pSymCl, hQual, TRUE) == FALSE)) { if (hQual != 0) { MemFree (hQual); } return (MTH_error); } MemFree (hQual); } return (MTH_found); } } } /** MoveSymCl - move symbol class structure * MoveSymCl (hSymCl); * Entry hSymCl = handle of symbol class structure * Exit *pSymClass = symbol class structure * Returns none */ void MoveSymCl ( HDEP hSymCl ) { psymclass_t pSymCl; ulong max; pSymCl = (psymclass_t) MemLock (hSymCl); DASSERT (pSymClass->MaxIndex >= pSymCl->CurIndex); max = pSymClass->MaxIndex; memmove (pSymClass, pSymCl, sizeof (symclass_t) + (pSymCl->CurIndex + 1) * sizeof (symbase_t)); pSymClass->MaxIndex = max; MemUnLock (hSymCl); MemFree (hSymCl); } /** PurgeAmbCl - purge ambiguous class structure list * PurgeAmbCl (pName) * Entry pName = pointer to symbol search structure * Exit pname->hAmb list freed * Returns none */ void PurgeAmbCl ( psearch_t pName ) { psymclass_t pAmbCl; HDEP hNext; while (pName->hAmbCl != 0) { pAmbCl = (psymclass_t) MHMemLock (pName->hAmbCl); hNext = pAmbCl->hNext; MHMemUnLock (pName->hAmbCl); pName->hAmbCl = hNext; } } /*** SetBase - set base value in pSymClass->symbase array * status = SetBase (pName, type, vbptr, vbpoff, thisadjust, attr, virtual) * Entry pName = pointer to struct describing search * type = type index of class * vbptr = type index of virtual base pointer * vbpoff = offset of virtual base pointer from address point * thisadjust = offset of base from previous class * thisadjust = virtual base index if virtual base * attr = field attribute mask * virtual = TRUE if virtual base * Exit new base class added to pSymClass * Returns enum describing search state */ SCN_t SetBase ( psearch_t pName, CV_typ_t type, CV_typ_t vbptr, UOFFSET vbpoff, UOFFSET thisadjust, CV_fldattr_t attr, bool_t fVirtual ) { peval_t pvB; // save offset of base from address point for this pointer adjustment pSymClass->symbase[pSymClass->CurIndex].thisadjust = thisadjust; pSymClass->symbase[pSymClass->CurIndex].vbptr = vbptr; pSymClass->symbase[pSymClass->CurIndex].vbpoff = vbpoff; pSymClass->symbase[pSymClass->CurIndex].attrBC = attr; pSymClass->symbase[pSymClass->CurIndex].fVirtual = fVirtual; pSymClass->symbase[pSymClass->CurIndex].clsmask = pName->clsmask; pvB = &pSymClass->symbase[pSymClass->CurIndex].Base; EVAL_MOD (pvB) = pName->hMod; EVAL_CXTT(pvB) = pName->CXTT; if (SetNodeType (pvB, type) == FALSE) { pExState->err_num = ERR_BADOMF; return (SCN_error); } return (SCN_found); } /*** SearchQualName - Search for a qualified method name * flag = SearchQualName (pName, pSymCl, hQual, fProc) * Entry pName = pointer to struct describing search * pSymCl = pointer to structure describing path to symbol * hQual = handle to symbol name * fProc = TRUE if proc symbol to be searched for * fProc = FALSE if data to be searched for * Exit pName updated to reflect search * Return enum describing search */ bool_t SearchQualName ( psearch_t pName, psymclass_t pSymCl, HDEP hQual, bool_t fProc ) { HDEP hTemp; psearch_t pTemp; uchar *pQual; ulong retval; if ((hTemp = MemAllocate (sizeof (search_t))) == 0) { pExState->err_num = ERR_NOMEMORY; return (FALSE); } pTemp = (psearch_t) MemLock (hTemp); *pTemp = *pName; pTemp->CXTT = *pCxt; // set pointer to symbol name pQual = (uchar *)MemLock (hQual); pTemp->sstr.lpName = pQual; pTemp->sstr.cb = (uchar)_tcslen ((char *)pQual); pTemp->state = SYM_init; if (fProc == TRUE) { pTemp->scope = SCP_module | SCP_global; pTemp->sstr.searchmask |= SSTR_proc; } else { pTemp->scope = SCP_module | SCP_global | SCP_lexical; // data members may not be overloaded, hence there is // no need for the type to qualify the name. Furthermore // there are cases where the symbol type doesn't match // the member type exactly (e.g. variable length arrays, // symbol has actual length and member has zero length) // hence this matching is suppressed for data items [rm] // pTemp->sstr.searchmask |= SSTR_data; } pTemp->initializer = INIT_qual; pTemp->typeOut = EVAL_TYP (&pSymCl->evalP); retval = SearchSym (pTemp); MemUnLock (hQual); if (retval != HR_found) { #ifdef NEVER /* CAVIAR #1081 */ if ((retval != HR_end) && (pTemp->FcnBP != 0)) { // there is another symbol with the same name but a different // type. Since this is set only when we are binding breakpoints, // let's go ahead and try it pTemp->state = SYM_init; pTemp->scope = SCP_module | SCP_global; pTemp->sstr.searchmask |= SSTR_proc; pTemp->typeOut = pTemp->FcnBP; retval = SearchSym (pTemp); } #endif if (retval != HR_found) { // the only way we can get here is if the method or data is declared // in the class but is not defined or is a noninstianted inline method. // therefore, we return a special error code if (ST == NULL) { // this is a hack to get around the case where the expression // bp {,foo.c, foo.exe}X::f // and the first function in the module foo is a method. // SearchSym ended up calling the class search routines // because the context is implicitly a class so class is // searched even though it shouldn't be. Any fix for this // causes problems and we are too close to release to find // a valid fix. The major result of this fix is that // some breakpoints will not get reset on entry. return (FALSE); } PushStack (ST); // if this is a missing static DATA member function then // best.match won't have anything in it at all... we'll need // to pick up what we want from typeOut which will have been // set by a previous non-qualified name search... [rm] if (pName->best.match == T_NOTYPE) { SetNodeType (ST, pName->typeOut); } else { SetNodeType (ST, pName->best.match); } if (EVAL_IS_FCN(ST)) { FCN_NOTPRESENT (ST) = TRUE; } else { // indicate missing static data member EVAL_HSYM (ST) = 0; pExState->state.fNotPresent = TRUE; } } } // pop off the stack entry that a successful search found. Move the // static data member flag first so that it will not be lost. EVAL_IS_STMEMBER (ST) = EVAL_IS_STMEMBER (&pSymCl->evalP); EVAL_ACCESS (ST) = (uchar)(pSymCl->access.access); pSymCl->evalP = *ST; MemUnLock (hTemp); MemFree (hTemp); return (PopStack ()); } /** SymAmbToList - add ambiguous symbol to list * status = SymAmbToList (pName) * Entry pName = pointer to list describing search * Exit ambiguous symbol added to list pointed to by pTMList * pTMLbp * pName reset to continue breakpoint search * Returns HR_... describing state */ HR_t SymAmbToList ( psearch_t pName ) { HDEP hSearch; psearch_t pSearch; HR_t retval; HDEP hevalT; PopStack (); if (pExState->ambiguous == 0) { // this is the first breakpoint symbol found. // indicate the only node in the tree that is // allowed ambiguity and initialize list of // symbols for later back patching into duplicated // expression trees. We save the initial search packet // so that the first symbol will be set into the breakpoint // list. pNameFirst = pName; pExState->ambiguous = pName->bn; if ((hSearch = MemAllocate (sizeof (search_t))) == 0) { pExState->err_num = ERR_NOMEMORY; return (HR_error); } if ((hevalT = MemAllocate (sizeof (eval_t))) == 0) { MemFree (hSearch); pExState->err_num = ERR_NOMEMORY; return (HR_error); } pSearch = (psearch_t) MemLock (hSearch); *pSearch = *pName; pSearch->pv = (peval_t)MemLock (hevalT); SHGoToParent (&pName->CXTT, &pSearch->CXTT); // clear the newly allocated pv memset ( pSearch->pv, 0, sizeof (eval_t) ); retval = SearchSym (pSearch); PushStack (pName->pv); MemUnLock (hSearch); MemFree (hSearch); MemUnLock (hevalT); MemFree (hevalT); if (retval == HR_end) { retval = HR_found; } return (retval); } else if (pExState->ambiguous != pName->bn) { // there has already been a ambiguous symbol that is // not at this node in the tree pExState->err_num = ERR_BPAMBIGUOUS; return (HR_error); } else { if (CheckDupAmb (pName) == FALSE) { // the function is not already in the ambiguity list if (AmbToList (pName) == FALSE) { return (HR_error); } } // reset search to allow more symbols pName->possibles = 0; return (SearchSym (pName)); } } /** CheckDupAmb - check for duplicate ambiguity entry * fSuccess = CheckDupAmb (pName) * Entry pName = pointer to list describing search * Exit none * Returns TRUE if duplicate symbol found * FALSE if duplicate symbol not found */ bool_t CheckDupAmb ( psearch_t pName ) { psearch_t pN; ulong i; bool_t fdup = FALSE; if ((EVAL_TYP (pNameFirst->pv) == EVAL_TYP (pName->pv)) && (memcmp ((void *)&EVAL_SYM (pNameFirst->pv), (void *)&EVAL_SYM (pName->pv), sizeof (ADDR)) == 0)) { return (TRUE); } for (i = 1; i < iBPatch; i++) { pN = (psearch_t) MemLock (pTMList[i]); if (pN->typeOut == EVAL_TYP (pName->pv) && (memcmp ((void *)&pN->addr, (void *)&EVAL_SYM (pName->pv), sizeof (ADDR)) == 0)) { fdup = TRUE; } MemUnLock (pTMList[i]); if (fdup == TRUE) { break; } } return (fdup); } /** SymToNode - store symbol information in evaluation node * fSuccess = SymToNode (hName) * Entry pName = pointer to search state * Exit type information and address data stored in value * if the symbol is a typedef record, then the evaluation * state will be set to EV_type. Otherwise, it will be set * to EV_lvalue. * Returns TRUE if variable was accessible * FALSE if error */ bool_t SymToNode ( psearch_t pName ) { CV_typ_t typ; HSYM hSym; peval_t pv = pName->pv; PCXT pCXT = &pName->CXTT; SYMPTR pSym; ulong cmpThis = 1; MEMINFO mi; if ((hSym = pName->hSym) == NULL) { // this symbol is found as a class member which means it does // not have a symbol. DASSERT (pName->typeOut != T_NOTYPE); return (SetNodeType (pv, pName->typeOut)); } EVAL_STATE (pv) = EV_lvalue; EVAL_MOD (pv) = SHHMODFrompCXT (pCXT); CLEAR_EVAL_FLAGS (pv); EVAL_SYM_EMI (pv) = pCXT->addr.emi; switch((pSym = (SYMPTR) MHOmfLock (hSym))->rectyp) { case S_REGISTER: EVAL_IS_REG (pv) = TRUE; EVAL_REG (pv) = ((REGPTR)pSym)->reg; typ = ((REGPTR)pSym)->typind; cmpThis = _tcsncmp ( (char *) &((REGPTR)pSym)->name[0], (char *) &OpName[0], ((REGPTR)pSym)->name[0] + 1); break; case S_CONSTANT: if (!DebLoadConst (pv, (CONSTPTR)pSym, hSym)) { MHOmfUnLock (hSym); return (FALSE); } EVAL_STATE (pv) = EV_constant; typ = EVAL_TYP (pv); break; case S_UDT: typ = ((UDTPTR)pSym)->typind; EVAL_STATE (pv) = EV_type; break; case S_BLOCK16: EVAL_SYM_SEG (pv) = ((BLOCKPTR16)pSym)->seg; EVAL_SYM_OFF (pv) = ((BLOCKPTR16)pSym)->off; typ = T_NOTYPE; ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; NOTTESTED (FALSE); // not tested break; case S_LPROC16: case S_GPROC16: ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; if ((typ = ((PROCPTR16)pSym)->typind) == T_NOTYPE) { // this is a hack to allow breakpoints on untyped symbols typ = T_PFVOID; EVAL_SYM_OFF (pv) = ((PROCPTR16)pSym)->off; EVAL_SYM_SEG (pv) = ((PROCPTR16)pSym)->seg; EVAL_PTR (pv) = EVAL_SYM (pv); EVAL_STATE (pv) = EV_rvalue; } else { EVAL_SYM (pv) = *SHpADDRFrompCXT (pCXT); EVAL_SYM_SEG (pv) = ((PROCPTR16)pSym)->seg; EVAL_SYM_OFF (pv) = ((PROCPTR16)pSym)->off; ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; } break; case S_LABEL16: EVAL_IS_LABEL (pv) = TRUE; EVAL_SYM_OFF (pv) = ((LABELPTR16)pSym)->off; EVAL_SYM_SEG (pv) = ((LABELPTR16)pSym)->seg; ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; EVAL_PTR (pv) = EVAL_SYM (pv); EVAL_STATE (pv) = EV_rvalue; typ = T_PFVOID; break; case S_BPREL16: EVAL_IS_BPREL (pv) = TRUE; EVAL_SYM_OFF (pv) = ((BPRELPTR16)pSym)->off; EVAL_SYM_SEG (pv) = 0; ADDR_IS_LI (EVAL_SYM (pv)) = FALSE; typ = ((BPRELPTR16)pSym)->typind; pExState->state.bprel = TRUE; cmpThis = _tcsncmp ( (char *) &((BPRELPTR16)pSym)->name[0], (char *) &OpName[0], ((BPRELPTR16)pSym)->name[0] + 1); break; case S_LDATA16: pExState->state.fLData = TRUE; EVAL_SYM_OFF (pv) = ((DATAPTR16)pSym)->off; EVAL_SYM_SEG (pv) = ((DATAPTR16)pSym)->seg; typ = ((DATAPTR16)pSym)->typind; ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; break; case S_GDATA16: pExState->state.fGData = TRUE; EVAL_SYM_OFF (pv) = ((DATAPTR16)pSym)->off; EVAL_SYM_SEG (pv) = ((DATAPTR16)pSym)->seg; typ = ((DATAPTR16)pSym)->typind; ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; break; case S_PUB16: EVAL_SYM_OFF (pv) = ((DATAPTR16)pSym)->off; EVAL_SYM_SEG (pv) = ((DATAPTR16)pSym)->seg; EVAL_STATE (pv) = EV_rvalue; if ((typ = ((DATAPTR16)pSym)->typind) == T_NOTYPE) { // this is a hack to allow breakpoints on untyped symbold typ = T_PFVOID; } ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; EVAL_PTR (pv) = EVAL_SYM (pv); break; case S_BLOCK32: EVAL_SYM_SEG (pv) = ((BLOCKPTR32)pSym)->seg; EVAL_SYM_OFF (pv) = ((BLOCKPTR32)pSym)->off; typ = T_NOTYPE; ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; ADDRLIN32(EVAL_SYM (pv)); break; case S_LPROC32: case S_GPROC32: ADDRLIN32(EVAL_SYM (pv)); ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; if ((typ = ((PROCPTR32)pSym)->typind) == T_NOTYPE) { // this is a hack to allow breakpoints on untyped symbols typ = T_32PVOID; EVAL_SYM_OFF (pv) = ((PROCPTR32)pSym)->off; EVAL_SYM_SEG (pv) = ((PROCPTR32)pSym)->seg; EVAL_PTR (pv) = EVAL_SYM (pv); EVAL_STATE (pv) = EV_rvalue; } else { EVAL_SYM (pv) = *SHpADDRFrompCXT (pCXT); EVAL_SYM_SEG (pv) = ((PROCPTR32)pSym)->seg; EVAL_SYM_OFF (pv) = ((PROCPTR32)pSym)->off; } break; case S_LPROCMIPS: case S_GPROCMIPS: ADDRLIN32(EVAL_SYM (pv)); ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; if ((typ = ((PROCPTRMIPS)pSym)->typind) == T_NOTYPE) { // this is a hack to allow breakpoints on untyped symbols typ = T_32PVOID; EVAL_SYM_OFF (pv) = ((PROCPTRMIPS)pSym)->off; EVAL_SYM_SEG (pv) = ((PROCPTRMIPS)pSym)->seg; EVAL_PTR (pv) = EVAL_SYM (pv); EVAL_STATE (pv) = EV_rvalue; } else { EVAL_SYM (pv) = *SHpADDRFrompCXT (pCXT); EVAL_SYM_SEG (pv) = ((PROCPTRMIPS)pSym)->seg; EVAL_SYM_OFF (pv) = ((PROCPTRMIPS)pSym)->off; } break; case S_REGREL32: EVAL_IS_REGREL (pv) = TRUE; EVAL_SYM_OFF (pv) = ((LPREGREL32)pSym)->off; EVAL_SYM_SEG (pv) = 0; EVAL_REGREL (pv) = ((LPREGREL32)pSym)->reg; typ = ((LPREGREL32)pSym)->typind; ADDRLIN32 (EVAL_SYM (pv)); pExState->state.regrel = TRUE; cmpThis = _tcsncmp ( (char *) &((LPREGREL32)pSym)->name[0], (char *) &OpName[0], ((LPREGREL32)pSym)->name[0] + 1); break; case S_LABEL32: EVAL_IS_LABEL (pv) = TRUE; EVAL_SYM_OFF (pv) = ((LABELPTR32)pSym)->off; EVAL_SYM_SEG (pv) = ((LABELPTR32)pSym)->seg; ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; ADDRLIN32(EVAL_SYM (pv)); EVAL_PTR (pv) = EVAL_SYM (pv); EVAL_STATE (pv) = EV_rvalue; typ = T_32PVOID; break; case S_BPREL32: EVAL_IS_BPREL (pv) = TRUE; ADDRLIN32(EVAL_SYM (pv)); EVAL_SYM_OFF (pv) = ((BPRELPTR32)pSym)->off; EVAL_SYM_SEG (pv) = 0; typ = ((BPRELPTR32)pSym)->typind; ADDR_IS_LI (EVAL_SYM (pv)) = FALSE; pExState->state.bprel = TRUE; cmpThis = _tcsncmp ( (char *) &((BPRELPTR32)pSym)->name[0], (char *) &OpName[0], ((BPRELPTR32)pSym)->name[0] + 1); break; case S_LDATA32: case S_LTHREAD32: pExState->state.fLData = TRUE; EVAL_SYM_OFF (pv) = ((DATAPTR32)pSym)->off; EVAL_SYM_SEG (pv) = ((DATAPTR32)pSym)->seg; typ = ((DATAPTR32)pSym)->typind; ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; ADDRLIN32(EVAL_SYM (pv)); break; case S_GDATA32: case S_GTHREAD32: pExState->state.fGData = TRUE; EVAL_SYM_OFF (pv) = ((DATAPTR32)pSym)->off; EVAL_SYM_SEG (pv) = ((DATAPTR32)pSym)->seg; typ = ((DATAPTR32)pSym)->typind; ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; ADDRLIN32(EVAL_SYM (pv)); break; case S_PUB32: #if 0 /* ** This is a hack so we can set breakpoints on publics. This ** allows EEInfoFromTM() to see that it needs to use the AI ** field to get the address to break at. Otherwise it would ** just use the value and not see that it needed to be fixed up */ EVAL_IS_LABEL (pv) = TRUE; EVAL_SYM_OFF (pv) = ((DATAPTR32)pSym)->off; EVAL_SYM_SEG (pv) = ((DATAPTR32)pSym)->seg; ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; ADDRLIN32(EVAL_SYM (pv)); EVAL_PTR (pv) = EVAL_SYM (pv); EVAL_STATE (pv) = EV_rvalue; typ = T_32PVOID; break; #endif EVAL_SYM_OFF (pv) = ((DATAPTR32)pSym)->off; EVAL_SYM_SEG (pv) = ((DATAPTR32)pSym)->seg; ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; ADDRLIN32(EVAL_SYM (pv)); EVAL_PTR (pv) = EVAL_SYM (pv); EVAL_STATE (pv) = EV_lvalue; if ((typ = ((DATAPTR32)pSym)->typind) == T_NOTYPE) { #if 0 if (FNtsdEvalType) { FNtsdEvalType = FALSE; evalstate = EV_rvalue; typ = T_32PULONG; } else { #endif typ = T_UINT4; #if 0 evalstate = EV_lvalue; } #endif // this is a hack to allow breakpoints on untyped symbols mi.addr = EVAL_SYM(pv); SYGetMemInfo(&mi); if ((mi.dwState & MEM_COMMIT) && (mi.dwProtect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) ) { typ = T_32PUCHAR; EVAL_STATE (pv) = EV_rvalue; } else { #if 0 // this gives windbg the "look & feel" of ntsd/kd // if the user does a "dd foo" and there are only // coff publics then the answer will be the same // as ntsd/kd EVAL_STATE (pv) = evalstate; #endif EVAL_STATE (pv) = EV_lvalue; } } break; case S_REGIA64: EVAL_IS_REGIA64 (pv) = TRUE; EVAL_REG (pv) = ((REGPTR)pSym)->reg; typ = ((REGPTRIA64)pSym)->typind; cmpThis = _ftcsncmp ( (char FAR *) &((REGPTRIA64)pSym)->name[0], (char FAR *) &OpName[0], ((REGPTRIA64)pSym)->name[0] + 1); break; case S_LPROCIA64: case S_GPROCIA64: ADDRLIN32(EVAL_SYM (pv)); ADDR_IS_LI (EVAL_SYM (pv)) = TRUE; if ((typ = ((PROCPTRIA64)pSym)->typind) == T_NOTYPE) { // this is a hack to allow breakpoints on untyped symbols typ = T_32PUCHAR; EVAL_SYM_OFF (pv) = ((PROCPTRIA64)pSym)->off; EVAL_SYM_SEG (pv) = ((PROCPTRIA64)pSym)->seg; EVAL_PTR (pv) = EVAL_SYM (pv); EVAL_STATE (pv) = EV_rvalue; } else { EVAL_SYM (pv) = *SHpADDRFrompCXT (pCXT); EVAL_SYM_SEG (pv) = ((PROCPTRIA64)pSym)->seg; EVAL_SYM_OFF (pv) = ((PROCPTRIA64)pSym)->off; } break; case S_REGRELIA64: EVAL_IS_REGRELIA64 (pv) = TRUE; EVAL_SYM_OFF (pv) = ((LPREGRELIA64)pSym)->off; EVAL_SYM_SEG (pv) = 0; EVAL_REGREL (pv) = ((LPREGRELIA64)pSym)->reg; typ = ((LPREGRELIA64)pSym)->typind; ADDRLIN32 (EVAL_SYM (pv)); pExState->state.regrel = TRUE; cmpThis = _ftcsncmp ( (char FAR *) &((LPREGRELIA64)pSym)->name[0], (char FAR *) &OpName[0], ((LPREGRELIA64)pSym)->name[0] + 1); break; default: // these OMF records are no longer supported MHOmfUnLock (hSym); pExState->err_num = ERR_BADOMF; return (FALSE); } MHOmfUnLock (hSym); if (SetNodeType (pv, typ) == FALSE) { return (FALSE); } else if (ClassImp != T_NOTYPE) { if (EVAL_IS_PTR (pv) && memcmp (pName->sstr.lpName, &OpName[0] + 1, pName->sstr.cb) == 0) { PTR_THISADJUST (pv) = ClassThisAdjust; } else if (cmpThis == 0) { PTR_THISADJUST (pv) = ClassThisAdjust; } } return (TRUE); } #define VALIDMPC601 0x01 #define VALIDMPC603 0x02 #define VALIDMPC604 0x04 #define VALIDMPC620 0x08 #define VALIDMPC6xx VALIDMPC601 | VALIDMPC603 | VALIDMPC604 | VALIDMPC620 struct hreg_ppc { char name[8]; ulong index; ulong valid; CV_typ_t type; } const hreg_list_ppc[] = { /* ** PowerPC General Registers ( User Level ) */ { "\004""GPR0", CV_PPC_GPR0, VALIDMPC6xx, T_ULONG }, { "\002""R0", CV_PPC_GPR0, VALIDMPC6xx, T_ULONG }, { "\004""GPR1", CV_PPC_GPR1, VALIDMPC6xx, T_ULONG }, { "\002""R1", CV_PPC_GPR1, VALIDMPC6xx, T_ULONG }, { "\002""SP", CV_PPC_GPR1, VALIDMPC6xx, T_ULONG }, // GPR1 Alias { "\004""GPR2", CV_PPC_GPR2, VALIDMPC6xx, T_ULONG }, { "\002""R2", CV_PPC_GPR2, VALIDMPC6xx, T_ULONG }, { "\004""RTOC", CV_PPC_GPR2, VALIDMPC6xx, T_ULONG }, // GPR2 Alias { "\004""GPR3", CV_PPC_GPR3, VALIDMPC6xx, T_ULONG }, { "\002""R3", CV_PPC_GPR3, VALIDMPC6xx, T_ULONG }, { "\004""GPR4", CV_PPC_GPR4, VALIDMPC6xx, T_ULONG }, { "\002""R4", CV_PPC_GPR4, VALIDMPC6xx, T_ULONG }, { "\004""GPR5", CV_PPC_GPR5, VALIDMPC6xx, T_ULONG }, { "\002""R5", CV_PPC_GPR5, VALIDMPC6xx, T_ULONG }, { "\004""GPR6", CV_PPC_GPR6, VALIDMPC6xx, T_ULONG }, { "\002""R6", CV_PPC_GPR6, VALIDMPC6xx, T_ULONG }, { "\004""GPR7", CV_PPC_GPR7, VALIDMPC6xx, T_ULONG }, { "\002""R7", CV_PPC_GPR7, VALIDMPC6xx, T_ULONG }, { "\004""GPR8", CV_PPC_GPR8, VALIDMPC6xx, T_ULONG }, { "\002""R8", CV_PPC_GPR8, VALIDMPC6xx, T_ULONG }, { "\004""GPR9", CV_PPC_GPR9, VALIDMPC6xx, T_ULONG }, { "\002""R9", CV_PPC_GPR9, VALIDMPC6xx, T_ULONG }, { "\005""GPR10", CV_PPC_GPR10, VALIDMPC6xx, T_ULONG }, { "\003""R10", CV_PPC_GPR10, VALIDMPC6xx, T_ULONG }, { "\005""GPR11", CV_PPC_GPR11, VALIDMPC6xx, T_ULONG }, { "\003""R11", CV_PPC_GPR11, VALIDMPC6xx, T_ULONG }, { "\005""GPR12", CV_PPC_GPR12, VALIDMPC6xx, T_ULONG }, { "\003""R12", CV_PPC_GPR12, VALIDMPC6xx, T_ULONG }, { "\005""GPR13", CV_PPC_GPR13, VALIDMPC6xx, T_ULONG }, { "\003""R13", CV_PPC_GPR13, VALIDMPC6xx, T_ULONG }, { "\005""GPR14", CV_PPC_GPR14, VALIDMPC6xx, T_ULONG }, { "\003""R14", CV_PPC_GPR14, VALIDMPC6xx, T_ULONG }, { "\005""GPR15", CV_PPC_GPR15, VALIDMPC6xx, T_ULONG }, { "\003""R15", CV_PPC_GPR15, VALIDMPC6xx, T_ULONG }, { "\005""GPR16", CV_PPC_GPR16, VALIDMPC6xx, T_ULONG }, { "\003""R16", CV_PPC_GPR16, VALIDMPC6xx, T_ULONG }, { "\005""GPR17", CV_PPC_GPR17, VALIDMPC6xx, T_ULONG }, { "\003""R17", CV_PPC_GPR17, VALIDMPC6xx, T_ULONG }, { "\005""GPR18", CV_PPC_GPR18, VALIDMPC6xx, T_ULONG }, { "\003""R18", CV_PPC_GPR18, VALIDMPC6xx, T_ULONG }, { "\005""GPR19", CV_PPC_GPR19, VALIDMPC6xx, T_ULONG }, { "\003""R19", CV_PPC_GPR19, VALIDMPC6xx, T_ULONG }, { "\005""GPR20", CV_PPC_GPR20, VALIDMPC6xx, T_ULONG }, { "\003""R20", CV_PPC_GPR20, VALIDMPC6xx, T_ULONG }, { "\005""GPR21", CV_PPC_GPR21, VALIDMPC6xx, T_ULONG }, { "\003""R21", CV_PPC_GPR21, VALIDMPC6xx, T_ULONG }, { "\005""GPR22", CV_PPC_GPR22, VALIDMPC6xx, T_ULONG }, { "\003""R22", CV_PPC_GPR22, VALIDMPC6xx, T_ULONG }, { "\005""GPR23", CV_PPC_GPR23, VALIDMPC6xx, T_ULONG }, { "\003""R23", CV_PPC_GPR23, VALIDMPC6xx, T_ULONG }, { "\005""GPR24", CV_PPC_GPR24, VALIDMPC6xx, T_ULONG }, { "\003""R24", CV_PPC_GPR24, VALIDMPC6xx, T_ULONG }, { "\005""GPR25", CV_PPC_GPR25, VALIDMPC6xx, T_ULONG }, { "\003""R25", CV_PPC_GPR25, VALIDMPC6xx, T_ULONG }, { "\005""GPR26", CV_PPC_GPR26, VALIDMPC6xx, T_ULONG }, { "\003""R26", CV_PPC_GPR26, VALIDMPC6xx, T_ULONG }, { "\005""GPR27", CV_PPC_GPR27, VALIDMPC6xx, T_ULONG }, { "\003""R27", CV_PPC_GPR27, VALIDMPC6xx, T_ULONG }, { "\005""GPR28", CV_PPC_GPR28, VALIDMPC6xx, T_ULONG }, { "\003""R28", CV_PPC_GPR28, VALIDMPC6xx, T_ULONG }, { "\005""GPR29", CV_PPC_GPR29, VALIDMPC6xx, T_ULONG }, { "\003""R29", CV_PPC_GPR29, VALIDMPC6xx, T_ULONG }, { "\005""GPR30", CV_PPC_GPR30, VALIDMPC6xx, T_ULONG }, { "\003""R30", CV_PPC_GPR30, VALIDMPC6xx, T_ULONG }, { "\005""GPR31", CV_PPC_GPR31, VALIDMPC6xx, T_ULONG }, { "\003""R31", CV_PPC_GPR31, VALIDMPC6xx, T_ULONG }, /* ** PowerPC Condition Register ( User Level ) */ { "\002""CR", CV_PPC_CR, VALIDMPC6xx, T_ULONG }, { "\003""CR0", CV_PPC_CR0, VALIDMPC6xx, T_ULONG }, { "\003""CR1", CV_PPC_CR1, VALIDMPC6xx, T_ULONG }, { "\003""CR2", CV_PPC_CR2, VALIDMPC6xx, T_ULONG }, { "\003""CR3", CV_PPC_CR3, VALIDMPC6xx, T_ULONG }, { "\003""CR4", CV_PPC_CR4, VALIDMPC6xx, T_ULONG }, { "\003""CR5", CV_PPC_CR5, VALIDMPC6xx, T_ULONG }, { "\003""CR6", CV_PPC_CR6, VALIDMPC6xx, T_ULONG }, { "\003""CR7", CV_PPC_CR7, VALIDMPC6xx, T_ULONG }, /* ** PowerPC Floating Point Registers ( User Level ) ** The floating point registers aren't really 80 bytes however the ** shell expects that they are so we say they are and thusly the em ** turns the 64bit doubles into 80bit long doubles before returning them */ { "\004""FPR0", CV_PPC_FPR0, VALIDMPC6xx, T_REAL80 }, { "\003""FP0", CV_PPC_FPR0, VALIDMPC6xx, T_REAL80 }, { "\004""FPR1", CV_PPC_FPR1, VALIDMPC6xx, T_REAL80 }, { "\003""FP1", CV_PPC_FPR1, VALIDMPC6xx, T_REAL80 }, { "\004""FPR2", CV_PPC_FPR2, VALIDMPC6xx, T_REAL80 }, { "\003""FP2", CV_PPC_FPR2, VALIDMPC6xx, T_REAL80 }, { "\004""FPR3", CV_PPC_FPR3, VALIDMPC6xx, T_REAL80 }, { "\003""FP3", CV_PPC_FPR3, VALIDMPC6xx, T_REAL80 }, { "\004""FPR4", CV_PPC_FPR4, VALIDMPC6xx, T_REAL80 }, { "\003""FP4", CV_PPC_FPR4, VALIDMPC6xx, T_REAL80 }, { "\004""FPR5", CV_PPC_FPR5, VALIDMPC6xx, T_REAL80 }, { "\003""FP5", CV_PPC_FPR5, VALIDMPC6xx, T_REAL80 }, { "\004""FPR6", CV_PPC_FPR6, VALIDMPC6xx, T_REAL80 }, { "\003""FP6", CV_PPC_FPR6, VALIDMPC6xx, T_REAL80 }, { "\004""FPR7", CV_PPC_FPR7, VALIDMPC6xx, T_REAL80 }, { "\003""FP7", CV_PPC_FPR7, VALIDMPC6xx, T_REAL80 }, { "\004""FPR8", CV_PPC_FPR8, VALIDMPC6xx, T_REAL80 }, { "\003""FP8", CV_PPC_FPR8, VALIDMPC6xx, T_REAL80 }, { "\004""FPR9", CV_PPC_FPR9, VALIDMPC6xx, T_REAL80 }, { "\003""FP9", CV_PPC_FPR9, VALIDMPC6xx, T_REAL80 }, { "\005""FPR10", CV_PPC_FPR10, VALIDMPC6xx, T_REAL80 }, { "\004""FP10", CV_PPC_FPR10, VALIDMPC6xx, T_REAL80 }, { "\005""FPR11", CV_PPC_FPR11, VALIDMPC6xx, T_REAL80 }, { "\004""FP11", CV_PPC_FPR11, VALIDMPC6xx, T_REAL80 }, { "\005""FPR12", CV_PPC_FPR12, VALIDMPC6xx, T_REAL80 }, { "\004""FP12", CV_PPC_FPR12, VALIDMPC6xx, T_REAL80 }, { "\005""FPR13", CV_PPC_FPR13, VALIDMPC6xx, T_REAL80 }, { "\004""FP13", CV_PPC_FPR13, VALIDMPC6xx, T_REAL80 }, { "\005""FPR14", CV_PPC_FPR14, VALIDMPC6xx, T_REAL80 }, { "\004""FP14", CV_PPC_FPR14, VALIDMPC6xx, T_REAL80 }, { "\005""FPR15", CV_PPC_FPR15, VALIDMPC6xx, T_REAL80 }, { "\004""FP15", CV_PPC_FPR15, VALIDMPC6xx, T_REAL80 }, { "\005""FPR16", CV_PPC_FPR16, VALIDMPC6xx, T_REAL80 }, { "\004""FP16", CV_PPC_FPR16, VALIDMPC6xx, T_REAL80 }, { "\005""FPR17", CV_PPC_FPR17, VALIDMPC6xx, T_REAL80 }, { "\004""FP17", CV_PPC_FPR17, VALIDMPC6xx, T_REAL80 }, { "\005""FPR18", CV_PPC_FPR18, VALIDMPC6xx, T_REAL80 }, { "\004""FP18", CV_PPC_FPR18, VALIDMPC6xx, T_REAL80 }, { "\005""FPR19", CV_PPC_FPR19, VALIDMPC6xx, T_REAL80 }, { "\004""FP19", CV_PPC_FPR19, VALIDMPC6xx, T_REAL80 }, { "\005""FPR20", CV_PPC_FPR20, VALIDMPC6xx, T_REAL80 }, { "\004""FP20", CV_PPC_FPR20, VALIDMPC6xx, T_REAL80 }, { "\005""FPR21", CV_PPC_FPR21, VALIDMPC6xx, T_REAL80 }, { "\004""FP21", CV_PPC_FPR21, VALIDMPC6xx, T_REAL80 }, { "\005""FPR22", CV_PPC_FPR22, VALIDMPC6xx, T_REAL80 }, { "\004""FP22", CV_PPC_FPR22, VALIDMPC6xx, T_REAL80 }, { "\005""FPR23", CV_PPC_FPR23, VALIDMPC6xx, T_REAL80 }, { "\004""FP23", CV_PPC_FPR23, VALIDMPC6xx, T_REAL80 }, { "\005""FPR24", CV_PPC_FPR24, VALIDMPC6xx, T_REAL80 }, { "\004""FP24", CV_PPC_FPR24, VALIDMPC6xx, T_REAL80 }, { "\005""FPR25", CV_PPC_FPR25, VALIDMPC6xx, T_REAL80 }, { "\004""FP25", CV_PPC_FPR25, VALIDMPC6xx, T_REAL80 }, { "\005""FPR26", CV_PPC_FPR26, VALIDMPC6xx, T_REAL80 }, { "\004""FP26", CV_PPC_FPR26, VALIDMPC6xx, T_REAL80 }, { "\005""FPR27", CV_PPC_FPR27, VALIDMPC6xx, T_REAL80 }, { "\004""FP27", CV_PPC_FPR27, VALIDMPC6xx, T_REAL80 }, { "\005""FPR28", CV_PPC_FPR28, VALIDMPC6xx, T_REAL80 }, { "\004""FP28", CV_PPC_FPR28, VALIDMPC6xx, T_REAL80 }, { "\005""FPR29", CV_PPC_FPR29, VALIDMPC6xx, T_REAL80 }, { "\004""FP29", CV_PPC_FPR29, VALIDMPC6xx, T_REAL80 }, { "\005""FPR30", CV_PPC_FPR30, VALIDMPC6xx, T_REAL80 }, { "\004""FP30", CV_PPC_FPR30, VALIDMPC6xx, T_REAL80 }, { "\005""FPR31", CV_PPC_FPR31, VALIDMPC6xx, T_REAL80 }, { "\004""FP31", CV_PPC_FPR31, VALIDMPC6xx, T_REAL80 }, /* ** PowerPC Floating Point Status and Control Register ( User Level ) */ { "\005""FPSCR", CV_PPC_FPSCR, VALIDMPC6xx, T_ULONG }, /* ** PowerPC Machine State Register ( Supervisor Level ) */ { "\003""MSR", CV_PPC_MSR, VALIDMPC6xx, T_ULONG }, /* ** PowerPC Segment Registers ( Supervisor Level ) */ { "\003""SR0", CV_PPC_SR0, VALIDMPC6xx, T_ULONG }, { "\003""SR1", CV_PPC_SR1, VALIDMPC6xx, T_ULONG }, { "\003""SR2", CV_PPC_SR2, VALIDMPC6xx, T_ULONG }, { "\003""SR3", CV_PPC_SR3, VALIDMPC6xx, T_ULONG }, { "\003""SR4", CV_PPC_SR4, VALIDMPC6xx, T_ULONG }, { "\003""SR5", CV_PPC_SR5, VALIDMPC6xx, T_ULONG }, { "\003""SR6", CV_PPC_SR6, VALIDMPC6xx, T_ULONG }, { "\003""SR7", CV_PPC_SR7, VALIDMPC6xx, T_ULONG }, { "\003""SR8", CV_PPC_SR8, VALIDMPC6xx, T_ULONG }, { "\003""SR9", CV_PPC_SR9, VALIDMPC6xx, T_ULONG }, { "\003""SR10", CV_PPC_SR10, VALIDMPC6xx, T_ULONG }, { "\003""SR11", CV_PPC_SR11, VALIDMPC6xx, T_ULONG }, { "\003""SR12", CV_PPC_SR12, VALIDMPC6xx, T_ULONG }, { "\003""SR13", CV_PPC_SR13, VALIDMPC6xx, T_ULONG }, { "\003""SR14", CV_PPC_SR14, VALIDMPC6xx, T_ULONG }, { "\003""SR15", CV_PPC_SR15, VALIDMPC6xx, T_ULONG }, /* ** For all of the special purpose registers add 100 to the SPR# that the ** Motorola/IBM documentation gives with the exception of any imaginary ** registers. */ /* ** PowerPC Special Purpose Registers ( User Level ) */ { "\002""PC", CV_PPC_PC, VALIDMPC6xx, T_ULONG }, // PC (imaginary register) { "\002""MQ", CV_PPC_MQ, VALIDMPC601, T_ULONG }, // MPC601 { "\003""XER", CV_PPC_XER, VALIDMPC6xx, T_ULONG }, { "\004""RTCU", CV_PPC_RTCU, VALIDMPC601, T_ULONG }, // MPC601 { "\004""RTCL", CV_PPC_RTCL, VALIDMPC601, T_ULONG }, // MPC601 { "\002""LR", CV_PPC_LR, VALIDMPC6xx, T_ULONG }, { "\003""CTR", CV_PPC_CTR, VALIDMPC6xx, T_ULONG }, /* ** PowerPC Special Purpose Registers ( Supervisor Level ) */ { "\005""DSISR", CV_PPC_DSISR, VALIDMPC6xx, T_ULONG }, { "\003""DAR", CV_PPC_DAR, VALIDMPC6xx, T_ULONG }, { "\003""DEC", CV_PPC_DEC, VALIDMPC6xx, T_ULONG }, { "\004""SDR1", CV_PPC_SDR1, VALIDMPC6xx, T_ULONG }, { "\004""SRR0", CV_PPC_SRR0, VALIDMPC6xx, T_ULONG }, { "\004""SRR1", CV_PPC_SRR1, VALIDMPC6xx, T_ULONG }, { "\005""SPRG0", CV_PPC_SPRG0, VALIDMPC6xx, T_ULONG }, { "\005""SPRG1", CV_PPC_SPRG1, VALIDMPC6xx, T_ULONG }, { "\005""SPRG2", CV_PPC_SPRG2, VALIDMPC6xx, T_ULONG }, { "\005""SPRG3", CV_PPC_SPRG3, VALIDMPC6xx, T_ULONG }, { "\003""ASR", CV_PPC_ASR, VALIDMPC6xx, T_ULONG }, // 64-bit implementations only { "\003""EAR", CV_PPC_EAR, VALIDMPC6xx, T_ULONG }, { "\003""PVR", CV_PPC_PVR, VALIDMPC6xx, T_ULONG }, { "\005""BAT0U", CV_PPC_BAT0U, VALIDMPC6xx, T_ULONG }, { "\005""BAT0L", CV_PPC_BAT0L, VALIDMPC6xx, T_ULONG }, { "\005""BAT1U", CV_PPC_BAT1U, VALIDMPC6xx, T_ULONG }, { "\005""BAT1L", CV_PPC_BAT1L, VALIDMPC6xx, T_ULONG }, { "\005""BAT2U", CV_PPC_BAT2U, VALIDMPC6xx, T_ULONG }, { "\005""BAT2L", CV_PPC_BAT2L, VALIDMPC6xx, T_ULONG }, { "\005""BAT3U", CV_PPC_BAT3U, VALIDMPC6xx, T_ULONG }, { "\005""BAT3L", CV_PPC_BAT3L, VALIDMPC6xx, T_ULONG }, { "\006""DBAT0U", CV_PPC_DBAT0U, VALIDMPC6xx, T_ULONG }, { "\006""DBAT0L", CV_PPC_DBAT0L, VALIDMPC6xx, T_ULONG }, { "\006""DBAT1U", CV_PPC_DBAT1U, VALIDMPC6xx, T_ULONG }, { "\006""DBAT1L", CV_PPC_DBAT1L, VALIDMPC6xx, T_ULONG }, { "\006""DBAT2U", CV_PPC_DBAT2U, VALIDMPC6xx, T_ULONG }, { "\006""DBAT2L", CV_PPC_DBAT2L, VALIDMPC6xx, T_ULONG }, { "\006""DBAT3U", CV_PPC_DBAT3U, VALIDMPC6xx, T_ULONG }, { "\006""DBAT3L", CV_PPC_DBAT3L, VALIDMPC6xx, T_ULONG }, /* ** PowerPC Special Purpose Registers Implementation Dependent ( Supervisor Level ) */ /* ** Doesn't appear that IBM/Motorola has finished defining these. */ { "\004""PMR0", CV_PPC_PMR0, VALIDMPC620, T_ULONG }, // MPC620 { "\004""PMR1", CV_PPC_PMR1, VALIDMPC620, T_ULONG }, // MPC620 { "\004""PMR2", CV_PPC_PMR2, VALIDMPC620, T_ULONG }, // MPC620 { "\004""PMR3", CV_PPC_PMR3, VALIDMPC620, T_ULONG }, // MPC620 { "\004""PMR4", CV_PPC_PMR4, VALIDMPC620, T_ULONG }, // MPC620 { "\004""PMR5", CV_PPC_PMR5, VALIDMPC620, T_ULONG }, // MPC620 { "\004""PMR6", CV_PPC_PMR6, VALIDMPC620, T_ULONG }, // MPC620 { "\004""PMR7", CV_PPC_PMR7, VALIDMPC620, T_ULONG }, // MPC620 { "\004""PMR8", CV_PPC_PMR8, VALIDMPC620, T_ULONG }, // MPC620 { "\004""PMR9", CV_PPC_PMR9, VALIDMPC620, T_ULONG }, // MPC620 { "\005""PMR10", CV_PPC_PMR10, VALIDMPC620, T_ULONG }, // MPC620 { "\005""PMR11", CV_PPC_PMR11, VALIDMPC620, T_ULONG }, // MPC620 { "\005""PMR12", CV_PPC_PMR12, VALIDMPC620, T_ULONG }, // MPC620 { "\005""PMR13", CV_PPC_PMR13, VALIDMPC620, T_ULONG }, // MPC620 { "\005""PMR14", CV_PPC_PMR14, VALIDMPC620, T_ULONG }, // MPC620 { "\005""PMR15", CV_PPC_PMR15, VALIDMPC620, T_ULONG }, // MPC620 { "\005""DMISS", CV_PPC_DMISS, VALIDMPC603, T_ULONG }, // MPC603 { "\004""DCMP", CV_PPC_DCMP, VALIDMPC603, T_ULONG }, // MPC603 { "\005""HASH1", CV_PPC_HASH1, VALIDMPC603, T_ULONG }, // MPC603 { "\005""HASH2", CV_PPC_HASH2, VALIDMPC603, T_ULONG }, // MPC603 { "\005""IMISS", CV_PPC_IMISS, VALIDMPC603, T_ULONG }, // MPC603 { "\004""ICMP", CV_PPC_ICMP, VALIDMPC603, T_ULONG }, // MPC603 { "\003""RPA", CV_PPC_RPA, VALIDMPC603, T_ULONG }, // MPC603 { "\004""HID0", CV_PPC_HID0, VALIDMPC601 | VALIDMPC603 | VALIDMPC620, T_ULONG }, // MPC601, MPC603, MPC620 { "\004""HID1", CV_PPC_HID1, VALIDMPC601, T_ULONG }, // MPC601 { "\004""HID2", CV_PPC_HID2, VALIDMPC601 | VALIDMPC603 | VALIDMPC620, T_ULONG }, // MPC601, MPC603, MPC620 ( IABR ) { "\004""HID3", CV_PPC_HID3, VALIDMPC6xx, T_ULONG }, // Not Defined { "\004""HID4", CV_PPC_HID4, VALIDMPC6xx, T_ULONG }, // Not Defined { "\004""HID5", CV_PPC_HID5, VALIDMPC601 | VALIDMPC604 | VALIDMPC620, T_ULONG }, // MPC601, MPC604, MPC620 ( DABR ) { "\004""HID6", CV_PPC_HID6, VALIDMPC6xx, T_ULONG }, // Not Defined { "\004""HID7", CV_PPC_HID7, VALIDMPC6xx, T_ULONG }, // Not Defined { "\004""HID8", CV_PPC_HID8, VALIDMPC620, T_ULONG }, // MPC620 ( BUSCSR ) { "\004""HID9", CV_PPC_HID9, VALIDMPC620, T_ULONG }, // MPC620 ( L2CSR ) { "\005""HID10", CV_PPC_HID10, VALIDMPC6xx, T_ULONG }, // Not Defined { "\005""HID11", CV_PPC_HID11, VALIDMPC6xx, T_ULONG }, // Not Defined { "\005""HID12", CV_PPC_HID12, VALIDMPC6xx, T_ULONG }, // Not Defined { "\005""HID13", CV_PPC_HID13, VALIDMPC604, T_ULONG }, // MPC604 ( HCR ) { "\005""HID14", CV_PPC_HID14, VALIDMPC6xx, T_ULONG }, // Not Defined { "\005""HID15", CV_PPC_HID15, VALIDMPC601 | VALIDMPC604 | VALIDMPC620, T_ULONG } // MPC601, MPC604, MPC620 ( PIR ) }; #define VALID68851 0x40 #define VALID68882 0x80 #define VALID68000 0x01 #define VALID68010 0x02 | VALID68000 #define VALID68020 0x04 | VALID68010 #define VALID68030 0x08 | VALID68020 | VALID68851 #define VALID68040 0x10 | VALID68030 struct hreg_68k { char name[7]; ulong index; ulong valid; CV_typ_t type; } const hreg_list_68k[] = { {"\x002""D0", CV_R68_D0, VALID68000, T_ULONG}, {"\x002""D1", CV_R68_D1, VALID68000, T_ULONG}, {"\x002""D2", CV_R68_D2, VALID68000, T_ULONG}, {"\x002""D3", CV_R68_D3, VALID68000, T_ULONG}, {"\x002""D4", CV_R68_D4, VALID68000, T_ULONG}, {"\x002""D5", CV_R68_D5, VALID68000, T_ULONG}, {"\x002""D6", CV_R68_D6, VALID68000, T_ULONG}, {"\x002""D7", CV_R68_D7, VALID68000, T_ULONG}, {"\x002""A0", CV_R68_A0, VALID68000, T_ULONG}, {"\x002""A1", CV_R68_A1, VALID68000, T_ULONG}, {"\x002""A2", CV_R68_A2, VALID68000, T_ULONG}, {"\x002""A3", CV_R68_A3, VALID68000, T_ULONG}, {"\x002""A4", CV_R68_A4, VALID68000, T_ULONG}, {"\x002""A5", CV_R68_A5, VALID68000, T_ULONG}, {"\x002""A6", CV_R68_A6, VALID68000, T_ULONG}, {"\x002""A7", CV_R68_A7, VALID68000, T_ULONG}, {"\x003""CCR", CV_R68_CCR, VALID68000, T_UCHAR}, {"\x002""SR", CV_R68_SR, VALID68000, T_USHORT}, #if 0 {"\x003""USP", CV_R68_USP, VALID68000, T_ULONG}, {"\x003""MSP", CV_R68_MSP, VALID68000, T_ULONG}, #endif {"\x002""PC", CV_R68_PC, VALID68000, T_ULONG}, #if 0 {"\x003""SFC", CV_R68_SFC, VALID68010, T_USHORT}, {"\x003""DFC", CV_R68_DFC, VALID68010, T_USHORT}, {"\x003""VBR", CV_R68_VBR, VALID68010, T_USHORT}, {"\x004""CACR", CV_R68_CACR, VALID68020, T_ULONG}, {"\x004""CAAR", CV_R68_CAAR, VALID68020, T_ULONG}, {"\x003""ISP", CV_R68_ISP, VALID68020, T_ULONG}, {"\x003""PSR", CV_R68_PSR, VALID68851, T_USHORT}, {"\x004""PCSR", CV_R68_PCSR, VALID68851, T_USHORT}, {"\x003""VAL", CV_R68_VAL, VALID68851, T_USHORT}, {"\x003""CRP", CV_R68_CRP, VALID68851, T_UQUAD}, {"\x003""SRP", CV_R68_SRP, VALID68851, T_UQUAD}, {"\x003""DRP", CV_R68_DRP, VALID68851, T_UQUAD}, {"\x002""TC", CV_R68_TC, VALID68851, T_ULONG}, {"\x002""AC", CV_R68_AC, VALID68851, T_USHORT}, {"\x003""SCC", CV_R68_SCC, VALID68851, T_USHORT}, {"\x003""CAL", CV_R68_CAL, VALID68851, T_USHORT}, {"\x004""BAD0", CV_R68_BAD0, VALID68851, T_USHORT}, {"\x004""BAD1", CV_R68_BAD1, VALID68851, T_USHORT}, {"\x004""BAD2", CV_R68_BAD2, VALID68851, T_USHORT}, {"\x004""BAD3", CV_R68_BAD3, VALID68851, T_USHORT}, {"\x004""BAD4", CV_R68_BAD4, VALID68851, T_USHORT}, {"\x004""BAD5", CV_R68_BAD5, VALID68851, T_USHORT}, {"\x004""BAD6", CV_R68_BAD6, VALID68851, T_USHORT}, {"\x004""BAD7", CV_R68_BAD7, VALID68851, T_USHORT}, {"\x004""BAC0", CV_R68_BAC0, VALID68851, T_USHORT}, {"\x004""BAC1", CV_R68_BAC1, VALID68851, T_USHORT}, {"\x004""BAC2", CV_R68_BAC2, VALID68851, T_USHORT}, {"\x004""BAC3", CV_R68_BAC3, VALID68851, T_USHORT}, {"\x004""BAC4", CV_R68_BAC4, VALID68851, T_USHORT}, {"\x004""BAC5", CV_R68_BAC5, VALID68851, T_USHORT}, {"\x004""BAC6", CV_R68_BAC6, VALID68851, T_USHORT}, {"\x004""BAC7", CV_R68_BAC7, VALID68851, T_USHORT}, {"\x003""TT0", CV_R68_TT0, VALID68030, T_ULONG}, {"\x003""TT1", CV_R68_TT1, VALID68030, T_ULONG}, #endif {"\x004""FPCR", CV_R68_FPCR, VALID68882, T_ULONG}, {"\x004""FPSR", CV_R68_FPSR, VALID68882, T_ULONG}, {"\x005""FPIAR", CV_R68_FPIAR, VALID68882, T_ULONG}, {"\x003""FP0", CV_R68_FP0, VALID68882, T_REAL80}, {"\x003""FP1", CV_R68_FP1, VALID68882, T_REAL80}, {"\x003""FP2", CV_R68_FP2, VALID68882, T_REAL80}, {"\x003""FP3", CV_R68_FP3, VALID68882, T_REAL80}, {"\x003""FP4", CV_R68_FP4, VALID68882, T_REAL80}, {"\x003""FP5", CV_R68_FP5, VALID68882, T_REAL80}, {"\x003""FP6", CV_R68_FP6, VALID68882, T_REAL80}, {"\x003""FP7", CV_R68_FP7, VALID68882, T_REAL80}, }; #define VALIDx86 0x01 #define VALID386 0x02 #define REGHI 0x04 #define REGLO 0x08 #define VALIDx87 0x10 struct hreg_x86 { char name[5]; int index; ulong valid; CV_typ_t type; } const hreg_list_x86[] = { {"\x002""AX", CV_REG_AX, VALIDx86 | VALID386, T_USHORT}, {"\x002""BX", CV_REG_BX, VALIDx86 | VALID386, T_USHORT}, {"\x002""CX", CV_REG_CX, VALIDx86 | VALID386, T_USHORT}, {"\x002""DX", CV_REG_DX, VALIDx86 | VALID386, T_USHORT}, {"\x002""SP", CV_REG_SP, VALIDx86 | VALID386, T_USHORT}, {"\x002""BP", CV_REG_BP, VALIDx86 | VALID386, T_USHORT}, {"\x002""SI", CV_REG_SI, VALIDx86 | VALID386, T_USHORT}, {"\x002""DI", CV_REG_DI, VALIDx86 | VALID386, T_USHORT}, {"\x002""DS", CV_REG_DS, VALIDx86 | VALID386, T_USHORT}, {"\x002""ES", CV_REG_ES, VALIDx86 | VALID386, T_USHORT}, {"\x002""SS", CV_REG_SS, VALIDx86 | VALID386, T_USHORT}, {"\x002""CS", CV_REG_CS, VALIDx86 | VALID386, T_USHORT}, {"\x002""IP", CV_REG_IP, VALIDx86 | VALID386, T_USHORT}, {"\x002""FL", CV_REG_FLAGS, VALIDx86 | VALID386, T_USHORT}, {"\x003""EFL", CV_REG_EFLAGS, VALID386, T_ULONG}, {"\x003""EAX", CV_REG_EAX, VALID386, T_ULONG}, {"\x003""EBX", CV_REG_EBX, VALID386, T_ULONG}, {"\x003""ECX", CV_REG_ECX, VALID386, T_ULONG}, {"\x003""EDX", CV_REG_EDX, VALID386, T_ULONG}, {"\x003""ESP", CV_REG_ESP, VALID386, T_ULONG}, {"\x003""EBP", CV_REG_EBP, VALID386, T_ULONG}, {"\x003""ESI", CV_REG_ESI, VALID386, T_ULONG}, {"\x003""EDI", CV_REG_EDI, VALID386, T_ULONG}, {"\x003""EIP", CV_REG_EIP, VALID386, T_ULONG}, {"\x002""PQ", CV_REG_QUOTE, VALIDx86, T_USHORT}, {"\x002""TL", CV_REG_TEMP, VALIDx86, T_USHORT}, {"\x002""TH", CV_REG_TEMPH, VALIDx86, T_USHORT}, {"\x002""FS", CV_REG_FS, VALID386, T_USHORT}, {"\x002""GS", CV_REG_GS, VALID386, T_USHORT}, {"\x002""AH", CV_REG_AH, VALIDx86 | VALID386 | REGHI, T_UCHAR}, {"\x002""BH", CV_REG_BH, VALIDx86 | VALID386 | REGHI, T_UCHAR}, {"\x002""CH", CV_REG_CH, VALIDx86 | VALID386 | REGHI, T_UCHAR}, {"\x002""DH", CV_REG_DH, VALIDx86 | VALID386 | REGHI, T_UCHAR}, {"\x002""AL", CV_REG_AL, VALIDx86 | VALID386 | REGLO, T_UCHAR}, {"\x002""BL", CV_REG_BL, VALIDx86 | VALID386 | REGLO, T_UCHAR}, {"\x002""CL", CV_REG_CL, VALIDx86 | VALID386 | REGLO, T_UCHAR}, {"\x002""DL", CV_REG_DL, VALIDx86 | VALID386 | REGLO, T_UCHAR}, {"\x002""st", CV_REG_ST0, VALIDx86 | VALID386 | VALIDx87, T_REAL80}, {"\x003""st0", CV_REG_ST0, VALIDx86 | VALID386 | VALIDx87, T_REAL80}, {"\x003""st1", CV_REG_ST1, VALIDx86 | VALID386 | VALIDx87, T_REAL80}, {"\x003""st2", CV_REG_ST2, VALIDx86 | VALID386 | VALIDx87, T_REAL80}, {"\x003""st3", CV_REG_ST3, VALIDx86 | VALID386 | VALIDx87, T_REAL80}, {"\x003""st4", CV_REG_ST4, VALIDx86 | VALID386 | VALIDx87, T_REAL80}, {"\x003""st5", CV_REG_ST5, VALIDx86 | VALID386 | VALIDx87, T_REAL80}, {"\x003""st6", CV_REG_ST6, VALIDx86 | VALID386 | VALIDx87, T_REAL80}, {"\x003""st7", CV_REG_ST7, VALIDx86 | VALID386 | VALIDx87, T_REAL80}, {"\x003""MM0", CV_REG_MM0, VALIDx86 , T_UQUAD}, {"\x003""MM1", CV_REG_MM1, VALIDx86 , T_UQUAD}, {"\x003""MM2", CV_REG_MM2, VALIDx86 , T_UQUAD}, {"\x003""MM3", CV_REG_MM3, VALIDx86 , T_UQUAD}, {"\x003""MM4", CV_REG_MM4, VALIDx86 , T_UQUAD}, {"\x003""MM5", CV_REG_MM5, VALIDx86 , T_UQUAD}, {"\x003""MM6", CV_REG_MM6, VALIDx86 , T_UQUAD}, {"\x003""MM7", CV_REG_MM7, VALIDx86 , T_UQUAD}, // {"\x003""TEB", CV_REG_TEB, VALIDx86, T_ULONG}, // {"\x003""ERR", CV_REG_ERR, VALIDx86, T_ULONG}, }; struct hreg_mip { char name[5]; int index; CV_typ_t type; } const hreg_list_mip[] = { {"\004""ZERO", CV_M4_IntZERO, T_ULONG}, {"\002""AT", CV_M4_IntAT, T_ULONG}, {"\002""V0", CV_M4_IntV0, T_ULONG}, {"\002""V1", CV_M4_IntV1, T_ULONG}, {"\002""A0", CV_M4_IntA0, T_ULONG}, {"\002""A1", CV_M4_IntA1, T_ULONG}, {"\002""A2", CV_M4_IntA2, T_ULONG}, {"\002""A3", CV_M4_IntA3, T_ULONG}, {"\002""T0", CV_M4_IntT0, T_ULONG}, {"\002""T1", CV_M4_IntT1, T_ULONG}, {"\002""T2", CV_M4_IntT2, T_ULONG}, {"\002""T3", CV_M4_IntT3, T_ULONG}, {"\002""T4", CV_M4_IntT4, T_ULONG}, {"\002""T5", CV_M4_IntT5, T_ULONG}, {"\002""T6", CV_M4_IntT6, T_ULONG}, {"\002""T7", CV_M4_IntT7, T_ULONG}, {"\002""T8", CV_M4_IntT8, T_ULONG}, {"\002""T9", CV_M4_IntT9, T_ULONG}, {"\002""S0", CV_M4_IntS0, T_ULONG}, {"\002""S1", CV_M4_IntS1, T_ULONG}, {"\002""S2", CV_M4_IntS2, T_ULONG}, {"\002""S3", CV_M4_IntS3, T_ULONG}, {"\002""S4", CV_M4_IntS4, T_ULONG}, {"\002""S5", CV_M4_IntS5, T_ULONG}, {"\002""S6", CV_M4_IntS6, T_ULONG}, {"\002""S7", CV_M4_IntS7, T_ULONG}, {"\002""S8", CV_M4_IntS8, T_ULONG}, {"\002""K0", CV_M4_IntKT0, T_ULONG}, {"\002""K1", CV_M4_IntKT1, T_ULONG}, {"\002""GP", CV_M4_IntGP, T_ULONG}, {"\002""SP", CV_M4_IntSP, T_ULONG}, {"\002""RA", CV_M4_IntRA, T_ULONG}, {"\003""FIR", CV_M4_Fir, T_ULONG}, {"\002""PC", CV_M4_Fir, T_ULONG}, {"\003""PSR", CV_M4_Psr, T_ULONG}, {"\003""FSR", CV_M4_FltFsr, T_ULONG}, {"\002""HI", CV_M4_IntHI, T_ULONG}, {"\002""LO", CV_M4_IntLO, T_ULONG}, {"\003""FR0", CV_M4_FltF0, T_REAL32}, {"\003""FR1", CV_M4_FltF1, T_REAL32}, {"\003""FR2", CV_M4_FltF2, T_REAL32}, {"\003""FR3", CV_M4_FltF3, T_REAL32}, {"\003""FR4", CV_M4_FltF4, T_REAL32}, {"\003""FR5", CV_M4_FltF5, T_REAL32}, {"\003""FR6", CV_M4_FltF6, T_REAL32}, {"\003""FR7", CV_M4_FltF7, T_REAL32}, {"\003""FR8", CV_M4_FltF8, T_REAL32}, {"\003""FR9", CV_M4_FltF9, T_REAL32}, {"\004""FR10", CV_M4_FltF10, T_REAL32}, {"\004""FR11", CV_M4_FltF11, T_REAL32}, {"\004""FR12", CV_M4_FltF12, T_REAL32}, {"\004""FR13", CV_M4_FltF13, T_REAL32}, {"\004""FR14", CV_M4_FltF14, T_REAL32}, {"\004""FR15", CV_M4_FltF15, T_REAL32}, {"\004""FR16", CV_M4_FltF16, T_REAL32}, {"\004""FR17", CV_M4_FltF17, T_REAL32}, {"\004""FR18", CV_M4_FltF18, T_REAL32}, {"\004""FR19", CV_M4_FltF19, T_REAL32}, {"\004""FR20", CV_M4_FltF20, T_REAL32}, {"\004""FR21", CV_M4_FltF21, T_REAL32}, {"\004""FR22", CV_M4_FltF22, T_REAL32}, {"\004""FR23", CV_M4_FltF23, T_REAL32}, {"\004""FR24", CV_M4_FltF24, T_REAL32}, {"\004""FR25", CV_M4_FltF25, T_REAL32}, {"\004""FR26", CV_M4_FltF26, T_REAL32}, {"\004""FR27", CV_M4_FltF27, T_REAL32}, {"\004""FR28", CV_M4_FltF28, T_REAL32}, {"\004""FR29", CV_M4_FltF29, T_REAL32}, {"\004""FR30", CV_M4_FltF30, T_REAL32}, {"\004""FR31", CV_M4_FltF31, T_REAL32}, {"\003""FP0", CV_M4_FltF1 << 8 | CV_M4_FltF0, T_REAL64}, {"\003""FP2", CV_M4_FltF3 << 8 | CV_M4_FltF2, T_REAL64}, {"\003""FP4", CV_M4_FltF5 << 8 | CV_M4_FltF4, T_REAL64}, {"\003""FP6", CV_M4_FltF7 << 8 | CV_M4_FltF6, T_REAL64}, {"\003""FP8", CV_M4_FltF9 << 8 | CV_M4_FltF8, T_REAL64}, {"\004""FP10", CV_M4_FltF11 << 8 | CV_M4_FltF10, T_REAL64}, {"\004""FP12", CV_M4_FltF13 << 8 | CV_M4_FltF12, T_REAL64}, {"\004""FP14", CV_M4_FltF15 << 8 | CV_M4_FltF14, T_REAL64}, {"\004""FP16", CV_M4_FltF17 << 8 | CV_M4_FltF16, T_REAL64}, {"\004""FP18", CV_M4_FltF19 << 8 | CV_M4_FltF18, T_REAL64}, {"\004""FP20", CV_M4_FltF21 << 8 | CV_M4_FltF20, T_REAL64}, {"\004""FP22", CV_M4_FltF23 << 8 | CV_M4_FltF22, T_REAL64}, {"\004""FP24", CV_M4_FltF25 << 8 | CV_M4_FltF24, T_REAL64}, {"\004""FP26", CV_M4_FltF27 << 8 | CV_M4_FltF26, T_REAL64}, {"\004""FP28", CV_M4_FltF29 << 8 | CV_M4_FltF28, T_REAL64}, {"\004""FP30", CV_M4_FltF31 << 8 | CV_M4_FltF30, T_REAL64}, }; struct hreg_axp { char name[5]; int index; CV_typ_t type; } hreg_list_axp[] = { {"\004""ZERO", CV_ALPHA_IntZERO, T_UQUAD}, {"\002""AT", CV_ALPHA_IntAT, T_UQUAD}, {"\002""V0", CV_ALPHA_IntV0, T_UQUAD}, {"\002""A0", CV_ALPHA_IntA0, T_UQUAD}, {"\002""A1", CV_ALPHA_IntA1, T_UQUAD}, {"\002""A2", CV_ALPHA_IntA2, T_UQUAD}, {"\002""A3", CV_ALPHA_IntA3, T_UQUAD}, {"\002""A4", CV_ALPHA_IntA4, T_UQUAD}, {"\002""A5", CV_ALPHA_IntA5, T_UQUAD}, {"\002""T0", CV_ALPHA_IntT0, T_UQUAD}, {"\002""T1", CV_ALPHA_IntT1, T_UQUAD}, {"\002""T2", CV_ALPHA_IntT2, T_UQUAD}, {"\002""T3", CV_ALPHA_IntT3, T_UQUAD}, {"\002""T4", CV_ALPHA_IntT4, T_UQUAD}, {"\002""T5", CV_ALPHA_IntT5, T_UQUAD}, {"\002""T6", CV_ALPHA_IntT6, T_UQUAD}, {"\002""T7", CV_ALPHA_IntT7, T_UQUAD}, {"\002""T8", CV_ALPHA_IntT8, T_UQUAD}, {"\002""T9", CV_ALPHA_IntT9, T_UQUAD}, {"\003""T10", CV_ALPHA_IntT10, T_UQUAD}, {"\003""T11", CV_ALPHA_IntT11, T_UQUAD}, {"\003""T12", CV_ALPHA_IntT12, T_UQUAD}, {"\002""S0", CV_ALPHA_IntS0, T_UQUAD}, {"\002""S1", CV_ALPHA_IntS1, T_UQUAD}, {"\002""S2", CV_ALPHA_IntS2, T_UQUAD}, {"\002""S3", CV_ALPHA_IntS3, T_UQUAD}, {"\002""S4", CV_ALPHA_IntS4, T_UQUAD}, {"\002""S5", CV_ALPHA_IntS5, T_UQUAD}, {"\002""GP", CV_ALPHA_IntGP, T_UQUAD}, {"\002""SP", CV_ALPHA_IntSP, T_UQUAD}, {"\002""FP", CV_ALPHA_IntFP, T_UQUAD}, {"\004""FPCR", CV_ALPHA_Fpcr, T_UQUAD}, {"\002""RA", CV_ALPHA_IntRA, T_UQUAD}, {"\003""FIR", CV_ALPHA_Fir, T_UQUAD}, {"\003""PC", CV_ALPHA_Fir, T_UQUAD}, {"\003""PSR", CV_ALPHA_Psr, T_UQUAD}, {"\003""FSR", CV_ALPHA_FltFsr, T_UQUAD}, {"\002""F0", CV_ALPHA_FltF0, T_REAL64}, {"\002""F1", CV_ALPHA_FltF1, T_REAL64}, {"\002""F2", CV_ALPHA_FltF2, T_REAL64}, {"\002""F3", CV_ALPHA_FltF3, T_REAL64}, {"\002""F4", CV_ALPHA_FltF4, T_REAL64}, {"\002""F5", CV_ALPHA_FltF5, T_REAL64}, {"\002""F6", CV_ALPHA_FltF6, T_REAL64}, {"\002""F7", CV_ALPHA_FltF7, T_REAL64}, {"\002""F8", CV_ALPHA_FltF8, T_REAL64}, {"\002""F9", CV_ALPHA_FltF9, T_REAL64}, {"\003""F10", CV_ALPHA_FltF10, T_REAL64}, {"\003""F11", CV_ALPHA_FltF11, T_REAL64}, {"\003""F12", CV_ALPHA_FltF12, T_REAL64}, {"\003""F13", CV_ALPHA_FltF13, T_REAL64}, {"\003""F14", CV_ALPHA_FltF14, T_REAL64}, {"\003""F15", CV_ALPHA_FltF15, T_REAL64}, {"\003""F16", CV_ALPHA_FltF16, T_REAL64}, {"\003""F17", CV_ALPHA_FltF17, T_REAL64}, {"\003""F18", CV_ALPHA_FltF18, T_REAL64}, {"\003""F19", CV_ALPHA_FltF19, T_REAL64}, {"\003""F20", CV_ALPHA_FltF20, T_REAL64}, {"\003""F21", CV_ALPHA_FltF21, T_REAL64}, {"\003""F22", CV_ALPHA_FltF22, T_REAL64}, {"\003""F23", CV_ALPHA_FltF23, T_REAL64}, {"\003""F24", CV_ALPHA_FltF24, T_REAL64}, {"\003""F25", CV_ALPHA_FltF25, T_REAL64}, {"\003""F26", CV_ALPHA_FltF26, T_REAL64}, {"\003""F27", CV_ALPHA_FltF27, T_REAL64}, {"\003""F28", CV_ALPHA_FltF28, T_REAL64}, {"\003""F29", CV_ALPHA_FltF29, T_REAL64}, {"\003""F30", CV_ALPHA_FltF30, T_REAL64}, {"\003""F31", CV_ALPHA_FltF31, T_REAL64}, }; struct hreg_ia64 { char name[9]; //v-vadimp we have "BSPSTORE" int index; CV_typ_t type; } hreg_list_ia64[] = { // First, the pseudo registers {"\x002""$p", CV_REG_PSEUDO1, T_ULONG}, {"\x003""$p1", CV_REG_PSEUDO1, T_ULONG}, {"\x003""$p2", CV_REG_PSEUDO2, T_ULONG}, {"\x003""$p3", CV_REG_PSEUDO3, T_ULONG}, {"\x003""$p4", CV_REG_PSEUDO4, T_ULONG}, {"\x002""$u", CV_REG_PSEUDO5, T_ULONG}, {"\x003""$u1", CV_REG_PSEUDO5, T_ULONG}, {"\x003""$u2", CV_REG_PSEUDO6, T_ULONG}, {"\x003""$u3", CV_REG_PSEUDO7, T_ULONG}, {"\x003""$u4", CV_REG_PSEUDO8, T_ULONG}, {"\x004""$exp", CV_REG_PSEUDO9, T_ULONG}, // Then the IA64 registers. {"\004""BRRP", CV_IA64_BrRp, T_UQUAD }, {"\004""BRS0", CV_IA64_BrS0, T_UQUAD }, {"\004""BRS1", CV_IA64_BrS1, T_UQUAD }, {"\004""BRS2", CV_IA64_BrS2, T_UQUAD }, {"\004""BRS3", CV_IA64_BrS3, T_UQUAD }, {"\004""BRS4", CV_IA64_BrS4, T_UQUAD }, {"\004""BRT0", CV_IA64_BrT0, T_UQUAD }, {"\004""BRT1", CV_IA64_BrT1, T_UQUAD }, {"\005""PREDS", CV_IA64_Preds, T_UQUAD}, // {"\002""P0", CV_IA64_P0, T_BIT }, // {"\002""P1", CV_IA64_P1, T_BIT }, // {"\002""P2", CV_IA64_P2, T_BIT }, // {"\002""P3", CV_IA64_P3, T_BIT }, // {"\002""P4", CV_IA64_P4, T_BIT }, // {"\002""P5", CV_IA64_P5, T_BIT }, // {"\002""P6", CV_IA64_P6, T_BIT }, // {"\002""P7", CV_IA64_P7, T_BIT }, // {"\002""P8", CV_IA64_P8, T_BIT }, // {"\002""P9", CV_IA64_P9, T_BIT }, // {"\003""P10", CV_IA64_P10, T_BIT }, // {"\003""P11", CV_IA64_P11, T_BIT }, // {"\003""P12", CV_IA64_P12, T_BIT }, // {"\003""P13", CV_IA64_P13, T_BIT }, // {"\003""P14", CV_IA64_P14, T_BIT }, // {"\003""P15", CV_IA64_P15, T_BIT }, // {"\003""P16", CV_IA64_P16, T_BIT }, // {"\003""P17", CV_IA64_P17, T_BIT }, // {"\003""P18", CV_IA64_P18, T_BIT }, // {"\003""P19", CV_IA64_P19, T_BIT }, // {"\003""P20", CV_IA64_P20, T_BIT }, // {"\003""P21", CV_IA64_P21, T_BIT }, // {"\003""P22", CV_IA64_P22, T_BIT }, // {"\003""P23", CV_IA64_P23, T_BIT }, // {"\003""P24", CV_IA64_P24, T_BIT }, // {"\003""P25", CV_IA64_P25, T_BIT }, // {"\003""P26", CV_IA64_P26, T_BIT }, // {"\003""P27", CV_IA64_P27, T_BIT }, // {"\003""P28", CV_IA64_P28, T_BIT }, // {"\003""P29", CV_IA64_P29, T_BIT }, // {"\003""P30", CV_IA64_P30, T_BIT }, // {"\003""P31", CV_IA64_P31, T_BIT }, // {"\003""P32", CV_IA64_P32, T_BIT }, // {"\003""P33", CV_IA64_P33, T_BIT }, // {"\003""P34", CV_IA64_P34, T_BIT }, // {"\003""P35", CV_IA64_P35, T_BIT }, // {"\003""P36", CV_IA64_P36, T_BIT }, // {"\003""P37", CV_IA64_P37, T_BIT }, // {"\003""P38", CV_IA64_P38, T_BIT }, // {"\003""P39", CV_IA64_P39, T_BIT }, // {"\003""P40", CV_IA64_P40, T_BIT }, // {"\003""P41", CV_IA64_P41, T_BIT }, // {"\003""P42", CV_IA64_P42, T_BIT }, // {"\003""P43", CV_IA64_P43, T_BIT }, // {"\003""P44", CV_IA64_P44, T_BIT }, // {"\003""P45", CV_IA64_P45, T_BIT }, // {"\003""P46", CV_IA64_P46, T_BIT }, // {"\003""P47", CV_IA64_P47, T_BIT }, // {"\003""P48", CV_IA64_P48, T_BIT }, // {"\003""P49", CV_IA64_P49, T_BIT }, // {"\003""P50", CV_IA64_P50, T_BIT }, // {"\003""P51", CV_IA64_P51, T_BIT }, // {"\003""P52", CV_IA64_P52, T_BIT }, // {"\003""P53", CV_IA64_P53, T_BIT }, // {"\003""P54", CV_IA64_P54, T_BIT }, // {"\003""P55", CV_IA64_P55, T_BIT }, // {"\003""P56", CV_IA64_P56, T_BIT }, // {"\003""P57", CV_IA64_P57, T_BIT }, // {"\003""P58", CV_IA64_P58, T_BIT }, // {"\003""P59", CV_IA64_P59, T_BIT }, // {"\003""P60", CV_IA64_P60, T_BIT }, // {"\003""P61", CV_IA64_P61, T_BIT }, // {"\003""P62", CV_IA64_P62, T_BIT }, // {"\003""P63", CV_IA64_P63, T_BIT }, {"\002""IP", CV_IA64_Ip, T_UQUAD }, {"\004""NATS", CV_IA64_IntNats, T_UQUAD }, {"\003""CFM", CV_IA64_Cfm, T_UQUAD }, {"\003""PSR", CV_IA64_Psr, T_UQUAD }, {"\004""ZERO", CV_IA64_IntZero, T_UQUAD }, {"\002""GP", CV_IA64_IntGp, T_UQUAD }, {"\002""T0", CV_IA64_IntT0, T_UQUAD }, {"\002""T1", CV_IA64_IntT1, T_UQUAD }, {"\002""S0", CV_IA64_IntS0, T_UQUAD }, {"\002""S1", CV_IA64_IntS1, T_UQUAD }, {"\002""S2", CV_IA64_IntS2, T_UQUAD }, {"\002""S3", CV_IA64_IntS3, T_UQUAD }, {"\002""V0", CV_IA64_IntV0, T_UQUAD }, {"\002""Teb", CV_IA64_IntTeb, T_UQUAD }, {"\002""T2", CV_IA64_IntT2, T_UQUAD }, {"\002""T3", CV_IA64_IntT3, T_UQUAD }, {"\002""SP", CV_IA64_IntSp, T_UQUAD }, {"\002""T4", CV_IA64_IntT4, T_UQUAD }, {"\002""T5", CV_IA64_IntT5, T_UQUAD }, {"\002""T6", CV_IA64_IntT6, T_UQUAD }, {"\002""T7", CV_IA64_IntT7, T_UQUAD }, {"\002""T8", CV_IA64_IntT8, T_UQUAD }, {"\002""T9", CV_IA64_IntT9, T_UQUAD }, {"\003""T10", CV_IA64_IntT10, T_UQUAD }, {"\003""T11", CV_IA64_IntT11, T_UQUAD }, {"\003""T12", CV_IA64_IntT12, T_UQUAD }, {"\003""T13", CV_IA64_IntT13, T_UQUAD }, {"\003""T14", CV_IA64_IntT14, T_UQUAD }, {"\003""T15", CV_IA64_IntT15, T_UQUAD }, {"\003""T16", CV_IA64_IntT16, T_UQUAD }, {"\003""T17", CV_IA64_IntT17, T_UQUAD }, {"\003""T18", CV_IA64_IntT18, T_UQUAD }, {"\003""T19", CV_IA64_IntT19, T_UQUAD }, {"\003""T20", CV_IA64_IntT20, T_UQUAD }, {"\003""T21", CV_IA64_IntT21, T_UQUAD }, {"\003""T22", CV_IA64_IntT22, T_UQUAD }, {"\003""R32", CV_IA64_IntR32, T_UQUAD }, {"\003""R33", CV_IA64_IntR33, T_UQUAD }, {"\003""R34", CV_IA64_IntR34, T_UQUAD }, {"\003""R35", CV_IA64_IntR35, T_UQUAD }, {"\003""R36", CV_IA64_IntR36, T_UQUAD }, {"\003""R37", CV_IA64_IntR37, T_UQUAD }, {"\003""R38", CV_IA64_IntR38, T_UQUAD }, {"\003""R39", CV_IA64_IntR39, T_UQUAD }, {"\003""R40", CV_IA64_IntR40, T_UQUAD }, {"\003""R41", CV_IA64_IntR41, T_UQUAD }, {"\003""R42", CV_IA64_IntR42, T_UQUAD }, {"\003""R43", CV_IA64_IntR43, T_UQUAD }, {"\003""R44", CV_IA64_IntR44, T_UQUAD }, {"\003""R45", CV_IA64_IntR45, T_UQUAD }, {"\003""R46", CV_IA64_IntR46, T_UQUAD }, {"\003""R47", CV_IA64_IntR47, T_UQUAD }, {"\003""R48", CV_IA64_IntR48, T_UQUAD }, {"\003""R49", CV_IA64_IntR49, T_UQUAD }, {"\003""R50", CV_IA64_IntR50, T_UQUAD }, {"\003""R51", CV_IA64_IntR51, T_UQUAD }, {"\003""R52", CV_IA64_IntR52, T_UQUAD }, {"\003""R53", CV_IA64_IntR53, T_UQUAD }, {"\003""R54", CV_IA64_IntR54, T_UQUAD }, {"\003""R55", CV_IA64_IntR55, T_UQUAD }, {"\003""R56", CV_IA64_IntR56, T_UQUAD }, {"\003""R57", CV_IA64_IntR57, T_UQUAD }, {"\003""R58", CV_IA64_IntR58, T_UQUAD }, {"\003""R59", CV_IA64_IntR59, T_UQUAD }, {"\003""R60", CV_IA64_IntR60, T_UQUAD }, {"\003""R61", CV_IA64_IntR61, T_UQUAD }, {"\003""R62", CV_IA64_IntR62, T_UQUAD }, {"\003""R63", CV_IA64_IntR63, T_UQUAD }, {"\003""R64", CV_IA64_IntR64, T_UQUAD }, {"\003""R65", CV_IA64_IntR65, T_UQUAD }, {"\003""R66", CV_IA64_IntR66, T_UQUAD }, {"\003""R67", CV_IA64_IntR67, T_UQUAD }, {"\003""R68", CV_IA64_IntR68, T_UQUAD }, {"\003""R69", CV_IA64_IntR69, T_UQUAD }, {"\003""R70", CV_IA64_IntR70, T_UQUAD }, {"\003""R71", CV_IA64_IntR71, T_UQUAD }, {"\003""R72", CV_IA64_IntR72, T_UQUAD }, {"\003""R73", CV_IA64_IntR73, T_UQUAD }, {"\003""R74", CV_IA64_IntR74, T_UQUAD }, {"\003""R75", CV_IA64_IntR75, T_UQUAD }, {"\003""R76", CV_IA64_IntR76, T_UQUAD }, {"\003""R77", CV_IA64_IntR77, T_UQUAD }, {"\003""R78", CV_IA64_IntR78, T_UQUAD }, {"\003""R79", CV_IA64_IntR79, T_UQUAD }, {"\003""R80", CV_IA64_IntR80, T_UQUAD }, {"\003""R81", CV_IA64_IntR81, T_UQUAD }, {"\003""R82", CV_IA64_IntR82, T_UQUAD }, {"\003""R83", CV_IA64_IntR83, T_UQUAD }, {"\003""R84", CV_IA64_IntR84, T_UQUAD }, {"\003""R85", CV_IA64_IntR85, T_UQUAD }, {"\003""R86", CV_IA64_IntR86, T_UQUAD }, {"\003""R87", CV_IA64_IntR87, T_UQUAD }, {"\003""R88", CV_IA64_IntR88, T_UQUAD }, {"\003""R89", CV_IA64_IntR89, T_UQUAD }, {"\003""R90", CV_IA64_IntR90, T_UQUAD }, {"\003""R91", CV_IA64_IntR91, T_UQUAD }, {"\003""R92", CV_IA64_IntR92, T_UQUAD }, {"\003""R93", CV_IA64_IntR93, T_UQUAD }, {"\003""R94", CV_IA64_IntR94, T_UQUAD }, {"\003""R95", CV_IA64_IntR95, T_UQUAD }, {"\003""R96", CV_IA64_IntR96, T_UQUAD }, {"\003""R97", CV_IA64_IntR97, T_UQUAD }, {"\003""R98", CV_IA64_IntR98, T_UQUAD }, {"\003""R99", CV_IA64_IntR99, T_UQUAD }, {"\004""R100", CV_IA64_IntR100, T_UQUAD }, {"\004""R101", CV_IA64_IntR101, T_UQUAD }, {"\004""R102", CV_IA64_IntR102, T_UQUAD }, {"\004""R103", CV_IA64_IntR103, T_UQUAD }, {"\004""R104", CV_IA64_IntR104, T_UQUAD }, {"\004""R105", CV_IA64_IntR105, T_UQUAD }, {"\004""R106", CV_IA64_IntR106, T_UQUAD }, {"\004""R107", CV_IA64_IntR107, T_UQUAD }, {"\004""R108", CV_IA64_IntR108, T_UQUAD }, {"\004""R109", CV_IA64_IntR109, T_UQUAD }, {"\004""R110", CV_IA64_IntR110, T_UQUAD }, {"\004""R111", CV_IA64_IntR111, T_UQUAD }, {"\004""R112", CV_IA64_IntR112, T_UQUAD }, {"\004""R113", CV_IA64_IntR113, T_UQUAD }, {"\004""R114", CV_IA64_IntR114, T_UQUAD }, {"\004""R115", CV_IA64_IntR115, T_UQUAD }, {"\004""R116", CV_IA64_IntR116, T_UQUAD }, {"\004""R117", CV_IA64_IntR117, T_UQUAD }, {"\004""R118", CV_IA64_IntR118, T_UQUAD }, {"\004""R119", CV_IA64_IntR119, T_UQUAD }, {"\004""R120", CV_IA64_IntR120, T_UQUAD }, {"\004""R121", CV_IA64_IntR121, T_UQUAD }, {"\004""R122", CV_IA64_IntR122, T_UQUAD }, {"\004""R123", CV_IA64_IntR123, T_UQUAD }, {"\004""R124", CV_IA64_IntR124, T_UQUAD }, {"\004""R125", CV_IA64_IntR125, T_UQUAD }, {"\004""R126", CV_IA64_IntR126, T_UQUAD }, {"\004""R127", CV_IA64_IntR127, T_UQUAD }, {"\005""FZERO", CV_IA64_FltZero, T_REAL80 }, {"\004""FONE", CV_IA64_FltOne, T_REAL80 }, {"\003""FS0", CV_IA64_FltS0, T_REAL80 }, {"\003""FS1", CV_IA64_FltS1, T_REAL80 }, {"\003""FS2", CV_IA64_FltS2, T_REAL80 }, {"\003""FS3", CV_IA64_FltS3, T_REAL80 }, {"\003""FT0", CV_IA64_FltT0, T_REAL80 }, {"\003""FT1", CV_IA64_FltT1, T_REAL80 }, {"\003""FT2", CV_IA64_FltT2, T_REAL80 }, {"\003""FT3", CV_IA64_FltT3, T_REAL80 }, {"\003""FT4", CV_IA64_FltT4, T_REAL80 }, {"\003""FT5", CV_IA64_FltT5, T_REAL80 }, {"\003""FT6", CV_IA64_FltT6, T_REAL80 }, {"\003""FT7", CV_IA64_FltT7, T_REAL80 }, {"\003""FT8", CV_IA64_FltT8, T_REAL80 }, {"\003""FT9", CV_IA64_FltT9, T_REAL80 }, {"\003""FS4", CV_IA64_FltS4, T_REAL80 }, {"\003""FS5", CV_IA64_FltS5, T_REAL80 }, {"\003""FS6", CV_IA64_FltS6, T_REAL80 }, {"\003""FS7", CV_IA64_FltS7, T_REAL80 }, {"\003""FS8", CV_IA64_FltS8, T_REAL80 }, {"\003""FS9", CV_IA64_FltS9, T_REAL80 }, {"\004""FS10", CV_IA64_FltS10, T_REAL80 }, {"\004""FS11", CV_IA64_FltS11, T_REAL80 }, {"\004""FS12", CV_IA64_FltS12, T_REAL80 }, {"\004""FS13", CV_IA64_FltS13, T_REAL80 }, {"\004""FS14", CV_IA64_FltS14, T_REAL80 }, {"\004""FS15", CV_IA64_FltS15, T_REAL80 }, {"\004""FS16", CV_IA64_FltS16, T_REAL80 }, {"\004""FS17", CV_IA64_FltS17, T_REAL80 }, {"\004""FS18", CV_IA64_FltS18, T_REAL80 }, {"\004""FS19", CV_IA64_FltS19, T_REAL80 }, {"\003""F32", CV_IA64_FltF32, T_REAL80 }, {"\003""F33", CV_IA64_FltF33, T_REAL80 }, {"\003""F34", CV_IA64_FltF34, T_REAL80 }, {"\003""F35", CV_IA64_FltF35, T_REAL80 }, {"\003""F36", CV_IA64_FltF36, T_REAL80 }, {"\003""F37", CV_IA64_FltF37, T_REAL80 }, {"\003""F38", CV_IA64_FltF38, T_REAL80 }, {"\003""F39", CV_IA64_FltF39, T_REAL80 }, {"\003""F40", CV_IA64_FltF40, T_REAL80 }, {"\003""F41", CV_IA64_FltF41, T_REAL80 }, {"\003""F42", CV_IA64_FltF42, T_REAL80 }, {"\003""F43", CV_IA64_FltF43, T_REAL80 }, {"\003""F44", CV_IA64_FltF44, T_REAL80 }, {"\003""F45", CV_IA64_FltF45, T_REAL80 }, {"\003""F46", CV_IA64_FltF46, T_REAL80 }, {"\003""F47", CV_IA64_FltF47, T_REAL80 }, {"\003""F48", CV_IA64_FltF48, T_REAL80 }, {"\003""F49", CV_IA64_FltF49, T_REAL80 }, {"\003""F50", CV_IA64_FltF50, T_REAL80 }, {"\003""F51", CV_IA64_FltF51, T_REAL80 }, {"\003""F52", CV_IA64_FltF52, T_REAL80 }, {"\003""F53", CV_IA64_FltF53, T_REAL80 }, {"\003""F54", CV_IA64_FltF54, T_REAL80 }, {"\003""F55", CV_IA64_FltF55, T_REAL80 }, {"\003""F56", CV_IA64_FltF56, T_REAL80 }, {"\003""F57", CV_IA64_FltF57, T_REAL80 }, {"\003""F58", CV_IA64_FltF58, T_REAL80 }, {"\003""F59", CV_IA64_FltF59, T_REAL80 }, {"\003""F60", CV_IA64_FltF60, T_REAL80 }, {"\003""F61", CV_IA64_FltF61, T_REAL80 }, {"\003""F62", CV_IA64_FltF62, T_REAL80 }, {"\003""F63", CV_IA64_FltF63, T_REAL80 }, {"\003""F64", CV_IA64_FltF64, T_REAL80 }, {"\003""F65", CV_IA64_FltF65, T_REAL80 }, {"\003""F66", CV_IA64_FltF66, T_REAL80 }, {"\003""F67", CV_IA64_FltF67, T_REAL80 }, {"\003""F68", CV_IA64_FltF68, T_REAL80 }, {"\003""F69", CV_IA64_FltF69, T_REAL80 }, {"\003""F70", CV_IA64_FltF70, T_REAL80 }, {"\003""F71", CV_IA64_FltF71, T_REAL80 }, {"\003""F72", CV_IA64_FltF72, T_REAL80 }, {"\003""F73", CV_IA64_FltF73, T_REAL80 }, {"\003""F74", CV_IA64_FltF74, T_REAL80 }, {"\003""F75", CV_IA64_FltF75, T_REAL80 }, {"\003""F76", CV_IA64_FltF76, T_REAL80 }, {"\003""F77", CV_IA64_FltF77, T_REAL80 }, {"\003""F78", CV_IA64_FltF78, T_REAL80 }, {"\003""F79", CV_IA64_FltF79, T_REAL80 }, {"\003""F80", CV_IA64_FltF80, T_REAL80 }, {"\003""F81", CV_IA64_FltF81, T_REAL80 }, {"\003""F82", CV_IA64_FltF82, T_REAL80 }, {"\003""F83", CV_IA64_FltF83, T_REAL80 }, {"\003""F84", CV_IA64_FltF84, T_REAL80 }, {"\003""F85", CV_IA64_FltF85, T_REAL80 }, {"\003""F86", CV_IA64_FltF86, T_REAL80 }, {"\003""F87", CV_IA64_FltF87, T_REAL80 }, {"\003""F88", CV_IA64_FltF88, T_REAL80 }, {"\003""F89", CV_IA64_FltF89, T_REAL80 }, {"\003""F90", CV_IA64_FltF90, T_REAL80 }, {"\003""F91", CV_IA64_FltF91, T_REAL80 }, {"\003""F92", CV_IA64_FltF92, T_REAL80 }, {"\003""F93", CV_IA64_FltF93, T_REAL80 }, {"\003""F94", CV_IA64_FltF94, T_REAL80 }, {"\003""F95", CV_IA64_FltF95, T_REAL80 }, {"\003""F96", CV_IA64_FltF96, T_REAL80 }, {"\003""F97", CV_IA64_FltF97, T_REAL80 }, {"\003""F98", CV_IA64_FltF98, T_REAL80 }, {"\003""F99", CV_IA64_FltF99, T_REAL80 }, {"\004""F100", CV_IA64_FltF100, T_REAL80 }, {"\004""F101", CV_IA64_FltF101, T_REAL80 }, {"\004""F102", CV_IA64_FltF102, T_REAL80 }, {"\004""F103", CV_IA64_FltF103, T_REAL80 }, {"\004""F104", CV_IA64_FltF104, T_REAL80 }, {"\004""F105", CV_IA64_FltF105, T_REAL80 }, {"\004""F106", CV_IA64_FltF106, T_REAL80 }, {"\004""F107", CV_IA64_FltF107, T_REAL80 }, {"\004""F108", CV_IA64_FltF108, T_REAL80 }, {"\004""F109", CV_IA64_FltF109, T_REAL80 }, {"\004""F110", CV_IA64_FltF110, T_REAL80 }, {"\004""F111", CV_IA64_FltF111, T_REAL80 }, {"\004""F112", CV_IA64_FltF112, T_REAL80 }, {"\004""F113", CV_IA64_FltF113, T_REAL80 }, {"\004""F114", CV_IA64_FltF114, T_REAL80 }, {"\004""F115", CV_IA64_FltF115, T_REAL80 }, {"\004""F116", CV_IA64_FltF116, T_REAL80 }, {"\004""F117", CV_IA64_FltF117, T_REAL80 }, {"\004""F118", CV_IA64_FltF118, T_REAL80 }, {"\004""F119", CV_IA64_FltF119, T_REAL80 }, {"\004""F120", CV_IA64_FltF120, T_REAL80 }, {"\004""F121", CV_IA64_FltF121, T_REAL80 }, {"\004""F122", CV_IA64_FltF122, T_REAL80 }, {"\004""F123", CV_IA64_FltF123, T_REAL80 }, {"\004""F124", CV_IA64_FltF124, T_REAL80 }, {"\004""F125", CV_IA64_FltF125, T_REAL80 }, {"\004""F126", CV_IA64_FltF126, T_REAL80 }, {"\004""F127", CV_IA64_FltF127, T_REAL80 }, {"\003""KR0", CV_IA64_ApKR0, T_UQUAD }, {"\003""KR1", CV_IA64_ApKR1, T_UQUAD }, {"\003""KR2", CV_IA64_ApKR2, T_UQUAD }, {"\003""KR3", CV_IA64_ApKR3, T_UQUAD }, {"\003""KR4", CV_IA64_ApKR4, T_UQUAD }, {"\003""KR5", CV_IA64_ApKR5, T_UQUAD }, {"\003""KR6", CV_IA64_ApKR6, T_UQUAD }, {"\003""KR7", CV_IA64_ApKR7, T_UQUAD }, {"\003""AR8", CV_IA64_AR8, T_UQUAD }, {"\004""AR90", CV_IA64_AR9, T_UQUAD }, {"\004""AR10", CV_IA64_AR10, T_UQUAD }, {"\004""AR11", CV_IA64_AR11, T_UQUAD }, {"\004""AR12", CV_IA64_AR12, T_UQUAD }, {"\004""AR13", CV_IA64_AR13, T_UQUAD }, {"\004""AR14", CV_IA64_AR14, T_UQUAD }, {"\004""AR15", CV_IA64_AR15, T_UQUAD }, {"\003""RSC", CV_IA64_RsRSC, T_UQUAD }, {"\003""BSP", CV_IA64_RsBSP, T_UQUAD }, {"\007""BSPSTORE", CV_IA64_RsBSPSTORE, T_UQUAD }, {"\004""RNAT", CV_IA64_RsRNAT, T_UQUAD }, {"\004""AR20", CV_IA64_AR20, T_UQUAD }, {"\004""AR21", CV_IA64_AR21, T_UQUAD }, {"\004""AR22", CV_IA64_AR22, T_UQUAD }, {"\004""AR23", CV_IA64_AR23, T_UQUAD }, {"\004""AR24", CV_IA64_AR24, T_UQUAD }, {"\004""AR25", CV_IA64_AR25, T_UQUAD }, {"\004""AR26", CV_IA64_AR26, T_UQUAD }, {"\004""AR27", CV_IA64_AR27, T_UQUAD }, {"\004""AR28", CV_IA64_AR28, T_UQUAD }, {"\004""AR29", CV_IA64_AR29, T_UQUAD }, {"\004""AR30", CV_IA64_AR30, T_UQUAD }, {"\004""AR31", CV_IA64_AR31, T_UQUAD }, {"\003""CCV", CV_IA64_ApCCV, T_UQUAD }, {"\004""AR33", CV_IA64_AR33, T_UQUAD }, {"\004""AR34", CV_IA64_AR34, T_UQUAD }, {"\004""AR35", CV_IA64_AR35, T_UQUAD }, {"\004""UNAT", CV_IA64_ApUNAT, T_UQUAD }, {"\004""AR37", CV_IA64_AR37, T_UQUAD }, {"\004""AR38", CV_IA64_AR38, T_UQUAD }, {"\004""AR39", CV_IA64_AR39, T_UQUAD }, {"\004""FPSR", CV_IA64_StFPSR, T_UQUAD }, {"\004""AR41", CV_IA64_AR41, T_UQUAD }, {"\004""AR42", CV_IA64_AR42, T_UQUAD }, {"\004""AR43", CV_IA64_AR43, T_UQUAD }, {"\003""ITC", CV_IA64_ApITC, T_UQUAD }, {"\004""AR45", CV_IA64_AR45, T_UQUAD }, {"\004""AR46", CV_IA64_AR46, T_UQUAD }, {"\004""AR47", CV_IA64_AR47, T_UQUAD }, {"\004""AR48", CV_IA64_AR48, T_UQUAD }, {"\004""AR49", CV_IA64_AR49, T_UQUAD }, {"\004""AR50", CV_IA64_AR50, T_UQUAD }, {"\004""AR51", CV_IA64_AR51, T_UQUAD }, {"\004""AR52", CV_IA64_AR52, T_UQUAD }, {"\004""AR53", CV_IA64_AR53, T_UQUAD }, {"\004""AR54", CV_IA64_AR54, T_UQUAD }, {"\004""AR55", CV_IA64_AR55, T_UQUAD }, {"\004""AR56", CV_IA64_AR56, T_UQUAD }, {"\004""AR57", CV_IA64_AR57, T_UQUAD }, {"\004""AR58", CV_IA64_AR58, T_UQUAD }, {"\004""AR59", CV_IA64_AR59, T_UQUAD }, {"\004""AR60", CV_IA64_AR60, T_UQUAD }, {"\004""AR61", CV_IA64_AR61, T_UQUAD }, {"\004""AR62", CV_IA64_AR62, T_UQUAD }, {"\004""AR63", CV_IA64_AR63, T_UQUAD }, {"\003""PFS", CV_IA64_RsPFS, T_UQUAD }, {"\002""LC", CV_IA64_ApLC, T_UQUAD }, {"\002""EC", CV_IA64_ApEC, T_UQUAD }, {"\004""AR67", CV_IA64_AR67, T_UQUAD }, {"\004""AR68", CV_IA64_AR68, T_UQUAD }, {"\004""AR69", CV_IA64_AR69, T_UQUAD }, {"\004""AR70", CV_IA64_AR70, T_UQUAD }, {"\004""AR71", CV_IA64_AR71, T_UQUAD }, {"\004""AR72", CV_IA64_AR72, T_UQUAD }, {"\004""AR73", CV_IA64_AR73, T_UQUAD }, {"\004""AR74", CV_IA64_AR74, T_UQUAD }, {"\004""AR75", CV_IA64_AR75, T_UQUAD }, {"\004""AR76", CV_IA64_AR76, T_UQUAD }, {"\004""AR77", CV_IA64_AR77, T_UQUAD }, {"\004""AR78", CV_IA64_AR78, T_UQUAD }, {"\004""AR79", CV_IA64_AR79, T_UQUAD }, {"\004""AR80", CV_IA64_AR80, T_UQUAD }, {"\004""AR81", CV_IA64_AR81, T_UQUAD }, {"\004""AR82", CV_IA64_AR82, T_UQUAD }, {"\004""AR83", CV_IA64_AR83, T_UQUAD }, {"\004""AR84", CV_IA64_AR84, T_UQUAD }, {"\004""AR85", CV_IA64_AR85, T_UQUAD }, {"\004""AR86", CV_IA64_AR86, T_UQUAD }, {"\004""AR87", CV_IA64_AR87, T_UQUAD }, {"\004""AR88", CV_IA64_AR88, T_UQUAD }, {"\004""AR89", CV_IA64_AR89, T_UQUAD }, {"\004""AR90", CV_IA64_AR90, T_UQUAD }, {"\004""AR91", CV_IA64_AR91, T_UQUAD }, {"\004""AR92", CV_IA64_AR92, T_UQUAD }, {"\004""AR93", CV_IA64_AR93, T_UQUAD }, {"\004""AR94", CV_IA64_AR94, T_UQUAD }, {"\004""AR95", CV_IA64_AR95, T_UQUAD }, {"\004""AR96", CV_IA64_AR96, T_UQUAD }, {"\004""AR97", CV_IA64_AR97, T_UQUAD }, {"\004""AR98", CV_IA64_AR98, T_UQUAD }, {"\004""AR99", CV_IA64_AR99, T_UQUAD }, {"\005""AR100", CV_IA64_AR100, T_UQUAD }, {"\005""AR101", CV_IA64_AR101, T_UQUAD }, {"\005""AR102", CV_IA64_AR102, T_UQUAD }, {"\005""AR103", CV_IA64_AR103, T_UQUAD }, {"\005""AR104", CV_IA64_AR104, T_UQUAD }, {"\005""AR105", CV_IA64_AR105, T_UQUAD }, {"\005""AR106", CV_IA64_AR106, T_UQUAD }, {"\005""AR107", CV_IA64_AR107, T_UQUAD }, {"\005""AR108", CV_IA64_AR108, T_UQUAD }, {"\005""AR109", CV_IA64_AR109, T_UQUAD }, {"\005""AR110", CV_IA64_AR110, T_UQUAD }, {"\005""AR111", CV_IA64_AR111, T_UQUAD }, {"\005""AR112", CV_IA64_AR112, T_UQUAD }, {"\005""AR113", CV_IA64_AR113, T_UQUAD }, {"\005""AR114", CV_IA64_AR114, T_UQUAD }, {"\005""AR115", CV_IA64_AR115, T_UQUAD }, {"\005""AR116", CV_IA64_AR116, T_UQUAD }, {"\005""AR117", CV_IA64_AR117, T_UQUAD }, {"\005""AR118", CV_IA64_AR118, T_UQUAD }, {"\005""AR119", CV_IA64_AR119, T_UQUAD }, {"\005""AR120", CV_IA64_AR120, T_UQUAD }, {"\005""AR121", CV_IA64_AR121, T_UQUAD }, {"\005""AR122", CV_IA64_AR122, T_UQUAD }, {"\005""AR123", CV_IA64_AR123, T_UQUAD }, {"\005""AR124", CV_IA64_AR124, T_UQUAD }, {"\005""AR125", CV_IA64_AR125, T_UQUAD }, {"\005""AR126", CV_IA64_AR126, T_UQUAD }, {"\005""AR127", CV_IA64_AR127, T_UQUAD }, {"\003""DCR", CV_IA64_ApDCR, T_UQUAD }, {"\003""ITM", CV_IA64_ApITM, T_UQUAD }, {"\003""IVA", CV_IA64_ApIVA, T_UQUAD }, {"\003""CR3", CV_IA64_CR3, T_UQUAD }, {"\003""CR4", CV_IA64_CR4, T_UQUAD }, {"\003""CR5", CV_IA64_CR5, T_UQUAD }, {"\003""CR6", CV_IA64_CR6, T_UQUAD }, {"\003""CR7", CV_IA64_CR7, T_UQUAD }, {"\003""PTA", CV_IA64_ApPTA, T_UQUAD }, {"\003""CR9", CV_IA64_CR9, T_UQUAD }, {"\004""CR10", CV_IA64_CR10, T_UQUAD }, {"\004""CR11", CV_IA64_CR11, T_UQUAD }, {"\004""CR12", CV_IA64_CR12, T_UQUAD }, {"\004""CR13", CV_IA64_CR13, T_UQUAD }, {"\004""CR14", CV_IA64_CR14, T_UQUAD }, {"\004""CR15", CV_IA64_CR15, T_UQUAD }, {"\004""IPSR", CV_IA64_StIPSR, T_UQUAD }, {"\003""ISR ", CV_IA64_StISR, T_UQUAD }, {"\003""IDA", CV_IA64_StIDA, T_UQUAD }, {"\003""IIP", CV_IA64_StIIP, T_UQUAD }, {"\004""IDTR", CV_IA64_StIDTR, T_UQUAD }, {"\004""IITR", CV_IA64_StIITR, T_UQUAD }, {"\004""IIPA", CV_IA64_StIIPA, T_UQUAD }, {"\003""IFS", CV_IA64_StIFS, T_UQUAD }, {"\003""IIM", CV_IA64_StIIM, T_UQUAD }, {"\003""IHA", CV_IA64_StIHA, T_UQUAD }, {"\004""CR26", CV_IA64_CR26, T_UQUAD }, {"\004""CR27", CV_IA64_CR27, T_UQUAD }, {"\004""CR28", CV_IA64_CR28, T_UQUAD }, {"\004""CR29", CV_IA64_CR29, T_UQUAD }, {"\004""CR30", CV_IA64_CR30, T_UQUAD }, {"\004""CR31", CV_IA64_CR31, T_UQUAD }, {"\004""CR32", CV_IA64_CR32, T_UQUAD }, {"\004""CR33", CV_IA64_CR33, T_UQUAD }, {"\004""CR34", CV_IA64_CR34, T_UQUAD }, {"\004""CR35", CV_IA64_CR35, T_UQUAD }, {"\004""CR36", CV_IA64_CR36, T_UQUAD }, {"\004""CR37", CV_IA64_CR37, T_UQUAD }, {"\004""CR38", CV_IA64_CR38, T_UQUAD }, {"\004""CR39", CV_IA64_CR39, T_UQUAD }, {"\004""CR40", CV_IA64_CR40, T_UQUAD }, {"\004""CR41", CV_IA64_CR41, T_UQUAD }, {"\004""CR42", CV_IA64_CR42, T_UQUAD }, {"\004""CR43", CV_IA64_CR43, T_UQUAD }, {"\004""CR44", CV_IA64_CR44, T_UQUAD }, {"\004""CR45", CV_IA64_CR45, T_UQUAD }, {"\004""CR46", CV_IA64_CR46, T_UQUAD }, {"\004""CR47", CV_IA64_CR47, T_UQUAD }, {"\004""CR48", CV_IA64_CR48, T_UQUAD }, {"\004""CR49", CV_IA64_CR49, T_UQUAD }, {"\004""CR50", CV_IA64_CR50, T_UQUAD }, {"\004""CR51", CV_IA64_CR51, T_UQUAD }, {"\004""CR52", CV_IA64_CR52, T_UQUAD }, {"\004""CR53", CV_IA64_CR53, T_UQUAD }, {"\004""CR54", CV_IA64_CR54, T_UQUAD }, {"\004""CR55", CV_IA64_CR55, T_UQUAD }, {"\004""CR56", CV_IA64_CR56, T_UQUAD }, {"\004""CR57", CV_IA64_CR57, T_UQUAD }, {"\004""CR58", CV_IA64_CR58, T_UQUAD }, {"\004""CR59", CV_IA64_CR59, T_UQUAD }, {"\004""CR60", CV_IA64_CR60, T_UQUAD }, {"\004""CR61", CV_IA64_CR61, T_UQUAD }, {"\004""CR62", CV_IA64_CR62, T_UQUAD }, {"\004""CR63", CV_IA64_CR63, T_UQUAD }, {"\004""CR64", CV_IA64_CR64, T_UQUAD }, {"\004""CR65", CV_IA64_CR65, T_UQUAD }, {"\003""LID ", CV_IA64_SaLID, T_UQUAD }, {"\004""CR67", CV_IA64_CR67, T_UQUAD }, {"\004""CR68", CV_IA64_CR68, T_UQUAD }, {"\004""CR69", CV_IA64_CR69, T_UQUAD }, {"\004""CR70", CV_IA64_CR70, T_UQUAD }, {"\003""IVR ", CV_IA64_SaIVR, T_UQUAD }, {"\003""TPR ", CV_IA64_SaTPR, T_UQUAD }, {"\004""CR73", CV_IA64_CR73, T_UQUAD }, {"\004""CR74", CV_IA64_CR74, T_UQUAD }, {"\003""EOI ", CV_IA64_SaEOI, T_UQUAD }, {"\004""CR76", CV_IA64_CR76, T_UQUAD }, {"\004""CR77", CV_IA64_CR77, T_UQUAD }, {"\004""CR78", CV_IA64_CR78, T_UQUAD }, {"\004""CR79", CV_IA64_CR79, T_UQUAD }, {"\004""CR80", CV_IA64_CR80, T_UQUAD }, {"\004""CR81", CV_IA64_CR81, T_UQUAD }, {"\004""CR82", CV_IA64_CR82, T_UQUAD }, {"\004""CR83", CV_IA64_CR83, T_UQUAD }, {"\004""CR84", CV_IA64_CR84, T_UQUAD }, {"\004""CR85", CV_IA64_CR85, T_UQUAD }, {"\004""CR86", CV_IA64_CR86, T_UQUAD }, {"\004""CR87", CV_IA64_CR87, T_UQUAD }, {"\004""CR88", CV_IA64_CR88, T_UQUAD }, {"\004""CR89", CV_IA64_CR89, T_UQUAD }, {"\004""CR90", CV_IA64_CR90, T_UQUAD }, {"\004""CR91", CV_IA64_CR91, T_UQUAD }, {"\004""CR92", CV_IA64_CR92, T_UQUAD }, {"\004""CR93", CV_IA64_CR93, T_UQUAD }, {"\004""CR94", CV_IA64_CR94, T_UQUAD }, {"\004""CR95", CV_IA64_CR95, T_UQUAD }, {"\004""IRR0", CV_IA64_SaIRR0, T_UQUAD }, {"\004""CR97", CV_IA64_CR97, T_UQUAD }, {"\004""IRR1", CV_IA64_SaIRR1, T_UQUAD }, {"\004""CR99", CV_IA64_CR99, T_UQUAD }, {"\004""IRR2", CV_IA64_SaIRR2, T_UQUAD }, {"\005""CR101", CV_IA64_CR101, T_UQUAD }, {"\004""IRR3", CV_IA64_SaIRR3, T_UQUAD }, {"\005""CR103", CV_IA64_CR103, T_UQUAD }, {"\005""CR104", CV_IA64_CR104, T_UQUAD }, {"\005""CR105", CV_IA64_CR105, T_UQUAD }, {"\005""CR106", CV_IA64_CR106, T_UQUAD }, {"\005""CR107", CV_IA64_CR107, T_UQUAD }, {"\005""CR108", CV_IA64_CR108, T_UQUAD }, {"\005""CR109", CV_IA64_CR109, T_UQUAD }, {"\005""CR110", CV_IA64_CR110, T_UQUAD }, {"\005""CR111", CV_IA64_CR111, T_UQUAD }, {"\005""CR112", CV_IA64_CR112, T_UQUAD }, {"\005""CR113", CV_IA64_CR113, T_UQUAD }, {"\003""ITV", CV_IA64_SaITV, T_UQUAD }, {"\005""CR115", CV_IA64_CR115, T_UQUAD }, {"\003""PMV", CV_IA64_SaPMV, T_UQUAD }, {"\004""LRR0", CV_IA64_SaLRR0, T_UQUAD }, {"\004""LRR1", CV_IA64_SaLRR1, T_UQUAD }, {"\004""CMCV", CV_IA64_SaCMCV, T_UQUAD }, {"\005""CR120", CV_IA64_CR120, T_UQUAD }, {"\005""CR121", CV_IA64_CR121, T_UQUAD }, {"\005""CR122", CV_IA64_CR122, T_UQUAD }, {"\005""CR123", CV_IA64_CR123, T_UQUAD }, {"\005""CR124", CV_IA64_CR124, T_UQUAD }, {"\005""CR125", CV_IA64_CR125, T_UQUAD }, {"\005""CR126", CV_IA64_CR126, T_UQUAD }, {"\005""CR127", CV_IA64_CR127, T_UQUAD }, {"\004""PKR0", CV_IA64_Pkr0 , T_UQUAD }, {"\004""PKR1", CV_IA64_Pkr1 , T_UQUAD }, {"\004""PKR2", CV_IA64_Pkr2 , T_UQUAD }, {"\004""PKR3", CV_IA64_Pkr3 , T_UQUAD }, {"\004""PKR4", CV_IA64_Pkr4 , T_UQUAD }, {"\004""PKR5", CV_IA64_Pkr5 , T_UQUAD }, {"\004""PKR6", CV_IA64_Pkr6 , T_UQUAD }, {"\004""PKR7", CV_IA64_Pkr7 , T_UQUAD }, {"\004""PKR8", CV_IA64_Pkr8 , T_UQUAD }, {"\004""PKR9", CV_IA64_Pkr9 , T_UQUAD }, {"\005""PKR10", CV_IA64_Pkr10, T_UQUAD }, {"\005""PKR11", CV_IA64_Pkr11, T_UQUAD }, {"\005""PKR12", CV_IA64_Pkr12, T_UQUAD }, {"\005""PKR13", CV_IA64_Pkr13, T_UQUAD }, {"\005""PKR14", CV_IA64_Pkr14, T_UQUAD }, {"\005""PKR15", CV_IA64_Pkr15, T_UQUAD }, {"\003""RR0", CV_IA64_Rr0, T_UQUAD }, {"\003""RR1", CV_IA64_Rr1, T_UQUAD }, {"\003""RR2", CV_IA64_Rr2, T_UQUAD }, {"\003""RR3", CV_IA64_Rr3, T_UQUAD }, {"\003""RR4", CV_IA64_Rr4, T_UQUAD }, {"\003""RR5", CV_IA64_Rr5, T_UQUAD }, {"\003""RR6", CV_IA64_Rr6, T_UQUAD }, {"\003""RR7", CV_IA64_Rr7, T_UQUAD }, {"\004""PFD0", CV_IA64_PFD0, T_UQUAD }, {"\004""PFD1", CV_IA64_PFD1, T_UQUAD }, {"\004""PFD2", CV_IA64_PFD2, T_UQUAD }, {"\004""PFD3", CV_IA64_PFD3, T_UQUAD }, {"\004""PFD4", CV_IA64_PFD4, T_UQUAD }, {"\004""PFD5", CV_IA64_PFD5, T_UQUAD }, {"\004""PFD6", CV_IA64_PFD6, T_UQUAD }, {"\004""PFD7", CV_IA64_PFD7, T_UQUAD }, {"\004""PFC0", CV_IA64_PFC0, T_UQUAD }, {"\004""PFC1", CV_IA64_PFC1, T_UQUAD }, {"\004""PFC2", CV_IA64_PFC2, T_UQUAD }, {"\004""PFC3", CV_IA64_PFC3, T_UQUAD }, {"\004""PFC4", CV_IA64_PFC4, T_UQUAD }, {"\004""PFC5", CV_IA64_PFC5, T_UQUAD }, {"\004""PFC6", CV_IA64_PFC6, T_UQUAD }, {"\004""PFC7", CV_IA64_PFC7, T_UQUAD }, {"\004""TRI0", CV_IA64_TrI0, T_UQUAD }, {"\004""TRI1", CV_IA64_TrI1, T_UQUAD }, {"\004""TRI2", CV_IA64_TrI2, T_UQUAD }, {"\004""TRI3", CV_IA64_TrI3, T_UQUAD }, {"\004""TRI4", CV_IA64_TrI4, T_UQUAD }, {"\004""TRI5", CV_IA64_TrI5, T_UQUAD }, {"\004""TRI6", CV_IA64_TrI6, T_UQUAD }, {"\004""TRI7", CV_IA64_TrI7, T_UQUAD }, {"\004""TRD0", CV_IA64_TrD0, T_UQUAD }, {"\004""TRD1", CV_IA64_TrD1, T_UQUAD }, {"\004""TRD2", CV_IA64_TrD2, T_UQUAD }, {"\004""TRD3", CV_IA64_TrD3, T_UQUAD }, {"\004""TRD4", CV_IA64_TrD4, T_UQUAD }, {"\004""TRD5", CV_IA64_TrD5, T_UQUAD }, {"\004""TRD6", CV_IA64_TrD6, T_UQUAD }, {"\004""TRD7", CV_IA64_TrD7, T_UQUAD }, {"\004""DBI0", CV_IA64_DbI0, T_UQUAD }, {"\004""DBI1", CV_IA64_DbI1, T_UQUAD }, {"\004""DBI2", CV_IA64_DbI2, T_UQUAD }, {"\004""DBI3", CV_IA64_DbI3, T_UQUAD }, {"\004""DBI4", CV_IA64_DbI4, T_UQUAD }, {"\004""DBI5", CV_IA64_DbI5, T_UQUAD }, {"\004""DBI6", CV_IA64_DbI6, T_UQUAD }, {"\004""DBI7", CV_IA64_DbI7, T_UQUAD }, {"\004""DBD0", CV_IA64_DbD0, T_UQUAD }, {"\004""DBD1", CV_IA64_DbD1, T_UQUAD }, {"\004""DBD2", CV_IA64_DbD2, T_UQUAD }, {"\004""DBD3", CV_IA64_DbD3, T_UQUAD }, {"\004""DBD4", CV_IA64_DbD4, T_UQUAD }, {"\004""DBD5", CV_IA64_DbD5, T_UQUAD }, {"\004""DBD6", CV_IA64_DbD6, T_UQUAD }, {"\004""DBD7", CV_IA64_DbD7, T_UQUAD } }; #define REGCNT_X86 (sizeof (hreg_list_x86)/sizeof (struct hreg_x86)) #define REGCNT_MIP (sizeof (hreg_list_mip)/sizeof (struct hreg_mip)) #define REGCNT_AXP (sizeof (hreg_list_axp)/sizeof (struct hreg_axp)) #define REGCNT_PPC (sizeof (hreg_list_ppc)/sizeof (struct hreg_ppc)) #define REGCNT_68K (sizeof (hreg_list_68k)/sizeof (struct hreg_68k)) #define REGCNT_IA64 (sizeof (hreg_list_ia64)/sizeof (struct hreg_ia64)) bool_t ParseRegister ( psearch_t pName ) { int i; peval_t pv; if (*pName->sstr.lpName == '@') { pName->sstr.lpName++; pName->sstr.cb--; } pv = pName->pv; switch (TargetMachine) { case mptmips: for (i = 0; i < REGCNT_MIP; i++) { if (fnCmp (pName, NULL, hreg_list_mip[i].name, FALSE) == 0) break; } if (i >= REGCNT_MIP) { return (HR_notfound); } EVAL_REG (pv) = hreg_list_mip[i].index; SetNodeType (pv, hreg_list_mip[i].type); EVAL_IS_HIBYTE (pv) = FALSE; break; case mptix86: for (i = 0; i < REGCNT_X86; i++) { if (fnCmp (pName, NULL, hreg_list_x86[i].name, FALSE) == 0) break; } if ((i >= REGCNT_X86) || (!(hreg_list_x86[i].valid & VALIDx86) && !in386mode)) { return (HR_notfound); } EVAL_REG (pv) = hreg_list_x86[i].index; SetNodeType (pv, hreg_list_x86[i].type); EVAL_IS_HIBYTE (pv) = ((hreg_list_x86[i].valid & REGHI) == REGHI); break; case mptia64: for (i = 0; i < REGCNT_IA64; i++) { if (fnCmp (pName, NULL, hreg_list_ia64[i].name, FALSE) == 0) break; } if (i >= REGCNT_IA64) { return (HR_notfound); } EVAL_REG (pv) = hreg_list_ia64[i].index; SetNodeType (pv, hreg_list_ia64[i].type); EVAL_IS_HIBYTE (pv) = FALSE; break; case mptdaxp: for (i = 0; i < REGCNT_AXP; i++) { if (fnCmp (pName, NULL, hreg_list_axp[i].name, FALSE) == 0) break; } if (i >= REGCNT_AXP) { return (HR_notfound); } EVAL_REG (pv) = hreg_list_axp[i].index; SetNodeType (pv, hreg_list_axp[i].type); EVAL_IS_HIBYTE (pv) = FALSE; break; case mptmppc: case mptntppc: for (i = 0; i < REGCNT_PPC; i++) { if (fnCmp (pName, NULL, hreg_list_ppc[i].name, FALSE) == 0) break; } if (i >= REGCNT_PPC) { return (HR_notfound); } EVAL_REG (pv) = hreg_list_ppc[i].index; SetNodeType (pv, hreg_list_ppc[i].type); EVAL_IS_HIBYTE (pv) = FALSE; break; case mptm68k: for (i = 0; i < REGCNT_68K; i++) { if (fnCmp (pName, NULL, hreg_list_68k[i].name, FALSE) == 0) break; } if (i >= REGCNT_68K) { return (HR_notfound); } EVAL_REG (pv) = hreg_list_68k[i].index; SetNodeType (pv, hreg_list_68k[i].type); EVAL_IS_HIBYTE (pv) = FALSE; break; default: DASSERT(FALSE); } EVAL_IS_REG (pv) = TRUE; EVAL_STATE (pv) = EV_lvalue; PushStack (pv); return (HR_found); } bool_t LineNumber ( psearch_t pName ) { uchar *pb = pName->sstr.lpName + 1; uint i; char c; ulong val = 0; //FLS fls; HSF hsf; ADDR addr; SHOFF cbLine; peval_t pv; // convert line number for (i = pName->sstr.cb - 1; i > 0; i--) { c = *pb; if (!_istdigit ((_TUCHAR)c)) { // Must have reached the end pExState->err_num = ERR_LINENUMBER; return (HR_error); } val *= 10; val += (c - '0'); if (val > 0xffff) { // Must have overflowed pExState->err_num = ERR_LINENUMBER; return (HR_error); } pb++; } if ( (hsf = SLHsfFromPcxt ( pCxt ) ) && SLFLineToAddr ( hsf, (WORD) val, &addr, &cbLine, NULL ) ) { pv = pName->pv; if ( ADDR_IS_OFF32 ( addr ) ) { SetNodeType (pv, T_32PVOID); } else { SetNodeType (pv, T_PFVOID); } EVAL_IS_LABEL (pv) = TRUE; EVAL_STATE (pv) = EV_rvalue; EVAL_SYM (pv) = addr; EVAL_PTR (pv) = addr; PushStack (pv); return (HR_found); } else { pExState->err_num = ERR_NOCODE; return (HR_error); } pExState->err_num = ERR_BADCONTEXT; return (HR_error); } /** InsertThis - rewrite bind tree to add this-> * fSuccess = InsertThis (pName); * Entry pName = pointer to search structure * Exit tree rewritten such that the node pn becomes OP_pointsto * with the left node being OP_this and the right node being * the original symbol * Returns TRUE if tree rewritten * FALSE if error */ bool_t FASTCALL InsertThis ( psearch_t pName ) { ulong len = 2 * (sizeof (node_t) + sizeof (eval_t)); ulong Left; ulong Right; pnode_t pn; bnode_t bn = pName->bn; Left = pTree->node_next; Right = Left + sizeof (node_t) + sizeof (eval_t); if ((pTree->size - Left) < len) { if (!GrowETree (len)) { NOTTESTED (FALSE); pExState->err_num = ERR_NOMEMORY; return (FALSE); } if (bnCxt != 0) { // the context was pointing into the expression tree. // since the expression tree could have been reallocated, // we must recompute the context pointer pCxt = SHpCXTFrompCXF ((PCXF)&((pnode_t)bnCxt)->v[0]); } } // copy symbol to right node memcpy ((pnode_t)((bnode_t)Right), (pnode_t)bn, sizeof (node_t) + sizeof (eval_t)); // insert OP_this node as left node pn = (pnode_t)((bnode_t)Left); memset (pn, 0, sizeof (node_t) + sizeof (eval_t)); NODE_OP (pn) = OP_this; // change original node to OP_pointsto pn = (pnode_t)bn; memset (pn, 0, sizeof (node_t) + sizeof (eval_t)); NODE_OP (pn) = OP_pointsto; NODE_LCHILD (pn) = (bnode_t)Left; NODE_RCHILD (pn) = (bnode_t)Right; pTree->node_next += len; return (TRUE); } /* * load a constant symbol into a node. */ bool_t DebLoadConst ( peval_t pv, CONSTPTR pSym, HSYM hSym ) { uint skip = 0; CV_typ_t type; HTYPE hType; plfEnum pEnum; type = pSym->typind; if (!CV_IS_PRIMITIVE (type)) { // we also allow constants that are enumeration values, so check // that the non-primitive type is an enumeration and set the type // to the underlying type of the enum MHOmfUnLock (hSym); hType = THGetTypeFromIndex (EVAL_MOD (pv), type); if (hType == 0) { DASSERT (FALSE); pSym = (CONSTPTR) MHOmfLock (hSym); pExState->err_num = ERR_BADOMF; return (FALSE); } pEnum = (plfEnum)(&((TYPPTR)(MHOmfLock (hType)))->leaf); if ((pEnum->leaf != LF_ENUM) || !CV_IS_PRIMITIVE (pEnum->utype)) { DASSERT (FALSE); MHOmfUnLock (hType); pSym = (CONSTPTR) MHOmfLock (hSym); pExState->err_num = ERR_BADOMF; return (FALSE); } MHOmfUnLock (hType); pSym = (CONSTPTR) MHOmfLock (hSym); SetNodeType (pv, type); // SetNodeType will resolve forward ref Enums - but we need to get the // utype from the pv when this happens - sps type = ENUM_UTYPE (pv); } else { SetNodeType (pv, type); } EVAL_STATE (pv) = EV_rvalue; if ((CV_MODE (type) != CV_TM_DIRECT) || ((CV_TYPE (type) != CV_SIGNED) && (CV_TYPE (type) != CV_UNSIGNED) && (CV_TYPE (type) != CV_INT))) { DASSERT (FALSE); pExState->err_num = ERR_BADOMF; return (FALSE); } EVAL_UQUAD (pv) = RNumLeaf (&pSym->value, &skip); return (TRUE); } /** fValidInProlog - check if local symbol is valid in the func. prolog * flag = fValidInProlog (hSym, fNoFrame) * Entry hSym = handle to local symbol * Exit none * Returns TRUE if hSym is valid * FALSE if hSym is rejectable * A local symbol is rejectable in the prolog if it is a bp-relative * or register item (since the new frame has not been set up yet) * However formal arguments (e.g., bp-relative symbols with +ve * offset) are not rejectable since they are already on the stack. * We let such symbols bind properly during the evaluation phase * the frame passed by the kernel contains a virtual bp value that * points to the right address on the stack. * NOTE: If the frame is indicated as not available then the symbol * is an argument or parameter. Only labels and the like are * valid without a frame... */ bool_t fValidInProlog ( HSYM hSym, bool_t fNoFrame ) { SYMPTR pSym = (SYMPTR) MHOmfLock (hSym); bool_t retval; switch (pSym->rectyp) { case S_BPREL16: retval = !fNoFrame && (((BPRELPTR16)pSym)->off >= 0); break; case S_BPREL32: retval = !fNoFrame && (((BPRELPTR32)pSym)->off >= 0); break; case S_REGREL32: if (TargetMachine == mptmips) { // All offsets are SP relative not FP. retval = (((LPREGREL32)pSym)->reg != CV_M4_IntSP) && (((LPREGREL32)pSym)->reg != CV_M4_IntS8); } else { retval = !fNoFrame && (((LPREGREL32)pSym)->off >= 0); } break; case S_REGISTER: if (fNoFrame) return FALSE; switch (((REGPTR)pSym)->reg) { case CV_REG_ECX: case CV_REG_EDX: // These registers are used for fastcall arguments retval = TRUE; break; default: retval = FALSE; } break; default: // non bp-rel, non reg-rel, non-register symbols // are always considered bindable during prolog retval = TRUE; } MHOmfUnLock (hSym); return retval; }