mirror of
https://github.com/fadden/6502bench.git
synced 2024-11-30 01:50:10 +00:00
02c79db749
For ACME and cc65, enable uniqification. This works with my basic tests, but there are a lot of potential edge cases.
215 lines
8.7 KiB
C#
215 lines
8.7 KiB
C#
/*
|
|
* Copyright 2019 faddenSoft
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
using System;
|
|
using System.Diagnostics;
|
|
|
|
namespace SourceGen {
|
|
/// <summary>
|
|
/// Subclass of Symbol used for symbols defined in the platform or project.
|
|
///
|
|
/// Instances are immutable, except for the Xrefs field.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The Xrefs field isn't really part of the object. It's just convenient to reference
|
|
/// them from here.
|
|
/// </remarks>
|
|
public class DefSymbol : Symbol {
|
|
// width to use when width doesn't matter; use 1 to try to get a prefab object
|
|
public const int NO_WIDTH = 1;
|
|
public const int MIN_WIDTH = 1;
|
|
public const int MAX_WIDTH = 4;
|
|
|
|
/// <summary>
|
|
/// Data format descriptor.
|
|
/// </summary>
|
|
public FormatDescriptor DataDescriptor { get; private set; }
|
|
|
|
/// <summary>
|
|
/// User-supplied comment.
|
|
/// </summary>
|
|
public string Comment { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Platform symbols only: tag used to organize symbols into groups. Used by
|
|
/// extension scripts.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This is not included in DefSymbol serialization because symbols with tags are
|
|
/// not stored in the project file. It's only set when symbols are parsed out of
|
|
/// platform symbol files.
|
|
/// </remarks>
|
|
public string Tag { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Cross-reference data, generated by the analyzer.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This is just a convenient place to reference some data generated at run-time. It's
|
|
/// not serialized, and not included in the test for equality.
|
|
/// </remarks>
|
|
public XrefSet Xrefs { get; private set; }
|
|
|
|
// NOTE: might be nice to identify the symbol's origin, e.g. which platform
|
|
// symbol file it was defined in. This could then be stored in a
|
|
// DisplayList line, for benefit of the Info panel.
|
|
|
|
|
|
/// <summary>
|
|
/// Internal base-object constructor, called by other constructors.
|
|
/// </summary>
|
|
private DefSymbol(string label, int value, Source source, Type type)
|
|
: base(label, value, source, type) {
|
|
Debug.Assert(source == Source.Platform || source == Source.Project ||
|
|
source == Source.Variable);
|
|
Debug.Assert(type == Type.ExternalAddr || type == Type.Constant);
|
|
Xrefs = new XrefSet();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructor.
|
|
/// </summary>
|
|
/// <param name="label">Symbol's label.</param>
|
|
/// <param name="value">Symbol's value.</param>
|
|
/// <param name="source">Symbol source (general point of origin).</param>
|
|
/// <param name="type">Symbol type.</param>
|
|
/// <param name="formatSubType">Format descriptor sub-type, so we know how the
|
|
/// user wants the value to be displayed.</param>
|
|
/// <param name="comment">End-of-line comment.</param>
|
|
/// <param name="tag">Symbol tag, used for grouping platform symbols.</param>
|
|
public DefSymbol(string label, int value, Source source, Type type,
|
|
FormatDescriptor.SubType formatSubType, string comment, string tag)
|
|
: this(label, value, source, type, formatSubType, comment, tag, NO_WIDTH) { }
|
|
|
|
/// <summary>
|
|
/// Constructor. Used for local variables, which have a meaningful width.
|
|
/// </summary>
|
|
/// <param name="label">Symbol's label.</param>
|
|
/// <param name="value">Symbol's value.</param>
|
|
/// <param name="source">Symbol source (general point of origin).</param>
|
|
/// <param name="type">Symbol type.</param>
|
|
/// <param name="formatSubType">Format descriptor sub-type, so we know how the
|
|
/// user wants the value to be displayed.</param>
|
|
/// <param name="comment">End-of-line comment.</param>
|
|
/// <param name="tag">Symbol tag, used for grouping platform symbols.</param>
|
|
/// <param name="width">Variable width.</param>
|
|
public DefSymbol(string label, int value, Source source, Type type,
|
|
FormatDescriptor.SubType formatSubType, string comment, string tag, int width)
|
|
: this(label, value, source, type) {
|
|
Debug.Assert(comment != null);
|
|
Debug.Assert(tag != null);
|
|
|
|
DataDescriptor = FormatDescriptor.Create(width,
|
|
FormatDescriptor.Type.NumericLE, formatSubType);
|
|
|
|
Comment = comment;
|
|
Tag = tag;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs a DefSymbol from a Symbol and a format descriptor. This is used
|
|
/// for project symbols.
|
|
/// </summary>
|
|
/// <param name="sym">Base symbol.</param>
|
|
/// <param name="dfd">Format descriptor.</param>
|
|
/// <param name="comment">End-of-line comment.</param>
|
|
public DefSymbol(Symbol sym, FormatDescriptor dfd, string comment)
|
|
: this(sym.Label, sym.Value, sym.SymbolSource, sym.SymbolType) {
|
|
Debug.Assert(comment != null);
|
|
|
|
DataDescriptor = dfd;
|
|
Comment = comment;
|
|
Tag = string.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs a DefSymbol from an existing DefSymbol, with a different label. Use
|
|
/// this to change the label while keeping everything else the same.
|
|
/// </summary>
|
|
/// <param name="defSym">Source DefSymbol.</param>
|
|
/// <param name="label">Label to use.</param>
|
|
public DefSymbol(DefSymbol defSym, string label)
|
|
: this(label, defSym.Value, defSym.SymbolSource, defSym.SymbolType,
|
|
defSym.DataDescriptor.FormatSubType, defSym.Comment, defSym.Tag,
|
|
defSym.DataDescriptor.Length) { }
|
|
|
|
/// <summary>
|
|
/// Determines whether a symbol overlaps with a region. Useful for variables.
|
|
/// </summary>
|
|
/// <param name="a">Symbol to check.</param>
|
|
/// <param name="value">Address.</param>
|
|
/// <param name="width">Symbol width.</param>
|
|
/// <param name="type">Symbol type to check against.</param>
|
|
/// <returns>True if the symbols overlap.</returns>
|
|
public static bool CheckOverlap(DefSymbol a, int value, int width, Type type) {
|
|
if (a.DataDescriptor.Length <= 0 || width <= 0) {
|
|
return false;
|
|
}
|
|
if (a.Value < 0 || value < 0) {
|
|
return false;
|
|
}
|
|
if (a.SymbolType != type) {
|
|
return false;
|
|
}
|
|
int maxStart = Math.Max(a.Value, value);
|
|
int minEnd = Math.Min(a.Value + a.DataDescriptor.Length - 1, value + width - 1);
|
|
return (maxStart <= minEnd);
|
|
}
|
|
|
|
|
|
public static bool operator ==(DefSymbol a, DefSymbol b) {
|
|
if (ReferenceEquals(a, b)) {
|
|
return true; // same object, or both null
|
|
}
|
|
if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) {
|
|
return false; // one is null
|
|
}
|
|
return a.Equals(b);
|
|
}
|
|
public static bool operator !=(DefSymbol a, DefSymbol b) {
|
|
return !(a == b);
|
|
}
|
|
public override bool Equals(object obj) {
|
|
if (!(obj is DefSymbol)) {
|
|
return false;
|
|
}
|
|
// Do base-class equality comparison and the ReferenceEquals check.
|
|
if (!base.Equals(obj)) {
|
|
return false;
|
|
}
|
|
|
|
// All fields must be equal, except Xrefs.
|
|
DefSymbol other = (DefSymbol)obj;
|
|
if (DataDescriptor != other.DataDescriptor ||
|
|
Comment != other.Comment ||
|
|
Tag != other.Tag) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
public override int GetHashCode() {
|
|
return base.GetHashCode() ^
|
|
DataDescriptor.GetHashCode() ^
|
|
Comment.GetHashCode() ^
|
|
Tag.GetHashCode();
|
|
}
|
|
|
|
public override string ToString() {
|
|
return base.ToString() + ":" + DataDescriptor + ";" + Comment +
|
|
(string.IsNullOrEmpty(Tag) ? "" : " [" + Tag + "]");
|
|
}
|
|
}
|
|
}
|