Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
kekyo committed May 1, 2024
1 parent ec9ac77 commit 0890aa4
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 108 deletions.
50 changes: 27 additions & 23 deletions chibild/chibild.core/Generating/ArchivedObjectInputFragment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using chibicc.toolchain.Parsing;
using chibicc.toolchain.Logging;
using chibicc.toolchain.Tokenizing;
using chibicc.toolchain.Internal;
using chibild.Internal;
using System.Collections.Generic;
using System.IO;
Expand All @@ -31,9 +32,9 @@ internal sealed class ArchivedObjectInputFragment :

private readonly string archivedObjectName;

private readonly HashSet<string> typeNames;
private readonly HashSet<string> variableNames;
private readonly HashSet<string> functionNames;
private readonly Dictionary<string, Symbol> typeSymbols;
private readonly Dictionary<string, Symbol> variableSymbols;
private readonly Dictionary<string, Symbol> functionSymbols;

private GlobalVariableNode[] globalVariables = Utilities.Empty<GlobalVariableNode>();
private GlobalConstantNode[] globalConstants = Utilities.Empty<GlobalConstantNode>();
Expand All @@ -48,18 +49,18 @@ private ArchivedObjectInputFragment(
string baseInputPath,
string relativePath,
string archivedObjectName,
HashSet<string> typeNames,
HashSet<string> variableNames,
HashSet<string> functionNames) :
Dictionary<string, Symbol> typeSymbols,
Dictionary<string, Symbol> variableSymbols,
Dictionary<string, Symbol> functionSymbols) :
base(baseInputPath, relativePath)
{
this.archivedObjectName = archivedObjectName;
this.ObjectName = Path.GetFileNameWithoutExtension(this.archivedObjectName);
this.ObjectPath = $"{this.archivedObjectName}@{base.ObjectPath}";

this.typeNames = typeNames;
this.variableNames = variableNames;
this.functionNames = functionNames;
this.typeSymbols = typeSymbols;
this.variableSymbols = variableSymbols;
this.functionSymbols = functionSymbols;
}

public override string ObjectName { get; }
Expand Down Expand Up @@ -92,20 +93,23 @@ public override string ToString() =>
//////////////////////////////////////////////////////////////

public override bool ContainsTypeAndSchedule(
TypeNode type)
TypeNode type,
out Scopes scope)
{
if (this.typeNames.Contains(type.TypeIdentity))
if (this.typeSymbols.TryGetValue(type.TypeIdentity, out var td))
{
this.isRequiredLoading = true;
CommonUtilities.TryParseEnum(td.Scope, out scope);
return true;
}
scope = default;
return false;
}

