Skip to content

Commit

Permalink
Merge pull request #497 from mortend/build-queue
Browse files Browse the repository at this point in the history
compiler: refactor build queue (beta-3.0)
  • Loading branch information
mortend authored Jun 3, 2023
2 parents 453b4b5 + 40403e7 commit 61df525
Show file tree
Hide file tree
Showing 15 changed files with 311 additions and 248 deletions.
24 changes: 14 additions & 10 deletions src/compiler/core/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class Compiler : LogObject, ICompiler, IScheduler
public readonly NameResolver NameResolver;

// Building
public readonly BuildQueue Queue;
public readonly BlockBuilder BlockBuilder;
public readonly BundleBuilder BundleBuilder;
public readonly TypeBuilder TypeBuilder;
Expand Down Expand Up @@ -91,8 +92,9 @@ public Compiler(Log log, Backend backend, SourceBundle bundle, CompilerOptions o
var data = Data = new BuildData(il, extensions, ilf);
var environment = Environment = new BuildEnvironment(backend, bundle, options, extensions, ilf, this);
var input = Input = new SourceReader(log, bundle, environment);
var blockBuilder = BlockBuilder = new BlockBuilder(backend, il, ilf, resolver, this);
var typeBuilder = TypeBuilder = new TypeBuilder(environment, ilf, resolver, this);
var queue = Queue = new BuildQueue(log, environment, backend, this);
var blockBuilder = BlockBuilder = new BlockBuilder(backend, il, ilf, resolver, this, queue);
var typeBuilder = TypeBuilder = new TypeBuilder(environment, ilf, resolver, this, queue);
BundleBuilder = new BundleBuilder(backend, environment, ilf, this);
AstProcessor = new AstProcessor(il, blockBuilder, typeBuilder, resolver, environment);
UxlProcessor = new UxlProcessor(disk, backend.Name, il, extensions, environment, ilf);
Expand Down Expand Up @@ -132,20 +134,23 @@ public void Compile()
if (Backend.CanLink(bundle))
bundle.Flags |= SourceBundleFlags.CanLink;

using (Log.StartProfiler(TypeBuilder))
TypeBuilder.Build();
using (Log.StartProfiler(Queue))
Queue.BuildTypesAndFunctions();

if (Log.HasErrors)
return;

Backend.ShaderBackend.Initialize(this, BundleBuilder);
using (Log.StartProfiler(UxlProcessor))
UxlProcessor.CompileDocuments();

using (Log.StartProfiler(BlockBuilder))
BlockBuilder.Build();
if (Log.HasErrors)
return;

using (Log.StartProfiler(UxlProcessor))
UxlProcessor.CompileDocuments();
Backend.ShaderBackend.Initialize(this, BundleBuilder);

using (Log.StartProfiler(Queue))
Queue.BuildEverything();

if (Log.HasErrors)
return;

Expand Down Expand Up @@ -205,7 +210,6 @@ public BackendResult Generate(Action<ICompiler> callback)
UxlProcessor.CompileRequirements();
ILStripper.Begin();
Run(_transforms);
TypeBuilder.BuildTypes();

using (Log.StartProfiler(ILStripper))
ILStripper.End();
Expand Down
2 changes: 0 additions & 2 deletions src/compiler/core/IL/EntitySwapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ DataType GetTypeInternal(DataType dt)
args[i] = GetType(dt.FlattenedArguments[i]);

result = TypeBuilder.Parameterize(result.Source, def, args);
TypeBuilder.BuildTypes();
SwapTypes.Add(dt, result);
return result;
}
Expand Down Expand Up @@ -99,7 +98,6 @@ DataType GetTypeInternal(DataType dt)

var def = result.IsGenericDefinition ? result : GetType(dt.GenericDefinition);
result = TypeBuilder.Parameterize(dt.Source, def, args);
TypeBuilder.BuildTypes();
}

SwapTypes.Add(dt, result);
Expand Down
6 changes: 2 additions & 4 deletions src/compiler/core/Syntax/Builders/BlockBuilder.CompileDraw.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@ public Statement CompileDraw(Function func, List<VariableScope> vscopeStack, Ast

var result = new DrawBlock(draw.Source, parent, method, FlattenVariableScopes(vscopeStack));
method.DrawBlocks.Add(result);

EnqueueBlock(result, x => PopulateBlock(draw.Block, x));
_enqueuedDrawClasses.Add(method.DeclaringType);

_queue.EnqueueBlock(result, x => PopulateBlock(draw.Block, x));
_queue.EnqueueDrawClass(method.DeclaringType);
return result.DrawScope;
}

Expand Down
5 changes: 2 additions & 3 deletions src/compiler/core/Syntax/Builders/BlockBuilder.CreateBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ public Block CreateBlock(AstBlock ast, Namescope parent)
Log.Error(src, ErrorCode.E3214, "Block declaration is not allowed in this scope");

_processedBlocks.Add(ast, result);
EnqueueBlock(result, x => PopulateBlock(ast, x));

_queue.EnqueueBlock(result, x => PopulateBlock(ast, x));
return result;
}

