From 26dadb18d6c64cbdcf98086480895ed61ed6114f Mon Sep 17 00:00:00 2001 From: Kouji Matsui Date: Mon, 29 Apr 2024 20:32:25 +0900 Subject: [PATCH] WIP --- chibild/chibild.core/CilLinker.cs | 2 +- .../chibild.core/Generating/CodeGenerator.cs | 33 ++- .../Generating/CodeGenerator_Consumer.cs | 259 ++++++++---------- .../Generating/CodeGenerator_Emit.cs | 53 ++-- .../Generating/CodeGenerator_LookupMember.cs | 113 +++----- .../chibild.core/Generating/LookupContext.cs | 109 ++++++++ .../TypeGenerator_FixedLengthArrayType.cs | 1 - .../chibild.core/Internal/CecilUtilities.cs | 40 +-- 8 files changed, 326 insertions(+), 284 deletions(-) create mode 100644 chibild/chibild.core/Generating/LookupContext.cs diff --git a/chibild/chibild.core/CilLinker.cs b/chibild/chibild.core/CilLinker.cs index 1fddc32..5396b73 100644 --- a/chibild/chibild.core/CilLinker.cs +++ b/chibild/chibild.core/CilLinker.cs @@ -353,6 +353,7 @@ injectToAssemblyPath is { } injectPath ? var codeGenerator = new CodeGenerator( this.logger, + targetModule, produceDebuggingInformation); if (!codeGenerator.ConsumeInputs( @@ -364,7 +365,6 @@ injectToAssemblyPath is { } injectPath ? if (!codeGenerator.Emit( loadedFragments, - targetModule, applyOptimization, targetFramework, disableJITOptimization, diff --git a/chibild/chibild.core/Generating/CodeGenerator.cs b/chibild/chibild.core/Generating/CodeGenerator.cs index 080d187..0dd3e59 100644 --- a/chibild/chibild.core/Generating/CodeGenerator.cs +++ b/chibild/chibild.core/Generating/CodeGenerator.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using chibicc.toolchain.Parsing; namespace chibild.Generating; @@ -27,6 +28,7 @@ internal sealed partial class CodeGenerator // during which time multithreading speedup is achieved. private readonly ILogger logger; + private readonly ModuleDefinition targetModule; private readonly bool produceDebuggingInformation; private readonly Queue> delayLookingUpEntries1 = new(); @@ -38,9 +40,11 @@ internal sealed partial class CodeGenerator public CodeGenerator( ILogger logger, + ModuleDefinition targetModule, bool produceDebuggingInformation) { this.logger = logger; + this.targetModule = targetModule; this.produceDebuggingInformation = produceDebuggingInformation; } @@ -67,30 +71,35 @@ private void ConsumeFragment( { currentFragment.ClearDeclarations(); + var context = new LookupContext( + this.targetModule, + currentFragment, + inputFragments); + #if DEBUG foreach (var variable in currentFragment.GlobalVariables) { - this.ConsumeGlobalVariable(currentFragment, inputFragments, variable); + this.ConsumeGlobalVariable(context, variable); } foreach (var constant in currentFragment.GlobalConstants) { - this.ConsumeGlobalConstant(currentFragment, inputFragments, constant); + this.ConsumeGlobalConstant(context, constant); } foreach (var function in currentFragment.Functions) { - this.ConsumeFunction(currentFragment, inputFragments, function); + this.ConsumeFunction(context, function); } foreach (var initializer in currentFragment.Initializers) { - this.ConsumeInitializer(currentFragment, inputFragments, initializer); + this.ConsumeInitializer(context, initializer); } foreach (var enumeration in currentFragment.Enumerations) { - this.ConsumeEnumeration(currentFragment, inputFragments, enumeration); + this.ConsumeEnumeration(context, enumeration); } foreach (var structure in currentFragment.Structures) { - this.ConsumeStructure(currentFragment, inputFragments, structure); + this.ConsumeStructure(context, structure); } #else Parallel.Invoke( @@ -98,42 +107,42 @@ private void ConsumeFragment( { foreach (var variable in currentFragment.GlobalVariables) { - this.ConsumeGlobalVariable(currentFragment, inputFragments, variable); + this.ConsumeGlobalVariable(context, variable); } }, () => { foreach (var constant in currentFragment.GlobalConstants) { - this.ConsumeGlobalConstant(currentFragment, inputFragments, constant); + this.ConsumeGlobalConstant(context, constant); } }, () => { foreach (var function in currentFragment.Functions) { - this.ConsumeFunction(currentFragment, inputFragments, function); + this.ConsumeFunction(context, function); } }, () => { foreach (var initializer in currentFragment.Initializers) { - this.ConsumeInitializer(currentFragment, inputFragments, initializer); + this.ConsumeInitializer(context, initializer); } }, () => { foreach (var enumeration in currentFragment.Enumerations) { - this.ConsumeEnumeration(currentFragment, inputFragments, enumeration); + this.ConsumeEnumeration(context, enumeration); } }, () => { foreach (var structure in currentFragment.Structures) { - this.ConsumeStructure(currentFragment, inputFragments, structure); + this.ConsumeStructure(context, structure); } }); #endif diff --git a/chibild/chibild.core/Generating/CodeGenerator_Consumer.cs b/chibild/chibild.core/Generating/CodeGenerator_Consumer.cs index 28d4249..1e4932c 100644 --- a/chibild/chibild.core/Generating/CodeGenerator_Consumer.cs +++ b/chibild/chibild.core/Generating/CodeGenerator_Consumer.cs @@ -36,8 +36,7 @@ private TypeDefinition CreatePlaceholderInstruction() => ////////////////////////////////////////////////////////////// private void ConsumeGlobalVariable( - ObjectInputFragment currentFragment, - InputFragment[] inputFragments, + LookupContext context, GlobalVariableNode globalVariable) { var fa = globalVariable.Scope.Scope switch @@ -59,28 +58,27 @@ private void ConsumeGlobalVariable( } this.DelayLookingUpType( - currentFragment, - inputFragments, + context, globalVariable.Type, false, (targetModule, type) => CecilUtilities.SetFieldType( field, - CecilUtilities.SafeImport(targetModule, type))); + targetModule.SafeImport(type))); switch (globalVariable.Scope.Scope) { case Scopes.Public: case Scopes.Internal: - currentFragment.AddVariable(field, false); + context.AddVariable(field, false); break; case Scopes.__Module__: this.OutputWarning( globalVariable.Scope.Token, $"Ignored variable module scope, will place on internal scope."); - currentFragment.AddVariable(field, false); + context.AddVariable(field, false); break; default: - currentFragment.AddVariable(field, true); + context.AddVariable(field, true); break; } } @@ -88,8 +86,7 @@ private void ConsumeGlobalVariable( ////////////////////////////////////////////////////////////// private void ConsumeGlobalConstant( - ObjectInputFragment currentFragment, - InputFragment[] inputFragments, + LookupContext context, GlobalConstantNode globalConstant) { var fa = globalConstant.Scope.Scope switch @@ -107,8 +104,7 @@ private void ConsumeGlobalConstant( field.InitialValue = globalConstant.InitializingData.Data; this.DelayLookingUpType( - currentFragment, - inputFragments, + context, globalConstant.Type, false, (_, fieldType) => @@ -118,15 +114,14 @@ private void ConsumeGlobalConstant( "System.Runtime.CompilerServices.IsConst")); this.DelayLookingUpType( - currentFragment, - inputFragments, + context, isConstTypeIdentity, false, (targetModule, isConstType) => { - var modifiedType = CecilUtilities.SafeImport(targetModule, fieldType). + var modifiedType = targetModule.SafeImport(fieldType). MakeOptionalModifierType( - CecilUtilities.SafeImport(targetModule, isConstType)); + targetModule.SafeImport(isConstType)); CecilUtilities.SetFieldType( field, @@ -136,7 +131,7 @@ private void ConsumeGlobalConstant( { CecilUtilities.SetFieldType( field, - CecilUtilities.SafeImport(targetModule, fieldType)); + targetModule.SafeImport(fieldType)); this.OutputWarning( isConstTypeIdentity.Token, @@ -148,16 +143,16 @@ private void ConsumeGlobalConstant( { case Scopes.Public: case Scopes.Internal: - currentFragment.AddConstant(field, false); + context.AddConstant(field, false); break; case Scopes.__Module__: this.OutputWarning( globalConstant.Scope.Token, $"Ignored constant module scope, will place on internal scope."); - currentFragment.AddConstant(field, false); + context.AddConstant(field, false); break; default: - currentFragment.AddConstant(field, true); + context.AddConstant(field, true); break; } } @@ -190,8 +185,7 @@ private MethodDefinition SetupMethodDefinition( ////////////////////////////////////////////////////////////// private void ConsumeLocalVariables( - ObjectInputFragment currentFragment, - InputFragment[] inputFragments, + LookupContext context, MethodDefinition method, LocalVariableNode[] localVariables, Dictionary vdis) @@ -204,8 +198,7 @@ private void ConsumeLocalVariables( this.CreatePlaceholderType()); this.DelayLookingUpType( - currentFragment, - inputFragments, + context, localVariable.Type, false, (targetModule, type) => @@ -217,15 +210,14 @@ private void ConsumeLocalVariables( var elementType = resolved.GetElementType(); if (elementType.IsValueType) { - variable.VariableType = CecilUtilities.SafeImport( - targetModule, + variable.VariableType = targetModule.SafeImport( type). MakePinnedType(); return; } } variable.VariableType = - CecilUtilities.SafeImport(targetModule, type); + context.SafeImport(type); }); if (localVariable.Name is { } name) @@ -280,8 +272,7 @@ private void DelayInsertingSequencePoint( } private void ConsumeInstructions( - ObjectInputFragment currentFragment, - InputFragment[] inputFragments, + LookupContext context, MethodDefinition method, InstructionNode[] instructions, Dictionary vdis) @@ -327,12 +318,11 @@ private void ConsumeInstructions( opCode, this.CreatePlaceholderField()); this.DelayLookingUpField( - currentFragment, - inputFragments, + context, field, false, (targetModule, f) => cilInstruction.Operand = - CecilUtilities.SafeImport(targetModule, f)); + targetModule.SafeImport(f)); break; case TypeInstructionNode(_, var type): @@ -340,12 +330,11 @@ private void ConsumeInstructions( opCode, this.CreatePlaceholderType()); this.DelayLookingUpType( - currentFragment, - inputFragments, + context, type, false, (targetModule, t) => cilInstruction.Operand = - CecilUtilities.SafeImport(targetModule, t)); + targetModule.SafeImport(t)); break; case MetadataTokenInstructionNode(_, var identity, var signature): @@ -353,13 +342,12 @@ private void ConsumeInstructions( opCode, this.CreatePlaceholderType()); this.DelayLookingUpMember( - currentFragment, - inputFragments, + context, identity, signature, false, (targetModule, m) => cilInstruction.Operand = - CecilUtilities.SafeImport(targetModule, m)); + targetModule.SafeImport(m)); break; case NumericValueInstructionNode(_, var (value, _)): @@ -457,13 +445,12 @@ private void ConsumeInstructions( opCode, this.CreatePlaceholderMethod()); this.DelayLookingUpMethod( - currentFragment, - inputFragments, + context, function, signature, false, (targetModule, m) => cilInstruction.Operand = - CecilUtilities.SafeImport(targetModule, m)); + targetModule.SafeImport(m)); break; case SignatureInstructionNode(_, var signature): @@ -485,12 +472,11 @@ private void ConsumeInstructions( callSite); this.DelayLookingUpType( - currentFragment, - inputFragments, + context, signature.ReturnType, false, (targetModule, t) => callSite.ReturnType = - CecilUtilities.SafeImport(targetModule, t)); + targetModule.SafeImport(t)); foreach (var (parameterType, parameterName, _) in signature.Parameters) { @@ -500,12 +486,11 @@ private void ConsumeInstructions( callSite.Parameters.Add(parameter); this.DelayLookingUpType( - currentFragment, - inputFragments, + context, parameterType, false, (targetModule, t) => parameter.ParameterType = - CecilUtilities.SafeImport(targetModule, t)); + targetModule.SafeImport(t)); } break; @@ -580,8 +565,7 @@ private void DelayInsertingVariableNames( } private void ConsumeFunction( - ObjectInputFragment currentFragment, - InputFragment[] inputFragments, + LookupContext context, FunctionNode function) { var ma = function.Scope.Scope switch @@ -615,14 +599,13 @@ private void ConsumeFunction( }; this.DelayLookingUpType( - currentFragment, - inputFragments, + context, function.Signature.ReturnType, false, (targetModule, type) => { method.ReturnType = - CecilUtilities.SafeImport(targetModule, type); + targetModule.SafeImport(type); // Special case: Force 1 byte footprint on boolean type. if (type.FullName == "System.Boolean") @@ -640,14 +623,13 @@ private void ConsumeFunction( var capturedParameter = method.Parameters[index]; this.DelayLookingUpType( - currentFragment, - inputFragments, + context, function.Signature.Parameters[index].ParameterType, false, (targetModule, type) => { capturedParameter.ParameterType = - CecilUtilities.SafeImport(targetModule, type); + targetModule.SafeImport(type); // Special case: Force 1 byte footprint on boolean type. if (type.FullName == "System.Boolean") @@ -664,15 +646,13 @@ private void ConsumeFunction( var vdis = new Dictionary(); this.ConsumeLocalVariables( - currentFragment, - inputFragments, + context, method, function.LocalVariables, vdis); this.ConsumeInstructions( - currentFragment, - inputFragments, + context, method, function.Instructions, vdis); @@ -687,13 +667,13 @@ private void ConsumeFunction( { case Scopes.Public: case Scopes.Internal: - currentFragment.AddFunction(method, false); + context.AddFunction(method, false); break; case Scopes.__Module__: - currentFragment.AddModuleFunction(method); + context.AddModuleFunction(method); break; default: - currentFragment.AddFunction(method, true); + context.AddFunction(method, true); break; } } @@ -701,8 +681,7 @@ private void ConsumeFunction( ////////////////////////////////////////////////////////////// private void ConsumeInitializer( - ObjectInputFragment currentFragment, - InputFragment[] inputFragments, + LookupContext context, InitializerNode initializer) { var method = this.SetupMethodDefinition( @@ -717,15 +696,13 @@ private void ConsumeInitializer( var vdis = new Dictionary(); this.ConsumeLocalVariables( - currentFragment, - inputFragments, + context, method, initializer.LocalVariables, vdis); this.ConsumeInstructions( - currentFragment, - inputFragments, + context, method, initializer.Instructions, vdis); @@ -740,16 +717,16 @@ private void ConsumeInitializer( { case Scopes.Public: case Scopes.Internal: - currentFragment.AddInitializer(method, false); + context.AddInitializer(method, false); break; case Scopes.__Module__: this.OutputWarning( initializer.Scope.Token, $"Ignored initializer module scope, will place on internal scope."); - currentFragment.AddInitializer(method, false); + context.AddInitializer(method, false); break; default: - currentFragment.AddInitializer(method, true); + context.AddInitializer(method, true); break; } } @@ -757,8 +734,7 @@ private void ConsumeInitializer( ////////////////////////////////////////////////////////////// private void ConsumeEnumeration( - ObjectInputFragment currentFragment, - InputFragment[] inputFragments, + LookupContext context, EnumerationNode enumeration) { var typeAttributes = enumeration.Scope.Scope switch @@ -768,6 +744,14 @@ private void ConsumeEnumeration( _ => TypeAttributes.NestedPublic | TypeAttributes.Sealed, }; + if (!context.UnsafeGetCoreType("System.Enum", out var setr)) + { + setr = this.CreatePlaceholderType(); + this.OutputError( + enumeration.Token, + $"Could not find System.Enum type."); + } + var enumerationType = new TypeDefinition( enumeration.Scope.Scope switch { @@ -778,59 +762,48 @@ private void ConsumeEnumeration( }, enumeration.Name.Identity, typeAttributes, - this.CreatePlaceholderType()); // System.Enum + context.SafeImport(setr)); this.DelayLookingUpType( - currentFragment, - inputFragments, + context, enumeration.UnderlyingType, false, (_, utr) => { - this.DelayLookingUpType( - currentFragment, - inputFragments, - new IdentityNode(enumeration.Token.AsText("System.Enum")), - false, - (targetModule, setr) => - { - enumerationType.BaseType = - CecilUtilities.SafeImport(targetModule, setr); - var ut = CecilUtilities.SafeImport(targetModule, utr); + var ut = targetModule.SafeImport(utr); - var enumerationValueField = new FieldDefinition( - "value__", - FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName, - ut); - enumerationType.Fields.Add(enumerationValueField); + var enumerationValueField = new FieldDefinition( + "value__", + FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName, + ut); + enumerationType.Fields.Add(enumerationValueField); - foreach (var enumValue in enumeration.Values) - { - var field = new FieldDefinition( - enumValue.Name.Identity, - FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal, - ut); - field.Constant = enumValue.Value!.Value; + foreach (var enumValue in enumeration.Values) + { + var field = new FieldDefinition( + enumValue.Name.Identity, + FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal, + ut); + field.Constant = enumValue.Value!.Value; - enumerationType.Fields.Add(field); - } - }); + enumerationType.Fields.Add(field); + } }); switch (enumeration.Scope.Scope) { case Scopes.Public: case Scopes.Internal: - currentFragment.AddEnumeration(enumerationType, false); + context.AddEnumeration(enumerationType, false); break; case Scopes.__Module__: this.OutputWarning( enumeration.Scope.Token, $"Ignored enumeration module scope, will place on internal scope."); - currentFragment.AddEnumeration(enumerationType, false); + context.AddEnumeration(enumerationType, false); break; default: - currentFragment.AddEnumeration(enumerationType, true); + context.AddEnumeration(enumerationType, true); break; } } @@ -838,8 +811,7 @@ private void ConsumeEnumeration( ////////////////////////////////////////////////////////////// private void ConsumeStructure( - ObjectInputFragment currentFragment, - InputFragment[] inputFragments, + LookupContext context, StructureNode structure) { var typeAttributes = structure.Scope.Scope switch @@ -852,6 +824,14 @@ private void ConsumeStructure( typeAttributes |= (structure.IsExplicit?.Value ?? false) ? TypeAttributes.ExplicitLayout : TypeAttributes.SequentialLayout; + if (!context.UnsafeGetCoreType("System.ValueType", out var vttr)) + { + vttr = this.CreatePlaceholderType(); + this.OutputError( + structure.Token, + $"Could not find System.ValueType type."); + } + var structureType = new TypeDefinition( structure.Scope.Scope switch { @@ -862,7 +842,7 @@ private void ConsumeStructure( }, structure.Name.Identity, typeAttributes, - this.CreatePlaceholderType()); // System.ValueType + context.SafeImport(vttr)); if (structure.PackSize?.Value is { } packSize) { @@ -870,62 +850,49 @@ private void ConsumeStructure( structureType.ClassSize = 0; } - this.DelayLookingUpType( - currentFragment, - inputFragments, - new IdentityNode(structure.Token.AsText("System.ValueType")), - false, - (targetModule, vttr) => + foreach (var structureField in structure.Fields) + { + var fieldAttribute = structureField.Scope.Scope switch { - structureType.BaseType = - CecilUtilities.SafeImport(targetModule, vttr); - - foreach (var structureField in structure.Fields) - { - var fieldAttribute = structureField.Scope.Scope switch - { - Scopes.Public => FieldAttributes.Public, - _ => FieldAttributes.Assembly, - }; - - var field = new FieldDefinition( - structureField.Name.Identity, - fieldAttribute, - this.CreatePlaceholderType()); + Scopes.Public => FieldAttributes.Public, + _ => FieldAttributes.Assembly, + }; - this.DelayLookingUpType( - currentFragment, - inputFragments, - structureField.Type, - false, - (_, ftr) => CecilUtilities.SetFieldType( - field, - CecilUtilities.SafeImport(targetModule, ftr))); + var field = new FieldDefinition( + structureField.Name.Identity, + fieldAttribute, + this.CreatePlaceholderType()); - if (typeAttributes.HasFlag(TypeAttributes.ExplicitLayout)) - { - field.Offset = (int)structureField.Offset!.Value; - } + this.DelayLookingUpType( + context, + structureField.Type, + false, + (_, ftr) => CecilUtilities.SetFieldType( + field, + targetModule.SafeImport(ftr))); - structureType.Fields.Add(field); - } + if (typeAttributes.HasFlag(TypeAttributes.ExplicitLayout)) + { + field.Offset = (int)structureField.Offset!.Value; + } - }); + structureType.Fields.Add(field); + } switch (structure.Scope.Scope) { case Scopes.Public: case Scopes.Internal: - currentFragment.AddStructure(structureType, false); + context.AddStructure(structureType, false); break; case Scopes.__Module__: this.OutputWarning( structure.Scope.Token, $"Ignored structure module scope, will place on internal scope."); - currentFragment.AddEnumeration(structureType, false); + context.AddEnumeration(structureType, false); break; default: - currentFragment.AddStructure(structureType, true); + context.AddStructure(structureType, true); break; } } diff --git a/chibild/chibild.core/Generating/CodeGenerator_Emit.cs b/chibild/chibild.core/Generating/CodeGenerator_Emit.cs index e8f44eb..63ded75 100644 --- a/chibild/chibild.core/Generating/CodeGenerator_Emit.cs +++ b/chibild/chibild.core/Generating/CodeGenerator_Emit.cs @@ -29,12 +29,16 @@ private void AddFundamentalAttributes( TargetFramework? targetFramework, bool? disableJITOptimization) { + var context = new LookupContext( + this.targetModule, + null, + inputFragments); + // Apply TargetFrameworkAttribute if could be imported. if (targetFramework != null) { this.DelayLookingUpMethod( - null, - inputFragments, + context, IdentityNode.Create( "System.Runtime.Versioning.TargetFrameworkAttribute..ctor"), TypeParser.UnsafeParse( @@ -43,7 +47,7 @@ private void AddFundamentalAttributes( (targetModule, tfacr) => { var tfa = new CustomAttribute( - CecilUtilities.SafeImport(targetModule, tfacr)); + targetModule.SafeImport(tfacr)); tfa.ConstructorArguments.Add(new( targetModule.TypeSystem.String, targetFramework.ToString())); @@ -63,15 +67,13 @@ private void AddFundamentalAttributes( if (disableJITOptimization ?? false) { this.DelayLookingUpType( - null, - inputFragments, + context, IdentityNode.Create("System.Diagnostics.DebuggableAttribute.DebuggingModes"), false, (targetModule, dmtr) => { this.DelayLookingUpMethod( - null, - inputFragments, + context, IdentityNode.Create("System.Diagnostics.DebuggableAttribute..ctor"), TypeParser.UnsafeParse( Token.Identity("System.Void(System.Diagnostics.DebuggableAttribute.DebuggingModes)")), @@ -79,9 +81,9 @@ private void AddFundamentalAttributes( (_, dacr) => { var da = new CustomAttribute( - CecilUtilities.SafeImport(targetModule, dacr)); + targetModule.SafeImport(dacr)); da.ConstructorArguments.Add(new( - CecilUtilities.SafeImport(targetModule, dmtr), + targetModule.SafeImport(dmtr), (int)(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations))); targetModule.Assembly.CustomAttributes.Add(da); @@ -104,37 +106,33 @@ private void AddFundamentalAttributes( // Apply pointer visualizers if could be imported. this.DelayLookingUpType( - null, - inputFragments, + context, IdentityNode.Create("C.type.__pointer_visualizer"), false, (_, pvtr) => { this.DelayLookingUpType( - null, - inputFragments, + context, IdentityNode.Create("System.Type"), false, - (targetModule, sttf) => + (_, sttf) => { this.DelayLookingUpMethod( - null, - inputFragments, + context, IdentityNode.Create("System.Diagnostics.DebuggerTypeProxyAttribute..ctor"), TypeParser.UnsafeParse(Token.Identity("System.Void(System.Type)")), false, - (_, dtpacr) => + (targetModule, dtpacr) => { - dtpacr = CecilUtilities.SafeImport(targetModule, dtpacr); - pvtr = CecilUtilities.SafeImport(targetModule, pvtr); - sttf = CecilUtilities.SafeImport(targetModule, sttf); + dtpacr = targetModule.SafeImport(dtpacr); + pvtr = targetModule.SafeImport(pvtr); + sttf = targetModule.SafeImport(sttf); foreach (var targetTypeName in new[] { "System.Void*", "System.Byte*", "System.SByte*", }) { this.DelayLookingUpType( - null, - inputFragments, + context, IdentityNode.Create(targetTypeName), false, (_, ttr) => @@ -143,7 +141,7 @@ private void AddFundamentalAttributes( dtpa.ConstructorArguments.Add(new(sttf, pvtr)); dtpa.Properties.Add(new( "Target", - new(sttf, CecilUtilities.SafeImport(targetModule, ttr)))); + new(sttf, targetModule.SafeImport(ttr)))); targetModule.Assembly.CustomAttributes.Add(dtpa); this.logger.Trace( @@ -417,7 +415,6 @@ private void OptimizeMethods( public bool Emit( InputFragment[] inputFragments, - ModuleDefinition targetModule, bool applyOptimization, TargetFramework? targetFramework, bool? disableJITOptimization, @@ -435,21 +432,21 @@ public bool Emit( { this.EmitMembers( fragment, - targetModule); + this.targetModule); } // Apply all delayed looking up (types). while (this.delayLookingUpEntries1.Count >= 1) { var action = this.delayLookingUpEntries1.Dequeue(); - action(targetModule); + action(this.targetModule); } // Apply all delayed looking up (not types). while (this.delayLookingUpEntries2.Count >= 1) { var action = this.delayLookingUpEntries2.Dequeue(); - action(targetModule); + action(this.targetModule); } // Assert reverse dependencies are nothing. @@ -484,7 +481,7 @@ public bool Emit( if (entryPointSymbol != null) { this.AssignEntryPoint( - targetModule, + this.targetModule, entryPointSymbol); } diff --git a/chibild/chibild.core/Generating/CodeGenerator_LookupMember.cs b/chibild/chibild.core/Generating/CodeGenerator_LookupMember.cs index 55443d8..f9a60c9 100644 --- a/chibild/chibild.core/Generating/CodeGenerator_LookupMember.cs +++ b/chibild/chibild.core/Generating/CodeGenerator_LookupMember.cs @@ -37,59 +37,19 @@ private void DelayLookingUpAction2(Action action) } ////////////////////////////////////////////////////////////// - - private bool TryLookUpTypeImmediate( - ModuleDefinition targetModule, - ObjectInputFragment? currentFragment, - InputFragment[] inputFragments, - TypeNode type, - bool isFileScoped, - out TypeReference tr) - { - // Step 1: Check on current fragment. - if (currentFragment?.TryGetType( - type, - targetModule, - out var tr1) ?? false) - { - tr = tr1; - return true; - } - - // Step 2: Check on entire fragments. - if (!isFileScoped) - { - foreach (var fragment in inputFragments) - { - if (fragment != currentFragment && - fragment.TryGetType( - type, - targetModule, - out var tr2)) - { - tr = tr2; - return true; - } - } - } - - tr = null!; - return false; - } private bool InternalDelayLookingUpType( - ObjectInputFragment? currentFragment, - InputFragment[] inputFragments, + LookupContext context, TypeNode type, bool isFileScoped, Action action) { // Step 1: Check on current fragment. - if (currentFragment?.ContainsTypeAndSchedule(type) ?? false) + if (context.CurrentFragment?.ContainsTypeAndSchedule(type) ?? false) { this.DelayLookingUpAction1(targetModule => { - if (currentFragment.TryGetType( + if (context.CurrentFragment.TryGetType( type, targetModule, out var tr)) @@ -108,9 +68,9 @@ private bool InternalDelayLookingUpType( if (!isFileScoped) { InputFragment? foundFragment = null; - foreach (var fragment in inputFragments) + foreach (var fragment in context.InputFragments) { - if (fragment != currentFragment && + if (fragment != context.CurrentFragment && fragment.ContainsTypeAndSchedule(type)) { // Found the symbol. @@ -163,8 +123,7 @@ private static void InvokeLookUpTypeActionIfCompleted( } private void DelayLookingUpType( - ObjectInputFragment? currentFragment, - InputFragment[] inputFragments, + LookupContext context, TypeNode type, bool isFileScoped, Action action, @@ -195,8 +154,7 @@ private void DelayLookingUpType( foreach (var requiredType in requiredPrioritizedTypes) { if (!this.InternalDelayLookingUpType( - currentFragment, - inputFragments, + context, requiredType, isFileScoped, (targetModule, tr) => @@ -205,7 +163,7 @@ private void DelayLookingUpType( resolvedTypeReferences.Add( requiredType.CilTypeName, // By importing the type in advance, it is possible to use the type as it is after synthesis. - CecilUtilities.SafeImport(targetModule, tr)); + targetModule.SafeImport(tr)); // Invoke action if all types resolved. InvokeLookUpTypeActionIfCompleted( @@ -233,7 +191,7 @@ private void DelayLookingUpType( // Append got .NET type. resolvedTypeReferences.Add( flat.CilTypeName, - CecilUtilities.SafeImport(targetModule, flatr)); + targetModule.SafeImport(flatr)); // Invoke action if all types resolved. InvokeLookUpTypeActionIfCompleted( @@ -269,15 +227,13 @@ private void DelayLookingUpType( } private void DelayLookingUpType( - ObjectInputFragment? currentFragment, - InputFragment[] inputFragments, + LookupContext context, IdentityNode type, bool isFileScoped, Action action, Action? didNotResolve = null) => this.DelayLookingUpType( - currentFragment, - inputFragments, + context, TypeParser.TryParse(type.Token, out var t) ? t : throw new InvalidOperationException(), isFileScoped, @@ -286,20 +242,19 @@ private void DelayLookingUpType( ////////////////////////////////////////////////////////////// - private void DelayLookingUpField( - ObjectInputFragment? currentFragment, - InputFragment[] inputFragments, + private void DelayLookingUpField( + LookupContext context, IdentityNode field, bool isFileScoped, Action action, Action? didNotResolve = null) { // Step 1: Check on current fragment. - if (currentFragment?.ContainsVariableAndSchedule(field) ?? false) + if (context.CurrentFragment?.ContainsVariableAndSchedule(field) ?? false) { this.DelayLookingUpAction2(targetModule => { - if (currentFragment.TryGetField( + if (context.CurrentFragment.TryGetField( field, targetModule, out var tr)) @@ -318,9 +273,9 @@ private void DelayLookingUpField( if (!isFileScoped) { InputFragment? foundFragment = null; - foreach (var fragment in inputFragments) + foreach (var fragment in context.InputFragments) { - if (fragment != currentFragment && + if (fragment != context.CurrentFragment && fragment.ContainsVariableAndSchedule(field)) { // Found the symbol. @@ -364,8 +319,7 @@ private void DelayLookingUpField( ////////////////////////////////////////////////////////////// private void DelayLookingUpMethod( - ObjectInputFragment? currentFragment, - InputFragment[] inputFragments, + LookupContext context, IdentityNode function, FunctionSignatureNode? signature, bool isFileScoped, @@ -373,13 +327,13 @@ private void DelayLookingUpMethod( Action? didNotResolve = null) { // Step 1: Check on current fragment. - if (currentFragment?.ContainsFunctionAndSchedule( + if (context.CurrentFragment?.ContainsFunctionAndSchedule( function, signature) ?? false) { this.DelayLookingUpAction2(targetModule => { - if (currentFragment.TryGetMethod( + if (context.CurrentFragment.TryGetMethod( function, signature, targetModule, @@ -399,9 +353,9 @@ private void DelayLookingUpMethod( if (!isFileScoped) { InputFragment? foundFragment = null; - foreach (var fragment in inputFragments) + foreach (var fragment in context.InputFragments) { - if (fragment != currentFragment && + if (fragment != context.CurrentFragment && fragment.ContainsFunctionAndSchedule( function, signature)) @@ -456,8 +410,7 @@ private enum FoundMembers } private void DelayLookingUpMember( - ObjectInputFragment? currentFragment, - InputFragment[] inputFragments, + LookupContext context, IdentityNode member, FunctionSignatureNode? functionSignature, bool isFileScoped, @@ -470,11 +423,11 @@ private void DelayLookingUpMember( { type = TypeParser.TryParse(member.Token, out var t) ? t : null; if (type != null && - (currentFragment?.ContainsTypeAndSchedule(type) ?? false)) + (context.CurrentFragment?.ContainsTypeAndSchedule(type) ?? false)) { this.DelayLookingUpAction1(targetModule => { - if (currentFragment.TryGetType( + if (context.CurrentFragment.TryGetType( type, targetModule, out var tr)) @@ -489,11 +442,11 @@ private void DelayLookingUpMember( return; } - if (currentFragment?.ContainsVariableAndSchedule(member) ?? false) + if (context.CurrentFragment?.ContainsVariableAndSchedule(member) ?? false) { this.DelayLookingUpAction2(targetModule => { - if (currentFragment.TryGetField( + if (context.CurrentFragment.TryGetField( member, targetModule, out var tr)) @@ -509,13 +462,13 @@ private void DelayLookingUpMember( } } - if (currentFragment?.ContainsFunctionAndSchedule( + if (context.CurrentFragment?.ContainsFunctionAndSchedule( member, functionSignature) ?? false) { this.DelayLookingUpAction2(targetModule => { - if (currentFragment.TryGetMethod( + if (context.CurrentFragment.TryGetMethod( member, functionSignature, targetModule, @@ -539,9 +492,9 @@ private void DelayLookingUpMember( if (functionSignature == null) { - foreach (var fragment in inputFragments) + foreach (var fragment in context.InputFragments) { - if (fragment != currentFragment) + if (fragment != context.CurrentFragment) { if (type != null && fragment.ContainsTypeAndSchedule(type)) @@ -570,9 +523,9 @@ private void DelayLookingUpMember( } else { - foreach (var fragment in inputFragments) + foreach (var fragment in context.InputFragments) { - if (fragment != currentFragment && + if (fragment != context.CurrentFragment && fragment.ContainsFunctionAndSchedule( member, functionSignature)) diff --git a/chibild/chibild.core/Generating/LookupContext.cs b/chibild/chibild.core/Generating/LookupContext.cs new file mode 100644 index 0000000..c8c3280 --- /dev/null +++ b/chibild/chibild.core/Generating/LookupContext.cs @@ -0,0 +1,109 @@ +///////////////////////////////////////////////////////////////////////////////////// +// +// chibicc-toolchain - The specialized backend toolchain for chibicc-cil +// Copyright (c) Kouji Matsui(@kozy_kekyo, @kekyo @mastodon.cloud) +// +// Licensed under MIT: https://opensource.org/licenses/MIT +// +///////////////////////////////////////////////////////////////////////////////////// + +using chibicc.toolchain.Parsing; +using chibicc.toolchain.Tokenizing; +using Mono.Cecil; +using System; +using chibild.Internal; + +namespace chibild.Generating; + +internal sealed class LookupContext +{ + private readonly ModuleDefinition targetModule; + + public readonly ObjectInputFragment? CurrentFragment; + public readonly InputFragment[] InputFragments; + + public LookupContext( + ModuleDefinition targetModule, + ObjectInputFragment? currentFragment, + InputFragment[] inputFragments) + { + this.targetModule = targetModule; + this.CurrentFragment = currentFragment; + this.InputFragments = inputFragments; + } + + ////////////////////////////////////////////////////////////// + + public TypeReference SafeImport(TypeReference tr) => + this.targetModule.SafeImport(tr); + + public FieldReference SafeImport(FieldReference fr) => + this.targetModule.SafeImport(fr); + + public MethodReference SafeImport(MethodReference mr) => + this.targetModule.SafeImport(mr); + + public MemberReference SafeImport(MemberReference member) => + member switch + { + TypeReference type => this.SafeImport(type), + FieldReference field => this.SafeImport(field), + MethodReference method => this.SafeImport(method), + _ => throw new InvalidOperationException(), + }; + + ////////////////////////////////////////////////////////////// + + public bool UnsafeGetCoreType( + string coreTypeName, + out TypeReference tr) + { + // This getter is only used for looking up core library types. + var coreType = new TypeIdentityNode(coreTypeName, Token.Unknown); + + if (this.CurrentFragment?.TryGetType( + coreType, + this.targetModule, + out tr) ?? false) + { + return true; + } + + foreach (var fragment in this.InputFragments) + { + if (fragment.TryGetType( + coreType, + this.targetModule, + out tr)) + { + return true; + } + } + + tr = null!; + return false; + } + + ////////////////////////////////////////////////////////////// + + public void AddVariable(FieldDefinition variable, bool isFileScope) => + this.CurrentFragment!.AddVariable(variable, isFileScope); + + public void AddConstant(FieldDefinition constant, bool isFileScope) => + this.CurrentFragment!.AddConstant(constant, isFileScope); + + public void AddFunction(MethodDefinition function, bool isFileScope) => + this.CurrentFragment!.AddFunction(function, isFileScope); + + public void AddInitializer(MethodDefinition initializer, bool isFileScope) => + this.CurrentFragment!.AddInitializer(initializer, isFileScope); + + public void AddModuleFunction(MethodDefinition function) => + this.CurrentFragment!.AddModuleFunction(function); + + public void AddEnumeration(TypeDefinition enumeration, bool isFileScope) => + this.CurrentFragment!.AddEnumeration(enumeration, isFileScope); + + public void AddStructure(TypeDefinition structure, bool isFileScope) => + this.CurrentFragment!.AddStructure(structure, isFileScope); +} diff --git a/chibild/chibild.core/Generating/TypeGenerator_FixedLengthArrayType.cs b/chibild/chibild.core/Generating/TypeGenerator_FixedLengthArrayType.cs index 2d9f44f..9e9b613 100644 --- a/chibild/chibild.core/Generating/TypeGenerator_FixedLengthArrayType.cs +++ b/chibild/chibild.core/Generating/TypeGenerator_FixedLengthArrayType.cs @@ -7,7 +7,6 @@ // ///////////////////////////////////////////////////////////////////////////////////// -using chibicc.toolchain.Logging; using chibicc.toolchain.Parsing; using chibicc.toolchain.Tokenizing; using chibild.Internal; diff --git a/chibild/chibild.core/Internal/CecilUtilities.cs b/chibild/chibild.core/Internal/CecilUtilities.cs index 4b2cb70..ac42587 100644 --- a/chibild/chibild.core/Internal/CecilUtilities.cs +++ b/chibild/chibild.core/Internal/CecilUtilities.cs @@ -196,24 +196,32 @@ public static void SetFieldType( } } - public static TypeReference SafeImport(ModuleDefinition targetModule, TypeReference type) => - (type.Module?.Equals(targetModule) ?? type is TypeDefinition) ? - type : targetModule.ImportReference(type); - - public static FieldReference SafeImport(ModuleDefinition targetModule, FieldReference field) => - (field.Module?.Equals(targetModule) ?? field is FieldDefinition) ? - field : targetModule.ImportReference(field); - - public static MethodReference SafeImport(ModuleDefinition targetModule, MethodReference method) => - (method.Module?.Equals(targetModule) ?? method is MethodDefinition) ? - method : targetModule.ImportReference(method); - - public static MemberReference SafeImport(ModuleDefinition targetModule, MemberReference member) => + public static TypeReference SafeImport( + this ModuleDefinition targetModule, + TypeReference tr) => + (tr.Module?.Equals(targetModule) ?? tr is TypeDefinition) ? + tr : targetModule.ImportReference(tr); + + public static FieldReference SafeImport( + this ModuleDefinition targetModule, + FieldReference fr) => + (fr.Module?.Equals(targetModule) ?? fr is FieldDefinition) ? + fr : targetModule.ImportReference(fr); + + public static MethodReference SafeImport( + this ModuleDefinition targetModule, + MethodReference mr) => + (mr.Module?.Equals(targetModule) ?? mr is MethodDefinition) ? + mr : targetModule.ImportReference(mr); + + public static MemberReference SafeImport( + this ModuleDefinition targetModule, + MemberReference member) => member switch { - TypeReference type => SafeImport(targetModule, type), - FieldReference field => SafeImport(targetModule, field), - MethodReference method => SafeImport(targetModule, method), + TypeReference type => targetModule.SafeImport(type), + FieldReference field => targetModule.SafeImport(field), + MethodReference method => targetModule.SafeImport(method), _ => throw new InvalidOperationException(), }; }