public override bool ContainsVariableAndSchedule(
IdentityNode variable)
{
if (this.variableNames.Contains(variable.Identity))
if (this.variableSymbols.ContainsKey(variable.Identity))
{
this.isRequiredLoading = true;
return true;
Expand All @@ -118,7 +122,7 @@ public override bool ContainsFunctionAndSchedule(
FunctionSignatureNode? signature)
{
// Ignored the signature, because contains only CABI functions.
if (this.functionNames.Contains(function.Identity))
if (this.functionSymbols.ContainsKey(function.Identity))
{
this.isRequiredLoading = true;
return true;
Expand All @@ -134,7 +138,7 @@ public bool LoadObjectIfRequired(
{
if (this.isRequiredLoading)
{
logger.Information($"Loading: {this.archivedObjectName}@{this.RelativePath}");
logger.Information($"Loading: {this.ObjectPath}");

using var stream = ArchiverUtilities.OpenArchivedObject(
Path.Combine(this.BaseInputPath, this.RelativePath),
Expand All @@ -147,12 +151,12 @@ public bool LoadObjectIfRequired(
isLocationOriginSource).
ToArray();

var variables = declarations.OfType<GlobalVariableNode>().ToArray();
var constants = declarations.OfType<GlobalConstantNode>().ToArray();
var functions = declarations.OfType<FunctionNode>().ToArray();
var initializers = declarations.OfType<InitializerNode>().ToArray();
var enumerations = declarations.OfType<EnumerationNode>().ToArray();
var structures = declarations.OfType<StructureNode>().ToArray();
this.globalVariables = declarations.OfType<GlobalVariableNode>().ToArray();
this.globalConstants = declarations.OfType<GlobalConstantNode>().ToArray();
this.functions = declarations.OfType<FunctionNode>().ToArray();
this.initializers = declarations.OfType<InitializerNode>().ToArray();
this.enumerations = declarations.OfType<EnumerationNode>().ToArray();
this.structures = declarations.OfType<StructureNode>().ToArray();

this.isRequiredLoading = false;
return true;
Expand Down Expand Up @@ -189,15 +193,15 @@ public static ArchivedObjectInputFragment[] Load(
}).
ToDictionary(
g => g.Key,
g => g.Select(symbol => symbol.Name).Distinct().ToHashSet());
g => g.DistinctBy(symbol => symbol.Name).ToDictionary(symbol => symbol.Name));
var empty = new HashSet<string>();
var empty = new Dictionary<string, Symbol>();
return new ArchivedObjectInputFragment(
baseInputPath,
relativePath,
symbolList.ObjectName,
symbols.TryGetValue("type", out var typeNames) ? typeNames : empty,
symbols.TryGetValue("type", out var types) ? types : empty,
symbols.TryGetValue("variable", out var variableNames) ? variableNames : empty,
symbols.TryGetValue("function", out var functionNames) ? functionNames : empty);
}).
Expand Down
16 changes: 12 additions & 4 deletions chibild/chibild.core/Generating/AssemblyInputFragment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
using System.Linq;
using System.Threading.Tasks;
using System.Diagnostics;
using MethodCallingConvention = Mono.Cecil.MethodCallingConvention;

namespace chibild.Generating;

Expand Down Expand Up @@ -52,8 +51,17 @@ public override string ToString() =>
//////////////////////////////////////////////////////////////

public override bool ContainsTypeAndSchedule(
TypeNode type) =>
this.types.ContainsKey(type.TypeIdentity);
TypeNode type,
out Scopes scope)
{
if (this.types.TryGetValue(type.TypeIdentity, out _))
{
scope = Scopes.Public;
return true;
}
scope = default;
return false;
}

public override bool ContainsVariableAndSchedule(
IdentityNode variable) =>
Expand Down Expand Up @@ -87,7 +95,7 @@ private static bool TryGetMatchedMethodIndex(
var overload = overloads[index];

// Match partially when overload is variadic.
if (overload.CallingConvention == MethodCallingConvention.VarArg)
if (overload.CallingConvention == Mono.Cecil.MethodCallingConvention.VarArg)
{
if (overload.Parameters.
Select(p => p.ParameterType.FullName).
Expand Down
21 changes: 15 additions & 6 deletions chibild/chibild.core/Generating/CodeGenerator_Consumer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -783,12 +783,16 @@ private void ConsumeEnumeration(
LookupContext context,
EnumerationNode enumeration)
{
// Check the type already declared another fragment.
// Check public type already declared another fragment.
var r = TypeParser.TryParse(enumeration.Name.Token, out var type);
Debug.Assert(r);
if (this.ContainsTypeAndSchedule(
context, type, out var declaredFragment) &&
declaredFragment != context.CurrentFragment)
context, type,
out var declaredFragment,
out var scope) &&
scope == Scopes.Public &&
declaredFragment != context.CurrentFragment &&
declaredFragment is not ObjectInputFragment) // Will combine into one assembly.
{
this.OutputTrace(
enumeration.Name.Token,
Expand Down Expand Up @@ -875,12 +879,17 @@ private void ConsumeStructure(
LookupContext context,
StructureNode structure)
{
// Check the type already declared another fragment.
// Check public type already declared another fragment.
var r = TypeParser.TryParse(structure.Name.Token, out var type);
Debug.Assert(r);
if (this.ContainsTypeAndSchedule(
context, type, out var declaredFragment) &&
declaredFragment != context.CurrentFragment)
context,
type,
out var declaredFragment,
out var scope) &&
scope == Scopes.Public &&
declaredFragment != context.CurrentFragment &&
declaredFragment is not ObjectInputFragment) // Will combine into one assembly.
{
this.OutputTrace(
structure.Name.Token,
Expand Down
18 changes: 11 additions & 7 deletions chibild/chibild.core/Generating/CodeGenerator_LookupMember.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ private void DelayLookingUpAction2(Action action)
private bool ContainsTypeAndSchedule(
LookupContext context,
TypeNode type,
out InputFragment declaredFragment)
out InputFragment declaredFragment,
out Scopes scope)
{
if (context.CurrentFragment?.ContainsTypeAndSchedule(type) ?? false)
if (context.CurrentFragment?.ContainsTypeAndSchedule(type, out scope) ?? false)
{
declaredFragment = context.CurrentFragment;
return true;
Expand All @@ -52,14 +53,15 @@ private bool ContainsTypeAndSchedule(
foreach (var fragment in context.InputFragments)
{
if (fragment != context.CurrentFragment &&
fragment.ContainsTypeAndSchedule(type))
fragment.ContainsTypeAndSchedule(type, out scope))
{
declaredFragment = fragment;
return true;
}
}

declaredFragment = null!;
scope = default;
return false;
}

Expand All @@ -72,7 +74,8 @@ private bool InternalDelayLookingUpType(
Action<TypeReference> action)
{
// Step 1: Check on current fragment.
if (context.CurrentFragment?.ContainsTypeAndSchedule(type) ?? false)
if (context.CurrentFragment?.
ContainsTypeAndSchedule(type, out _) ?? false)
{
this.DelayLookingUpAction1(() =>
{
Expand All @@ -98,7 +101,7 @@ private bool InternalDelayLookingUpType(
foreach (var fragment in context.InputFragments)
{
if (fragment != context.CurrentFragment &&
fragment.ContainsTypeAndSchedule(type))
fragment.ContainsTypeAndSchedule(type, out _))
{
// Found the symbol.
foundFragment = fragment;
Expand Down Expand Up @@ -473,7 +476,8 @@ private void DelayLookingUpMember(
{
type = TypeParser.TryParse(member.Token, out var t) ? t : null;
if (type != null &&
(context.CurrentFragment?.ContainsTypeAndSchedule(type) ?? false))
(context.CurrentFragment?.
ContainsTypeAndSchedule(type, out _) ?? false))
{
this.DelayLookingUpAction1(() =>
{
Expand Down Expand Up @@ -547,7 +551,7 @@ private void DelayLookingUpMember(
if (fragment != context.CurrentFragment)
{
if (type != null &&
fragment.ContainsTypeAndSchedule(type))
fragment.ContainsTypeAndSchedule(type, out _))
{
// Found the symbol.
foundFragment = fragment;
Expand Down
3 changes: 2 additions & 1 deletion chibild/chibild.core/Generating/InputFragment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ protected InputFragment(
//////////////////////////////////////////////////////////////

public abstract bool ContainsTypeAndSchedule(
TypeNode type);
TypeNode type,
out Scopes scope);

public abstract bool ContainsVariableAndSchedule(
IdentityNode variable);
Expand Down
25 changes: 17 additions & 8 deletions chibild/chibild.core/Generating/ObjectFileInputFragment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace chibild.Generating;
internal sealed class ObjectFileInputFragment :
ObjectInputFragment
{
private readonly HashSet<string> typeNames;
private readonly Dictionary<string, TypeDeclarationNode> types;
private readonly HashSet<string> variableNames;
private readonly HashSet<string> functionNames;

Expand All @@ -42,11 +42,11 @@ private ObjectFileInputFragment(
this.Enumerations = enumerations;
this.Structures = structures;

this.typeNames =
enumerations.Select(e => e.Name.Identity).
Concat(structures.Select(s => s.Name.Identity)).
Distinct().
ToHashSet();
this.types =
enumerations.Cast<TypeDeclarationNode>().
Concat(structures).
DistinctBy(td => td.Name.Identity).
ToDictionary(td => td.Name.Identity);
this.variableNames =
variables.Select(v => v.Name.Identity).
Concat(constants.Select(c => c.Name.Identity)).
Expand Down Expand Up @@ -78,8 +78,17 @@ public override string ToString() =>
//////////////////////////////////////////////////////////////

public override bool ContainsTypeAndSchedule(
TypeNode type) =>
this.typeNames.Contains(type.TypeIdentity);
TypeNode type,
out Scopes scope)
{
if (this.types.TryGetValue(type.TypeIdentity, out var td))
{
scope = td.Scope.Scope;
return true;
}
scope = default;
return false;
}

public override bool ContainsVariableAndSchedule(
IdentityNode variable) =>
Expand Down
17 changes: 17 additions & 0 deletions chibild/chibild.core/Internal/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,23 @@ public static IEnumerable<T> Prepend<T>(
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> enumerable) =>
new(enumerable);
#endif

#if !NET6_0_OR_GREATER
public static IEnumerable<T> DistinctBy<T, U>(
this IEnumerable<T> enumerable,
Func<T, U> selector)
{
var taken = new HashSet<U>();
foreach (var item in enumerable)
{
var value = selector(item);
if (taken.Add(value))
{
yield return item;
}
}
}
#endif

public static bool UpdateBytes(
MemoryStream ms,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public TupleElementNamesAttribute(string?[] transformNames) =>

namespace chibicc.toolchain.Internal
{
internal static class Utilities
internal static class CommonUtilities
{
private static readonly IFormatProvider invariantCulture = CultureInfo.InvariantCulture;

Expand Down
3 changes: 2 additions & 1 deletion toolchain.common/Parsing/CilParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using chibicc.toolchain.Internal;

namespace chibicc.toolchain.Parsing;

Expand Down Expand Up @@ -53,7 +54,7 @@ private static bool TryLookupScopeDescriptorName(
Token token,
out ScopeDescriptorNode scope)
{
if (!Enum.TryParse<Scopes>(token.Text, true, out var sd))
if (!CommonUtilities.TryParseEnum<Scopes>(token.Text, out var sd))
{
scope = null!;
return false;
Expand Down
Loading

0 comments on commit 0890aa4

Please sign in to comment.