Beispiel #1
0
void InsertObjGlobals (ObjData* O)
/* Insert imports and exports from the object file into the global import and
 * export lists.
 */
{
    unsigned I;

    /* Insert exports and imports */
    for (I = 0; I < CollCount (&O->Exports); ++I) {
        InsertExport (CollAt (&O->Exports, I));
    }
    for (I = 0; I < CollCount (&O->Imports); ++I) {
        InsertImport (CollAt (&O->Imports, I));
    }
}
Beispiel #2
0
void CS_DelLabel (CodeSeg* S, CodeLabel* L)
/* Remove references from this label and delete it. */
{
    unsigned Count, I;

    /* First, remove the label from the hash chain */
    CS_RemoveLabelFromHash (S, L);

    /* Remove references from insns jumping to this label */
    Count = CollCount (&L->JumpFrom);
    for (I = 0; I < Count; ++I) {
       	/* Get the insn referencing this label */
       	CodeEntry* E = CollAt (&L->JumpFrom, I);
       	/* Remove the reference */
       	CE_ClearJumpTo (E);
    }
    CollDeleteAll (&L->JumpFrom);

    /* Remove the reference to the owning instruction if it has one. The
     * function may be called for a label without an owner when deleting
     * unfinished parts of the code. This is unfortunate since it allows
     * errors to slip through.
     */
    if (L->Owner) {
       	CollDeleteItem (&L->Owner->Labels, L);
    }

    /* All references removed, delete the label itself */
    FreeCodeLabel (L);
}
Beispiel #3
0
static unsigned GetRegInfo1 (CodeSeg* S,
                             CodeEntry* E,
                             int Index,
                             Collection* Visited,
                             unsigned Used,
                             unsigned Unused,
                             unsigned Wanted)
