Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #3
0
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, ")");
}
Beispiel #4
0
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);
    }
}
Beispiel #5
0
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;
}