Expand Down Expand Up @@ -76,7 +75,7 @@ MetaBlock CreateNodeBlock(AstNode ast, BlockBase parent)
return MetaBlock.Invalid;
}

EnqueueBlock(result, x => PopulateBlock(ast, x));
_queue.EnqueueBlock(result, x => PopulateBlock(ast, x));
return result;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,11 @@ MetaProperty CreateMetaProperty(AstMetaProperty ast, BlockBase parent)
}

var result = new MetaProperty(ast.Name.Source, parent, dt, ast.Name.Symbol, visibility);
_enqueuedProperties.Add(new KeyValuePair<AstMetaProperty, MetaProperty>(ast, result));

_queue.EnqueueMetaProperty(ast, result);
return result;
}

void CompileMetaPropertyDefinitions(AstMetaProperty ast, MetaProperty mp)
internal void CompileMetaPropertyDefinitions(AstMetaProperty ast, MetaProperty mp)
{
var defs = new MetaDefinition[ast.Definitions.Count];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public partial class BlockBuilder
{
internal readonly Dictionary<DataType, HashSet<DataType>> FlattenedTypes = new Dictionary<DataType, HashSet<DataType>>();

void FlattenTypes()
internal void FlattenTypes()
{
FlattenTypes(_il);

Expand Down
38 changes: 5 additions & 33 deletions src/compiler/core/Syntax/Builders/BlockBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,54 +22,27 @@ public partial class BlockBuilder : LogObject
readonly ILFactory _ilf;
readonly NameResolver _resolver;
readonly Compiler _compiler;
readonly BuildQueue _queue;
readonly Dictionary<AstBlockBase, Block> _processedBlocks = new Dictionary<AstBlockBase, Block>();
readonly List<BlockBase> _enqueuedBlocks = new List<BlockBase>();
readonly List<KeyValuePair<AstMetaProperty, MetaProperty>> _enqueuedProperties = new List<KeyValuePair<AstMetaProperty, MetaProperty>>();
readonly HashSet<DataType> _enqueuedDrawClasses = new HashSet<DataType>();

Block _terminals;
readonly HashSet<string> _terminalNames = new HashSet<string>();

public BlockBuilder(
internal BlockBuilder(
Backend backend,
Namespace il,
ILFactory ilf,
NameResolver resolver,
Compiler compiler)
Compiler compiler,
BuildQueue queue)
: base(compiler)
{
_backend = backend;
_il = il;
_ilf = ilf;
_resolver = resolver;
_compiler = compiler;
}

void EnqueueBlock(BlockBase b, Action<BlockBase> populate)
{
b.Populating = populate;
_enqueuedBlocks.Add(b);
}

public void Build()
{
FlattenTypes();

for (int i = 0; i < _enqueuedBlocks.Count; i++)
if (!_enqueuedBlocks[i].Source.Bundle.CanLink)
_enqueuedBlocks[i].Populate();

_enqueuedBlocks.Clear();

for (int i = 0; i < _enqueuedProperties.Count; i++)
CompileMetaPropertyDefinitions(_enqueuedProperties[i].Key, _enqueuedProperties[i].Value);

_enqueuedProperties.Clear();

foreach (var dt in _enqueuedDrawClasses)
DrawCallGenerator.GenerateDrawCalls(_compiler, dt);

_enqueuedDrawClasses.Clear();
_queue = queue;
}

public Block TerminalProperties
Expand All @@ -83,7 +56,6 @@ public Block TerminalProperties

foreach (var t in _backend.ShaderBackend.InputProperties)
CompileTerminalProperty(t);

foreach (var t in _backend.ShaderBackend.OutputProperties)
CompileTerminalProperty(t);
}
Expand Down
189 changes: 189 additions & 0 deletions src/compiler/core/Syntax/Builders/BuildQueue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
using System;
using System.Collections.Generic;
using Uno.Compiler.API.Backends;
using Uno.Compiler.API.Domain.AST.Members;
using Uno.Compiler.API.Domain.AST.Statements;
using Uno.Compiler.API.Domain.Graphics;
using Uno.Compiler.API.Domain.IL;
using Uno.Compiler.API.Domain.IL.Members;
using Uno.Compiler.Core.Syntax.Compilers;
using Uno.Compiler.Core.Syntax.Generators;
using Uno.Logging;

namespace Uno.Compiler.Core.Syntax.Builders
{
public class BuildQueue : LogObject
{
readonly BuildEnvironment _env;
readonly Backend _backend;
readonly Compiler _compiler;
readonly List<BlockBase> _enqueuedBlocks = new List<BlockBase>();
readonly List<KeyValuePair<AstMetaProperty, MetaProperty>> _enqueuedMetaProperties = new List<KeyValuePair<AstMetaProperty, MetaProperty>>();
readonly HashSet<DataType> _enqueuedDrawClasses = new HashSet<DataType>();
readonly List<FunctionCompiler> _enqueuedFunctions = new List<FunctionCompiler>();
readonly List<Entity> _enqueuedAttributes = new List<Entity>();
readonly List<DataType> _enqueuedTypes = new List<DataType>();
readonly List<Action> _enqueuedActions = new List<Action>();
int _assignBaseTypeIndex;
int _populateMembersIndex;

public BuildQueue(Log log, BuildEnvironment env, Backend backend, Compiler compiler)
: base(log)
{
_env = env;
_backend = backend;
_compiler = compiler;
}

internal FunctionCompiler EnqueueFunction(Function func, DataType parameterizedParent, AstScope body)
{
var fc = new FunctionCompiler(_compiler, func, parameterizedParent, body);
func.Tag = fc;

if (_env.IsGeneratingCode)
func.Stats |= EntityStats.CanLink;
else if (body != null)
_enqueuedFunctions.Add(fc);
else if (_compiler.Backend.CanLink(func))
func.Stats |= EntityStats.CanLink;

return fc;
}

internal void EnqueueDrawClass(DataType declaringType)
{
_enqueuedDrawClasses.Add(declaringType);
}

internal void EnqueueType(DataType dt, Action<DataType> assignBaseType, Action<DataType> populate)
{
if (_env.IsGeneratingCode)
{
assignBaseType(dt);
populate(dt);
return;
}

dt.AssigningBaseType = assignBaseType;
dt.PopulatingMembers = x =>
{
populate(x);
x.Stats &= ~EntityStats.PopulatingMembers;
};
dt.Stats |= EntityStats.PopulatingMembers;
_enqueuedTypes.Add(dt);
}

internal void EnqueueAttributes(Entity e, Action<Entity> assign)
{
e.AssigningAttributes = assign;
_enqueuedAttributes.Add(e);
}

internal void EnqueueAttributes(Member e, DataType parameterizedParent, IReadOnlyList<AstAttribute> attributes)
{
if (attributes.Count > 0)
EnqueueAttributes(e, x => e.SetAttributes(_compiler.CompileAttributes(parameterizedParent, attributes)));
}

public void BuildTypes()
{
for (int count = 0, j = 0; count != _enqueuedTypes.Count && j < 10; j++)
{
count = _enqueuedTypes.Count;

while (_assignBaseTypeIndex < count)
_enqueuedTypes[_assignBaseTypeIndex++].AssignBaseType();

for (int i = 0; i < _enqueuedAttributes.Count; i++)
_enqueuedAttributes[i].AssignAttributes();

_enqueuedAttributes.Clear();

while (_populateMembersIndex < count)
if (_backend.CanLink(_enqueuedTypes[_populateMembersIndex]))
_enqueuedTypes[_populateMembersIndex++].Stats |= EntityStats.CanLink;
else
_enqueuedTypes[_populateMembersIndex++].PopulateMembers();

for (int i = 0; i < _enqueuedActions.Count; i++)
_enqueuedActions[i]();

_enqueuedActions.Clear();
}

for (; _populateMembersIndex < _enqueuedTypes.Count; _populateMembersIndex++)
Log.Warning(_enqueuedTypes[_populateMembersIndex].Source, ErrorCode.I0000, "Unable to parameterize " + _enqueuedTypes[_populateMembersIndex].Quote());

_assignBaseTypeIndex = _populateMembersIndex;
}

public void BuildTypesAndFunctions()
{
BuildTypes();

for (var i = 0; i < _enqueuedFunctions.Count; i++)
{
_enqueuedFunctions[i].Compile();
BuildTypes();
}

_enqueuedFunctions.Clear();
_enqueuedTypes.Clear();

_assignBaseTypeIndex = 0;
_populateMembersIndex = 0;
}

public void BuildEverything()
{
_compiler.BlockBuilder.FlattenTypes();

do
{
BuildTypesAndFunctions();
BuildBlocks();
BuildMetaProperties();

foreach (var dt in _enqueuedDrawClasses)
DrawCallGenerator.GenerateDrawCalls(_compiler, dt);

_enqueuedDrawClasses.Clear();

} while (_enqueuedFunctions.Count > 0);
}

public void BuildBlocks()
{
for (var i = 0; i < _enqueuedBlocks.Count; i++)
if (!_enqueuedBlocks[i].Source.Bundle.CanLink)
_enqueuedBlocks[i].Populate();

_enqueuedBlocks.Clear();
}

internal void EnqueueBlock(BlockBase b, Action<BlockBase> populate)
{
b.Populating = populate;
_enqueuedBlocks.Add(b);
}

public void BuildMetaProperties()
{
for (var i = 0; i < _enqueuedMetaProperties.Count; i++)
_compiler.BlockBuilder.CompileMetaPropertyDefinitions(_enqueuedMetaProperties[i].Key, _enqueuedMetaProperties[i].Value);

_enqueuedMetaProperties.Clear();
}

public void EnqueueMetaProperty(AstMetaProperty ast, MetaProperty result)
{
_enqueuedMetaProperties.Add(new KeyValuePair<AstMetaProperty, MetaProperty>(ast, result));
}

internal void Enqueue(Action action)
{
_enqueuedActions.Add(action);
}
}
}
Loading

0 comments on commit 61df525

Please sign in to comment.