/* Recursively called subfunction for GetRegInfo. */
{
    /* Remember the current count of the line collection */
    unsigned Count = CollCount (Visited);

    /* Call the worker routine */
    unsigned R = GetRegInfo2 (S, E, Index, Visited, Used, Unused, Wanted);

    /* Restore the old count, unmarking all new entries */
    unsigned NewCount = CollCount (Visited);
    while (NewCount-- > Count) {
        CodeEntry* E = CollAt (Visited, NewCount);
        CE_ResetMark (E);
        CollDelete (Visited, NewCount);
    }

    /* Return the registers used */
    return R;
}
Beispiel #4
0
static void WriteDep (FILE* F, FileType Types)
/* Helper function. Writes all file names that match Types to the output */
{
    unsigned I;

    /* Loop over all files */
    for (I = 0; I < CollCount (&FileTab); ++I) {

        const StrBuf* Filename;

        /* Get the next input file */
        const FileEntry* E = (const FileEntry*) CollAt (&FileTab, I);

        /* Ignore it if it is not of the correct type */
        if ((E->Type & Types) == 0) {
            continue;
        }

        /* If this is not the first file, add a space */
        if (I > 0) {
            fputc (' ', F);
        }

        /* Print the dependency */
        Filename = GetStrBuf (E->Name);
        fprintf (F, "%*s", SB_GetLen (Filename), SB_GetConstBuf (Filename));
    }
}
Beispiel #5
0
void PopSearchPath (SearchPaths* P)
/* Remove a search path from the head of an existing search path list */
{
    /* Remove the path at position 0 */
    xfree (CollAt (P, 0));
    CollDelete (P, 0);
}
Beispiel #6
0
static void WriteDep (FILE* F, InputType Types)
/* Helper function. Writes all file names that match Types to the output */
{
    unsigned I;

    /* Loop over all files */
    unsigned FileCount = CollCount (&IFiles);
    for (I = 0; I < FileCount; ++I) {

    	/* Get the next input file */
    	const IFile* IF = (const IFile*) CollAt (&IFiles, I);

        /* Ignore it if it is not of the correct type */
        if ((IF->Type & Types) == 0) {
            continue;
        }

    	/* If this is not the first file, add a space */
       	if (I > 0) {
            fputc (' ', F);
        }

    	/* Print the dependency escaping spaces */
        WriteEscaped (F, IF->Name);
    }
}
Beispiel #7
0
const char* GetCurrentFile (void)
/* Return the name of the current input file */
{
    unsigned AFileCount = CollCount (&AFiles);
    if (AFileCount > 0) {
     	const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
     	return AF->Input->Name;
    } else {
     	/* No open file. Use the main file if we have one. */
     	unsigned IFileCount = CollCount (&IFiles);
     	if (IFileCount > 0) {
     	    const IFile* IF = (const IFile*) CollAt (&IFiles, 0);
     	    return IF->Name;
     	} else {
      	    return "(outside file scope)";
     	}
    }
}
Beispiel #8
0
void ObjReadData (FILE* F, ObjData* O)
/* Read object file data from the given file. The function expects the Name
 * and Start fields to be valid. Header and basic data are read.
 */
{
    unsigned long Count;

    /* Seek to the start of the object file data */
    fseek (F, O->Start, SEEK_SET);

    /* Read the object file header */
    ObjReadHeader (F, &O->Header, O->Name);

    /* Read the string pool */
    fseek (F, O->Start + O->Header.StrPoolOffs, SEEK_SET);
    Count = ReadVar (F);
    CollGrow (&O->Strings, Count);
    while (Count--) {
        CollAppend (&O->Strings, ReadStr (F));
    }

    /* Read the exports */
    fseek (F, O->Start + O->Header.ExportOffs, SEEK_SET);
    Count = ReadVar (F);
    CollGrow (&O->Exports, Count);
    while (Count--) {

        unsigned char ConDes[CD_TYPE_COUNT];

        /* Skip data until we get to the name */
        unsigned Type = ReadVar (F);
        (void) Read8 (F);       /* AddrSize */
        ReadData (F, ConDes, SYM_GET_CONDES_COUNT (Type));

        /* Now this is what we actually need: The name of the export */
        CollAppend (&O->Exports, CollAt (&O->Strings, ReadVar (F)));

        /* Skip the export value */
        if (SYM_IS_EXPR (Type)) {
            /* Expression tree */
            SkipExpr (F);
        } else {
            /* Literal value */
            (void) Read32 (F);
        }

        /* Skip the size if necessary */
        if (SYM_HAS_SIZE (Type)) {
            (void) ReadVar (F);
        }

        /* Line info indices */
        SkipLineInfoList (F);
        SkipLineInfoList (F);
    }
}
Beispiel #9
0
static void ExecCmd (Collection* Args, const CmdEntry* Tab, unsigned Count)
/* Search for the command in slot 0 of the given collection. If found, check
 * the argument count, then execute it. If there are problems, output a
 * diagnostic.
 */
{
    /* Search for the command, check number of args, then execute it */
    const char* Cmd = CollAt (Args, 0);
    const CmdEntry* E = FindCmd (Cmd, Tab, Count);
    if (E == 0) {
        PrintLine ("No such command: %s", Cmd);
        return;
    }

    /* Check the number of arguments. Zero means that the function will check
     * itself. A negative count means that the function needs at least
     * abs(count) arguments. A positive count means that the function needs
     * exactly this number of arguments.
     * Note: The number includes the command itself.
     */
    if (E->ArgCount > 0 && (int)CollCount (Args) != E->ArgCount) {
        /* Argument number mismatch */
        switch (E->ArgCount) {

            case 1:
                PrintLine ("Command doesn't accept an argument");
                return;

            case 2:
                PrintLine ("Command requires an argument");
                return;

            default:
                PrintLine ("Command requires %d arguments", E->ArgCount-1);
                return;
        }
    } else if (E->ArgCount < 0 && (int)CollCount (Args) < -E->ArgCount) {
        /* Argument number mismatch */
        switch (E->ArgCount) {

            case -2:
                PrintLine ("Command requires at least one argument");
                return;

            default:
                PrintLine ("Command requires at least %d arguments", E->ArgCount-1);
                return;
        }
    } else {
        /* Remove the command from the argument list, then execute it */
        CollDelete (Args, 0);
        E->Func (Args);
    }
}
Beispiel #10
0
void ClearObjData (ObjData* O)
/* Remove any data stored in O */
{
    unsigned I;
    xfree (O->Name);
    O->Name = 0;
    for (I = 0; I < CollCount (&O->Strings); ++I) {
        xfree (CollAt (&O->Strings, I));
    }
    CollDeleteAll (&O->Strings);
    CollDeleteAll (&O->Exports);
}
Beispiel #11
0
unsigned GetCurrentLine (void)
/* Return the line number in the current input file */
{
    unsigned AFileCount = CollCount (&AFiles);
    if (AFileCount > 0) {
     	const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
     	return AF->Line;
    } else {
     	/* No open file */
     	return 0;
    }
}
Beispiel #12
0
ExprNode* ULabResolve (unsigned Index)
/* Return a valid expression for the unnamed label with the given index. This
 * is used to resolve unnamed labels when assembly is done, so it is an error
 * if a label is still undefined in this phase.
 */
{
    /* Get the label and check that it is defined */
    ULabel* L = CollAt (&ULabList, Index);
    CHECK (L->Val != 0);

    /* Return the label value */
    return CloneExpr (L->Val);
}
Beispiel #13
0
void FreeObjData (ObjData* O)
/* Free a complete struct */
{
    unsigned I;

    xfree (O->Name);
    for (I = 0; I < CollCount (&O->Strings); ++I) {
        xfree (CollAt (&O->Strings, I));
    }
    DoneCollection (&O->Strings);
    DoneCollection (&O->Exports);
    xfree (O);
}
Beispiel #14
0
Section* GetExprSection (ExprNode* Expr)
/* Get the segment for a section expression node */
{
    /* Check that this is really a section node */
    PRECONDITION (Expr->Op == EXPR_SECTION);

    /* If we have an object file, get the section from it, otherwise
     * (internally generated expressions), get the section from the
     * section pointer.
     */
    if (Expr->Obj) {
        /* Return the export */
        return CollAt (&Expr->Obj->Sections, Expr->V.SecNum);
    } else {
        return Expr->V.Sec;
    }
}
Beispiel #15
0
void CollMove (Collection* C, unsigned OldIndex, unsigned NewIndex)
/* Move an item from one position in the collection to another. OldIndex
** is the current position of the item, NewIndex is the new index after
** the function has done it's work. Existing entries with indices NewIndex
** and up are moved one position upwards.
*/
{
    /* Get the item and remove it from the collection */
    void* Item = CollAt (C, OldIndex);
    CollDelete (C, OldIndex);

    /* Correct NewIndex if needed */
    if (NewIndex >= OldIndex) {
        /* Position has changed with removal */
        --NewIndex;
    }

    /* Now insert it at the new position */
    CollInsert (C, Item, NewIndex);
}
Beispiel #16
0
static IFile* FindFile (const char* Name)
/* Find the file with the given name in the list of all files. Since the list
 * is not large (usually less than 10), I don't care about using hashes or
 * similar things and do a linear search.
 */
{
    unsigned I;
    for (I = 0; I < CollCount (&IFiles); ++I) {
	/* Get the file struct */
	IFile* IF = (IFile*) CollAt (&IFiles, I);
	/* Check the name */
	if (strcmp (Name, IF->Name) == 0) {
	    /* Found, return the struct */
	    return IF;
       	}
    }

    /* Not found */
    return 0;
}
Beispiel #17
0
static void CS_MoveLabelsToEntry (CodeSeg* S, CodeEntry* E)
/* Move all labels from the label pool to the given entry and remove them
 * from the pool.
 */
{
    /* Transfer the labels if we have any */
    unsigned I;
    unsigned LabelCount = CollCount (&S->Labels);
    for (I = 0; I < LabelCount; ++I) {

   	/* Get the label */
   	CodeLabel* L = CollAt (&S->Labels, I);

   	/* Attach it to the entry */
   	CE_AttachLabel (E, L);
    }

    /* Delete the transfered labels */
    CollDeleteAll (&S->Labels);
}
Beispiel #18
0
int FindAttr (const Collection* C, const char* Name, unsigned* Index)
/* Search for an attribute with the given name in the collection. If it is
 * found, the function returns true and Index contains the index of the
 * entry. If Name isn't found, the function returns false and Index
 * will contain the insert position.
 */
{
    /* Do a binary search */
    int Lo = 0;
    int Hi = (int) CollCount (C) - 1;
    while (Lo <= Hi) {

        /* Mid of range */
        int Cur = (Lo + Hi) / 2;

        /* Get item */
        const Attr* A = CollAt (C, Cur);

        /* Compare */
        int Res = strcmp (A->Name, Name);

        /* Found? */
        if (Res < 0) {
            Lo = Cur + 1;
        } else if (Res > 0) {
            Hi = Cur - 1;
        } else {
            /* Found! */
            *Index = Cur;
            return 1;
        }
    }

    /* Pass back the insert position */
    *Index = Lo;
    return 0;
}
Beispiel #19
0
Export* ReadExport (FILE* F, ObjData* O)
/* Read an export from a file */
{
    unsigned    ConDesCount;
    unsigned    I;
    Export*     E;

    /* Read the type */
    unsigned Type = ReadVar (F);

    /* Read the address size */
    unsigned char AddrSize = Read8 (F);

    /* Create a new export without a name */
    E = NewExport (Type, AddrSize, INVALID_STRING_ID, O);

    /* Read the constructor/destructor decls if we have any */
    ConDesCount = SYM_GET_CONDES_COUNT (Type);
    if (ConDesCount > 0) {

        unsigned char ConDes[CD_TYPE_COUNT];

        /* Read the data into temp storage */
        ReadData (F, ConDes, ConDesCount);

        /* Re-order the data. In the file, each decl is encoded into a byte
        ** which contains the type and the priority. In memory, we will use
        ** an array of types which contain the priority.
        */
        for (I = 0; I < ConDesCount; ++I) {
            E->ConDes[CD_GET_TYPE (ConDes[I])] = CD_GET_PRIO (ConDes[I]);
        }
    }

    /* Read the name */
    E->Name = MakeGlobalStringId (O, ReadVar (F));

    /* Read the value */
    if (SYM_IS_EXPR (Type)) {
        E->Expr = ReadExpr (F, O);
    } else {
        E->Expr = LiteralExpr (Read32 (F), O);
    }

    /* Read the size */
    if (SYM_HAS_SIZE (Type)) {
        E->Size = ReadVar (F);
    }

    /* Last are the locations */
    ReadLineInfoList (F, O, &E->DefLines);
    ReadLineInfoList (F, O, &E->RefLines);

    /* If this symbol is exported as a condes, and the condes type declares a
    ** forced import, add this import to the object module.
    */
    for (I = 0; I < CD_TYPE_COUNT; ++I) {
        const ConDesImport* CDI;

        if (E->ConDes[I] != CD_PRIO_NONE && (CDI = ConDesGetImport (I)) != 0) {
            unsigned J;

            /* Generate a new import, and add it to the module's import list. */
            Import* Imp = GenImport (CDI->Name, CDI->AddrSize);

            Imp->Obj = O;
            CollAppend (&O->Imports, Imp);

            /* Add line info for the export that is actually the condes that
            ** forces the import.  Then, add line info for the config. file.
            ** The export's info is added first because the import pretends
            ** that it came from the object module instead of the config. file.
            */
            for (J = 0; J < CollCount (&E->DefLines); ++J) {
                CollAppend (&Imp->RefLines, DupLineInfo (CollAt (&E->DefLines, J)));
            }
            CollAppend (&Imp->RefLines, GenLineInfo (&CDI->Pos));
        }
    }

    /* Return the new export */
    return E;
}
Beispiel #20
0
static StrBuf* ME_GetActual (MacroExp* E, unsigned Index)
/* Return an actual macro argument with the given index */
{
    return CollAt (&E->ActualArgs, Index);
}