/// <summary> /// Creates a LocalVariableTable from a SerLocalVariableTable. /// </summary> /// <param name="serTable">Deserialized data.</param> /// <param name="contentVersion">Serialization version.</param> /// <param name="report">Error report object.</param> /// <param name="outLvt">Created LocalVariableTable</param> /// <returns>True on success.</returns> private static bool CreateLocalVariableTable(SerLocalVariableTable serTable, int contentVersion, FileLoadReport report, out LocalVariableTable outLvt) { outLvt = new LocalVariableTable(); outLvt.ClearPrevious = serTable.ClearPrevious; foreach (SerDefSymbol serDef in serTable.Variables) { // Force the "has width" field to true for local variables, because it's // non-optional there. This is really only needed for loading projects // created in v1.3, which didn't have the "has width" property. serDef.HasWidth = true; if (!CreateDefSymbol(serDef, contentVersion, report, out DefSymbol defSym)) { return(false); } if (!defSym.IsVariable) { // not expected to happen; skip it Debug.WriteLine("Found local variable with bad source: " + defSym.SymbolSource); string str = string.Format(Res.Strings.ERR_BAD_LOCAL_VARIABLE_FMT, defSym); report.Add(FileLoadItem.Type.Warning, str); continue; } outLvt.AddOrReplace(defSym); } return(true); }
/// <summary> /// Updates internal state to reflect the state of the world at the specified offset. /// </summary> /// <remarks> /// When the offset is greater than or equal to its value on a previous call, we can /// do an incremental update. If the offset moves backward, we have to reset and walk /// forward again. /// </remarks> /// <param name="targetOffset">Target offset.</param> private void AdvanceToOffset(int targetOffset) { if (mNextLvtIndex < 0) { return; } if (targetOffset < mRecentOffset) { // We went backwards. Reset(); } while (mNextLvtOffset <= targetOffset) { if (!mProject.GetAnattrib(mNextLvtOffset).IsStart) { // Hidden table, ignore it. Debug.WriteLine("Ignoring LvTable at +" + mNextLvtOffset.ToString("x6")); } else { // Process this table. LocalVariableTable lvt = mLvTables.Values[mNextLvtIndex]; if (lvt.ClearPrevious) { mCurrentTable.Clear(); } // Create a list for GetVariablesDefinedAtOffset mRecentSymbols = new List <DefSymbol>(); mRecentOffset = mNextLvtOffset; // Merge the new entries into the work table. This automatically // discards entries that clash by name or value. for (int i = 0; i < lvt.Count; i++) { DefSymbol defSym = lvt[i]; // Look for non-variable symbols with the same label. Ordinarily the // editor prevents this from happening, but there are ways to trick // the system (e.g. add a symbol while the LvTable is hidden). We // deal with it here. if (mSymbolTable.TryGetNonVariableValue(defSym.Label, out Symbol unused)) { Debug.WriteLine("Detected duplicate non-var label " + defSym.Label + " at +" + mNextLvtOffset.ToString("x6")); string newLabel = DeDupLabel(defSym.Label); mDupRemap[defSym.Label] = newLabel; defSym = new DefSymbol(defSym, newLabel); } if (mDoUniquify) { if (mUniqueLabels.TryGetValue(defSym.Label, out UniqueLabel ulab)) { // We've seen this label before; generate a unique version by // increasing the appended number. ulab.MakeUnique(mSymbolTable); defSym = new DefSymbol(defSym, ulab.Label); } else { // Haven't seen this before. Add it to the unique-labels table. mUniqueLabels.Add(defSym.Label, new UniqueLabel(defSym.Label)); } } mCurrentTable.AddOrReplace(defSym); mRecentSymbols.Add(defSym); } //mCurrentTable.DebugDump(mNextLvtOffset); } // Update state to look for next table. mNextLvtIndex++; if (mNextLvtIndex < mLvTables.Keys.Count) { mNextLvtOffset = mLvTables.Keys[mNextLvtIndex]; } else { mNextLvtOffset = mProject.FileDataLength; // never reached } } }
/// <summary> /// Updates internal state to reflect the state of the world at the specified offset. /// </summary> /// <remarks> /// When the offset is greater than or equal to its value on a previous call, we can /// do an incremental update. If the offset moves backward, we have to reset and walk /// forward again. /// </remarks> /// <param name="targetOffset">Target offset.</param> private void AdvanceToOffset(int targetOffset) { if (mNextLvtIndex < 0) { return; } if (targetOffset < mRecentOffset) { // We went backwards. Reset(false); } while (mNextLvtOffset <= targetOffset) { if (!mProject.GetAnattrib(mNextLvtOffset).IsStart) { // Hidden table, ignore it. Debug.WriteLine("Ignoring LvTable at +" + mNextLvtOffset.ToString("x6")); } else { // Process this table. LocalVariableTable lvt = mLvTables.Values[mNextLvtIndex]; if (lvt.ClearPrevious) { mCurrentTable.Clear(); } // Create a list for GetVariablesDefinedAtOffset mRecentSymbols = new List <DefSymbol>(); mRecentOffset = mNextLvtOffset; // Merge the new entries into the work table. This automatically // discards entries that clash by name or value. for (int i = 0; i < lvt.Count; i++) { DefSymbol defSym = lvt[i]; string newLabel = defSym.Label; if (mMaskLeadingUnderscores && newLabel[0] == '_') { newLabel = AsmGen.LabelLocalizer.NO_UNDER_PFX + newLabel; } // Look for non-variable symbols with the same label. Ordinarily the // editor prevents this from happening, but there are ways to trick // the system (e.g. add a symbol while the LvTable is hidden, or have // a non-unique local promoted to global). We deal with it here. // // TODO(someday): this is not necessary for assemblers like Merlin 32 // that put variables in a separate namespace. if (mAllNvSymbols.TryGetValue(newLabel, out Symbol unused)) { Debug.WriteLine("Detected duplicate non-var label " + newLabel + " at +" + mNextLvtOffset.ToString("x6")); newLabel = GenerateDeDupLabel(newLabel); } if (newLabel != defSym.Label) { mDupRemap[defSym.Label] = newLabel; defSym = new DefSymbol(defSym, newLabel); } if (mDoUniquify) { if (mUniqueLabels.TryGetValue(defSym.Label, out UniqueLabel ulab)) { // We've seen this label before; generate a unique version by // increasing the appended number. ulab.MakeUnique(mAllNvSymbols); defSym = new DefSymbol(defSym, ulab.Label); } else { // Haven't seen this before. Add it to the unique-labels table. mUniqueLabels.Add(defSym.Label, new UniqueLabel(defSym.Label)); } } mCurrentTable.AddOrReplace(defSym); mRecentSymbols.Add(defSym); } //mCurrentTable.DebugDump(mNextLvtOffset); } // Update state to look for next table. mNextLvtIndex++; if (mNextLvtIndex < mLvTables.Keys.Count) { mNextLvtOffset = mLvTables.Keys[mNextLvtIndex]; } else { mNextLvtOffset = mProject.FileDataLength; // never reached } } }