void CS_DelCodeAfter (CodeSeg* S, unsigned Last) /* Delete all entries including the given one */ { /* Get the number of entries in this segment */ unsigned Count = CS_GetEntryCount (S); /* First pass: Delete all references to labels. If the reference count * for a label drops to zero, delete it. */ unsigned C = Count; while (Last < C--) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, C); /* Check if this entry has a label reference */ if (E->JumpTo) { /* If the label is a label in the label pool and this is the last * reference to the label, remove the label from the pool. */ CodeLabel* L = E->JumpTo; int Index = CollIndex (&S->Labels, L); if (Index >= 0 && CollCount (&L->JumpFrom) == 1) { /* Delete it from the pool */ CollDelete (&S->Labels, Index); } /* Remove the reference to the label */ CS_RemoveLabelRef (S, E); } } /* Second pass: Delete the instructions. If a label attached to an * instruction still has references, it must be references from outside * the deleted area. Don't delete the label in this case, just make it * ownerless and move it to the label pool. */ C = Count; while (Last < C--) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, C); /* Check if this entry has a label attached */ if (CE_HasLabel (E)) { /* Move the labels to the pool and clear the owner pointer */ CS_MoveLabelsToPool (S, E); } /* Delete the pointer to the entry */ CollDelete (&S->Entries, C); /* Delete the entry itself */ FreeCodeEntry (E); } }
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; }
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); }
static void CloseIncludeFile (void) /* Close an include file and switch to the higher level file. Set Input to * NULL if this was the main file. */ { AFile* Input; /* Get the number of active input files */ unsigned AFileCount = CollCount (&AFiles); /* Must have an input file when called */ PRECONDITION (AFileCount > 0); /* Get the current active input file */ Input = (AFile*) CollLast (&AFiles); /* Close the current input file (we're just reading so no error check) */ fclose (Input->F); /* Delete the last active file from the active file collection */ CollDelete (&AFiles, AFileCount-1); /* If we had added an extra search path for this AFile, remove it */ if (Input->SearchPath) { PopSearchPath (UsrIncSearchPath); } /* Delete the active file structure */ FreeAFile (Input); }
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); } }
void CS_DelEntry (CodeSeg* S, unsigned Index) /* Delete an entry from the code segment. This includes moving any associated * labels, removing references to labels and even removing the referenced labels * if the reference count drops to zero. * Note: Labels are moved forward if possible, that is, they are moved to the * next insn (not the preceeding one). */ { /* Get the code entry for the given index */ CodeEntry* E = CS_GetEntry (S, Index); /* If the entry has a labels, we have to move this label to the next insn. * If there is no next insn, move the label into the code segement label * pool. The operation is further complicated by the fact that the next * insn may already have a label. In that case change all reference to * this label and delete the label instead of moving it. */ unsigned Count = CE_GetLabelCount (E); if (Count > 0) { /* The instruction has labels attached. Check if there is a next * instruction. */ if (Index == CS_GetEntryCount (S)-1) { /* No next instruction, move to the codeseg label pool */ CS_MoveLabelsToPool (S, E); } else { /* There is a next insn, get it */ CodeEntry* N = CS_GetEntry (S, Index+1); /* Move labels to the next entry */ CS_MoveLabels (S, E, N); } } /* If this insn references a label, remove the reference. And, if the * the reference count for this label drops to zero, remove this label. */ if (E->JumpTo) { /* Remove the reference */ CS_RemoveLabelRef (S, E); } /* Delete the pointer to the insn */ CollDelete (&S->Entries, Index); /* Delete the instruction itself */ FreeCodeEntry (E); }
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); }
void DelObjData (const char* Module) /* Delete the object module from the list */ { unsigned I; for (I = 0; I < CollCount (&ObjPool); ++I) { /* Get this object file */ ObjData* O = CollAtUnchecked (&ObjPool, I); /* Did we find it? */ if (strcmp (O->Name, Module) == 0) { /* Free the entry */ CollDelete (&ObjPool, I); FreeObjData (O); /* Done */ return; } } /* Not found! */ Warning ("Module '%s' not found in library '%s'", Module, LibName); }
void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last) /* Delete all entries between first and last, both inclusive. The function * can only handle basic blocks (First is the only entry, Last the only exit) * and no open labels. It will call FAIL if any of these preconditions are * violated. */ { unsigned I; CodeEntry* FirstEntry; /* Do some sanity checks */ CHECK (First <= Last && Last < CS_GetEntryCount (S)); /* If Last is actually the last insn, call CS_DelCodeAfter instead, which * is more flexible in this case. */ if (Last == CS_GetEntryCount (S) - 1) { CS_DelCodeAfter (S, First); return; } /* Get the first entry and check if it has any labels. If it has, move * them to the insn following Last. If Last is the last insn of the code * segment, make them ownerless and move them to the label pool. */ FirstEntry = CS_GetEntry (S, First); if (CE_HasLabel (FirstEntry)) { /* Get the entry following last */ CodeEntry* FollowingEntry = CS_GetNextEntry (S, Last); if (FollowingEntry) { /* There is an entry after Last - move the labels */ CS_MoveLabels (S, FirstEntry, FollowingEntry); } else { /* Move the labels to the pool and clear the owner pointer */ CS_MoveLabelsToPool (S, FirstEntry); } } /* First pass: Delete all references to labels. If the reference count * for a label drops to zero, delete it. */ for (I = Last; I >= First; --I) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this entry has a label reference */ if (E->JumpTo) { /* If the label is a label in the label pool, this is an error */ CodeLabel* L = E->JumpTo; CHECK (CollIndex (&S->Labels, L) < 0); /* Remove the reference to the label */ CS_RemoveLabelRef (S, E); } } /* Second pass: Delete the instructions. If a label attached to an * instruction still has references, it must be references from outside * the deleted area, which is an error. */ for (I = Last; I >= First; --I) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this entry has a label attached */ CHECK (!CE_HasLabel (E)); /* Delete the pointer to the entry */ CollDelete (&S->Entries, I); /* Delete the entry itself */ FreeCodeEntry (E); } }