int IsVariadicFunc (const Type* T) /* Return true if this is a function type or pointer to function type with ** variable parameter list */ { FuncDesc* F = GetFuncDesc (T); return (F->Flags & FD_VARIADIC) != 0; }
static Function* NewFunction (struct SymEntry* Sym) /* Create a new function activation structure and return it */ { /* Allocate a new structure */ Function* F = (Function*) xmalloc (sizeof (Function)); /* Initialize the fields */ F->FuncEntry = Sym; F->ReturnType = GetFuncReturn (Sym->Type); F->Desc = GetFuncDesc (Sym->Type); F->Reserved = 0; F->RetLab = GetLocalLabel (); F->TopLevelSP = 0; F->RegOffs = RegisterSpace; F->Flags = IsTypeVoid (F->ReturnType) ? FF_VOID_RETURN : FF_NONE; /* Return the new structure */ return F; }
void PrintFuncSig (FILE* F, const char* Name, Type* T) /* Print a function signature. */ { /* Get the function descriptor */ const FuncDesc* D = GetFuncDesc (T); /* Print a comment with the function signature */ PrintType (F, GetFuncReturn (T)); if (IsQualNear (T)) { fprintf (F, " __near__"); } if (IsQualFar (T)) { fprintf (F, " __far__"); } if (IsQualFastcall (T)) { fprintf (F, " __fastcall__"); } if (IsQualCDecl (T)) { fprintf (F, " __cdecl__"); } fprintf (F, " %s (", Name); /* Parameters */ if (D->Flags & FD_VOID_PARAM) { fprintf (F, "void"); } else { unsigned I; SymEntry* E = D->SymTab->SymHead; for (I = 0; I < D->ParamCount; ++I) { if (I > 0) { fprintf (F, ", "); } if (SymIsRegVar (E)) { fprintf (F, "register "); } PrintType (F, E->Type); E = E->NextSym; } } /* End of parameter list */ fprintf (F, ")"); }
static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) /* Recursively compare two types. */ { unsigned Indirections; unsigned ElementCount; SymEntry* Sym1; SymEntry* Sym2; SymTable* Tab1; SymTable* Tab2; FuncDesc* F1; FuncDesc* F2; /* Initialize stuff */ Indirections = 0; ElementCount = 0; /* Compare two types. Determine, where they differ */ while (lhs->C != T_END) { TypeCode LeftType, RightType; TypeCode LeftSign, RightSign; TypeCode LeftQual, RightQual; long LeftCount, RightCount; /* Check if the end of the type string is reached */ if (rhs->C == T_END) { /* End of comparison reached */ return; } /* Get the raw left and right types, signs and qualifiers */ LeftType = GetType (lhs); RightType = GetType (rhs); LeftSign = GetSignedness (lhs); RightSign = GetSignedness (rhs); LeftQual = GetQualifier (lhs); RightQual = GetQualifier (rhs); /* If the left type is a pointer and the right is an array, both ** are compatible. */ if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) { RightType = T_TYPE_PTR; } /* If the raw types are not identical, the types are incompatible */ if (LeftType != RightType) { SetResult (Result, TC_INCOMPATIBLE); return; } /* On indirection level zero, a qualifier or sign difference is ** accepted. The types are no longer equal, but compatible. */ if (LeftSign != RightSign) { if (ElementCount == 0) { SetResult (Result, TC_SIGN_DIFF); } else { SetResult (Result, TC_INCOMPATIBLE); return; } } if (LeftQual != RightQual) { /* On the first indirection level, different qualifiers mean ** that the types are still compatible. On the second level, ** this is a (maybe minor) error, so we create a special ** return code, since a qualifier is dropped from a pointer. ** Starting from the next level, the types are incompatible ** if the qualifiers differ. */ /* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */ switch (Indirections) { case 0: SetResult (Result, TC_STRICT_COMPATIBLE); break; case 1: /* A non const value on the right is compatible to a ** const one to the left, same for volatile. */ if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) || (LeftQual & T_QUAL_VOLATILE) < (RightQual & T_QUAL_VOLATILE)) { SetResult (Result, TC_QUAL_DIFF); } else { SetResult (Result, TC_STRICT_COMPATIBLE); } break; default: SetResult (Result, TC_INCOMPATIBLE); return; } } /* Check for special type elements */ switch (LeftType) { case T_TYPE_PTR: ++Indirections; break; case T_TYPE_FUNC: /* Compare the function descriptors */ F1 = GetFuncDesc (lhs); F2 = GetFuncDesc (rhs); /* If one of both functions has an empty parameter list (which ** does also mean, it is not a function definition, because the ** flag is reset in this case), it is considered equal to any ** other definition, provided that the other has no default ** promotions in the parameter list. If none of both parameter ** lists is empty, we have to check the parameter lists and ** other attributes. */ if (F1->Flags & FD_EMPTY) { if ((F2->Flags & FD_EMPTY) == 0) { if (ParamsHaveDefaultPromotions (F2)) { /* Flags differ */ SetResult (Result, TC_INCOMPATIBLE); return; } } } else if (F2->Flags & FD_EMPTY) { if (ParamsHaveDefaultPromotions (F1)) { /* Flags differ */ SetResult (Result, TC_INCOMPATIBLE); return; } } else { /* Check the remaining flags */ if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) { /* Flags differ */ SetResult (Result, TC_INCOMPATIBLE); return; } /* Compare the parameter lists */ if (EqualFuncParams (F1, F2) == 0) { /* Parameter list is not identical */ SetResult (Result, TC_INCOMPATIBLE); return; } } /* Keep on and compare the return type */ break; case T_TYPE_ARRAY: /* Check member count */ LeftCount = GetElementCount (lhs); RightCount = GetElementCount (rhs); if (LeftCount != UNSPECIFIED && RightCount != UNSPECIFIED && LeftCount != RightCount) { /* Member count given but different */ SetResult (Result, TC_INCOMPATIBLE); return; } break; case T_TYPE_STRUCT: case T_TYPE_UNION: /* Compare the fields recursively. To do that, we fetch the ** pointer to the struct definition from the type, and compare ** the fields. */ Sym1 = GetSymEntry (lhs); Sym2 = GetSymEntry (rhs); /* If one symbol has a name, the names must be identical */ if (!HasAnonName (Sym1) || !HasAnonName (Sym2)) { if (strcmp (Sym1->Name, Sym2->Name) != 0) { /* Names are not identical */ SetResult (Result, TC_INCOMPATIBLE); return; } } /* Get the field tables from the struct entry */ Tab1 = Sym1->V.S.SymTab; Tab2 = Sym2->V.S.SymTab; /* One or both structs may be forward definitions. In this case, ** the symbol tables are both non existant. Assume that the ** structs are equal in this case. */ if (Tab1 != 0 && Tab2 != 0) { if (EqualSymTables (Tab1, Tab2) == 0) { /* Field lists are not equal */ SetResult (Result, TC_INCOMPATIBLE); return; } } /* Structs are equal */ break; } /* Next type string element */ ++lhs; ++rhs; ++ElementCount; } /* Check if end of rhs reached */ if (rhs->C == T_END) { SetResult (Result, TC_EQUAL); } else { SetResult (Result, TC_INCOMPATIBLE); } }
SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) /* Add an external or global symbol to the symbol table and return the entry */ { /* There is some special handling for functions, so check if it is one */ int IsFunc = IsTypeFunc (T); /* Functions must be inserted in the global symbol table */ SymTable* Tab = IsFunc? SymTab0 : SymTab; /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); if (Entry) { Type* EType; /* We have a symbol with this name already */ if (Entry->Flags & SC_TYPE) { Error ("Multiple definition for `%s'", Name); return Entry; } /* Get the type string of the existing symbol */ EType = Entry->Type; /* If we are handling arrays, the old entry or the new entry may be an ** incomplete declaration. Accept this, and if the exsting entry is ** incomplete, complete it. */ if (IsTypeArray (T) && IsTypeArray (EType)) { /* Get the array sizes */ long Size = GetElementCount (T); long ESize = GetElementCount (EType); if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) || TypeCmp (T + 1, EType + 1) < TC_EQUAL) { /* Types not identical: Conflicting types */ Error ("Conflicting types for `%s'", Name); return Entry; } else { /* Check if we have a size in the existing definition */ if (ESize == UNSPECIFIED) { /* Existing, size not given, use size from new def */ SetElementCount (EType, Size); } } } else { /* New type must be identical */ if (TypeCmp (EType, T) < TC_EQUAL) { Error ("Conflicting types for `%s'", Name); return Entry; } /* In case of a function, use the new type descriptor, since it ** contains pointers to the new symbol tables that are needed if ** an actual function definition follows. Be sure not to use the ** new descriptor if it contains a function declaration with an ** empty parameter list. */ if (IsFunc) { /* Get the function descriptor from the new type */ FuncDesc* F = GetFuncDesc (T); /* Use this new function descriptor if it doesn't contain ** an empty parameter list. */ if ((F->Flags & FD_EMPTY) == 0) { Entry->V.F.Func = F; SetFuncDesc (EType, F); } } } /* Add the new flags */ Entry->Flags |= Flags; } else { /* Create a new entry */ Entry = NewSymEntry (Name, Flags); /* Set the symbol attributes */ Entry->Type = TypeDup (T); /* If this is a function, set the function descriptor and clear ** additional fields. */ if (IsFunc) { Entry->V.F.Func = GetFuncDesc (Entry->Type); Entry->V.F.Seg = 0; } /* Add the assembler name of the symbol */ SymSetAsmName (Entry); /* Add the entry to the symbol table */ AddSymEntry (Tab, Entry); } /* Return the entry */ return Entry; }