mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Allow defining abstract Results
This commit is contained in:
parent
7b38708c11
commit
9eeed9c225
4 changed files with 1430 additions and 1327 deletions
|
@ -131,6 +131,7 @@ namespace LibHacBuild.CodeGen.Stage1
|
|||
foreach (ModuleInfo module in modules)
|
||||
{
|
||||
var descriptionSet = new HashSet<int>();
|
||||
var descriptionSetAbstract = new HashSet<int>();
|
||||
|
||||
if (!moduleIndexSet.Add(module.Index))
|
||||
{
|
||||
|
@ -143,10 +144,22 @@ namespace LibHacBuild.CodeGen.Stage1
|
|||
}
|
||||
|
||||
foreach (ResultInfo result in module.Results)
|
||||
{
|
||||
if (result.IsAbstract)
|
||||
{
|
||||
if (!descriptionSetAbstract.Add(result.DescriptionStart))
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
$"Duplicate abstract result {result.Module}-{result.DescriptionStart}-{result.DescriptionEnd}.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!descriptionSet.Add(result.DescriptionStart))
|
||||
{
|
||||
throw new InvalidDataException($"Duplicate result {result.Module}-{result.DescriptionStart}-{result.DescriptionEnd}.");
|
||||
throw new InvalidDataException(
|
||||
$"Duplicate result {result.Module}-{result.DescriptionStart}-{result.DescriptionEnd}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -263,8 +276,10 @@ namespace LibHacBuild.CodeGen.Stage1
|
|||
|
||||
sb.AppendLine(GetXmlDoc(result));
|
||||
|
||||
string resultCtor = $"new Result.Base(Module{moduleName}, {descriptionArgs});";
|
||||
sb.Append($"public static Result.Base {result.Name} ");
|
||||
string type = result.IsAbstract ? "Result.Base.Abstract" : "Result.Base";
|
||||
|
||||
string resultCtor = $"new {type}(Module{moduleName}, {descriptionArgs});";
|
||||
sb.Append($"public static {type} {result.Name} ");
|
||||
|
||||
if (EstimateCilSize(result) > InlineThreshold)
|
||||
{
|
||||
|
@ -292,7 +307,11 @@ namespace LibHacBuild.CodeGen.Stage1
|
|||
doc += $"; Range: {result.DescriptionStart}-{result.DescriptionEnd}";
|
||||
}
|
||||
|
||||
if (!result.IsAbstract)
|
||||
{
|
||||
doc += $"; Inner value: 0x{result.InnerValue:x}";
|
||||
}
|
||||
|
||||
doc += "</summary>";
|
||||
|
||||
return doc;
|
||||
|
@ -473,6 +492,7 @@ namespace LibHacBuild.CodeGen.Stage1
|
|||
element.Module = (short)result.Module;
|
||||
element.DescriptionStart = (short)result.DescriptionStart;
|
||||
element.DescriptionEnd = (short)result.DescriptionEnd;
|
||||
element.IsAbstract = result.IsAbstract;
|
||||
|
||||
Span<byte> utf8Name = Encoding.UTF8.GetBytes(result.FullName);
|
||||
utf8Name.CopyTo(nameTable.Slice(curNameOffset));
|
||||
|
@ -515,6 +535,7 @@ namespace LibHacBuild.CodeGen.Stage1
|
|||
public short Module;
|
||||
public short DescriptionStart;
|
||||
public short DescriptionEnd;
|
||||
public bool IsAbstract;
|
||||
}
|
||||
// ReSharper restore NotAccessedField.Local
|
||||
}
|
||||
|
@ -550,6 +571,7 @@ namespace LibHacBuild.CodeGen.Stage1
|
|||
public int Module { get; set; }
|
||||
public int DescriptionStart { get; set; }
|
||||
public int DescriptionEnd { get; set; }
|
||||
public ResultInfoFlags Flags { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string FullName { get; set; }
|
||||
public string Summary { get; set; }
|
||||
|
@ -557,6 +579,14 @@ namespace LibHacBuild.CodeGen.Stage1
|
|||
public bool IsRange => DescriptionStart != DescriptionEnd;
|
||||
public string ErrorCode => $"{2000 + Module:d4}-{DescriptionStart:d4}";
|
||||
public int InnerValue => Module & 0x1ff | ((DescriptionStart & 0x7ffff) << 9);
|
||||
public bool IsAbstract => Flags.HasFlag(ResultInfoFlags.Abstract);
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ResultInfoFlags
|
||||
{
|
||||
None = 0,
|
||||
Abstract = 1 << 0
|
||||
}
|
||||
|
||||
public sealed class ResultMap : ClassMap<ResultInfo>
|
||||
|
@ -575,6 +605,27 @@ namespace LibHacBuild.CodeGen.Stage1
|
|||
|
||||
return int.Parse(field);
|
||||
});
|
||||
|
||||
Map(m => m.Flags).ConvertUsing(row =>
|
||||
{
|
||||
string field = row.GetField("Flags");
|
||||
var flags = ResultInfoFlags.None;
|
||||
|
||||
foreach (char c in field)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'a':
|
||||
flags |= ResultInfoFlags.Abstract;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidDataException($"Invalid Result flag '{c}'");
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -311,6 +311,54 @@ namespace LibHac
|
|||
{
|
||||
return ((uint)value & ~(~default(ulong) << bitsCount)) << bitsOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Base"/> that can't be used as a <see cref="Result"/> itself, but can check if its
|
||||
/// range includes other <see cref="Result"/>s.
|
||||
/// </summary>
|
||||
public readonly struct Abstract
|
||||
{
|
||||
private readonly ulong _value;
|
||||
|
||||
public Abstract(int module, int description) : this(module, description, description) { }
|
||||
|
||||
public Abstract(int module, int descriptionStart, int descriptionEnd)
|
||||
{
|
||||
Debug.Assert(ModuleBegin <= module && module < ModuleEnd, "Invalid Module");
|
||||
Debug.Assert(DescriptionBegin <= descriptionStart && descriptionStart < DescriptionEnd, "Invalid Description Start");
|
||||
Debug.Assert(DescriptionBegin <= descriptionEnd && descriptionEnd < DescriptionEnd, "Invalid Description End");
|
||||
Debug.Assert(descriptionStart <= descriptionEnd, "descriptionStart must be <= descriptionEnd");
|
||||
|
||||
_value = SetBitsValueLong(module, ModuleBitsOffset, ModuleBitsCount) |
|
||||
SetBitsValueLong(descriptionStart, DescriptionBitsOffset, DescriptionBitsCount) |
|
||||
SetBitsValueLong(descriptionEnd, DescriptionEndBitsOffset, DescriptionBitsCount);
|
||||
}
|
||||
|
||||
public BaseType Module => GetBitsValueLong(_value, ModuleBitsOffset, ModuleBitsCount);
|
||||
public BaseType DescriptionRangeStart => GetBitsValueLong(_value, DescriptionBitsOffset, DescriptionBitsCount);
|
||||
public BaseType DescriptionRangeEnd => GetBitsValueLong(_value, DescriptionEndBitsOffset, DescriptionBitsCount);
|
||||
|
||||
private Result Value => new Result((BaseType)_value);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the range of this <see cref="Result.Base"/> includes the provided <see cref="Result"/>.
|
||||
/// </summary>
|
||||
/// <param name="result">The <see cref="Result"/> to check.</param>
|
||||
/// <returns><see langword="true"/> if the range includes <paramref name="result"/>. Otherwise, <see langword="false"/>.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Includes(Result result)
|
||||
{
|
||||
// 99% of the time the values in this struct will be constants.
|
||||
// This check allows the compiler to optimize this method down to a simple comparison when possible.
|
||||
if (DescriptionRangeStart == DescriptionRangeEnd)
|
||||
{
|
||||
return result.Value == Value.Value;
|
||||
}
|
||||
|
||||
return result.Module == Module &&
|
||||
result.Description - DescriptionRangeStart <= DescriptionRangeEnd - DescriptionRangeStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IResultLogger
|
||||
|
|
|
@ -57,6 +57,9 @@ namespace LibHac
|
|||
|
||||
foreach (ref readonly Element element in elements)
|
||||
{
|
||||
if (element.IsAbstract)
|
||||
continue;
|
||||
|
||||
var result = new Result(element.Module, element.DescriptionStart);
|
||||
|
||||
if (!dict.TryAdd(result, GetName(element.NameOffset).ToString()))
|
||||
|
@ -89,6 +92,7 @@ namespace LibHac
|
|||
public short Module;
|
||||
public short DescriptionStart;
|
||||
public short DescriptionEnd;
|
||||
public bool IsAbstract;
|
||||
}
|
||||
#pragma warning restore 649
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue