private void GenerateTypesList() { foreach (var nmKVP in EnvironmentBuilder !.NamespaceBuilders) { var namespaceName = nmKVP.Key; var namespaceBuilder = nmKVP.Value; var namespaceData = namespaceBuilder.NamespaceData; using var newTypesList = new StructPooledList <Pointer <ES_TypeInfo> > (CL_ClearMode.Auto); newTypesList.EnsureCapacity( namespaceBuilder.ClassBuilders.Count + namespaceBuilder.StructBuilders.Count + namespaceBuilder.EnumBuilders.Count ); foreach (var classKVP in namespaceBuilder.ClassBuilders) { var classBuilder = classKVP.Value; newTypesList.Add(&classBuilder.ClassData->TypeInfo); } foreach (var structKVP in namespaceBuilder.StructBuilders) { var structBuilder = structKVP.Value; newTypesList.Add(&structBuilder.StructData->TypeInfo); } foreach (var enumKVP in namespaceBuilder.EnumBuilders) { var enumBuilder = enumKVP.Value; newTypesList.Add(&enumBuilder.EnumData->TypeInfo); } } }
private static ExpressionSyntax CompileCode_NewObject(ES_TypeInfo *type, ExpressionSyntax?assignValue) { var isReference = type->TypeTag == ES_TypeTag.Reference; // Get the roslyn type. var intPtrType = IdentifierName(nameof(IntPtr)); var roslynType = GetRoslynType(type); // Generate the member access. var accessExpr = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(ES_GarbageCollector)), GenericName(Identifier(nameof(ES_GarbageCollector.AllocObject))).WithTypeArgumentList( TypeArgumentList(SingletonSeparatedList(!isReference ? roslynType : intPtrType)) ) ); // Construct the args list. using var argsList = new StructPooledList <SyntaxNodeOrToken> (CL_ClearMode.Auto); argsList.EnsureCapacity(3); // Generate the pointer type syntax for the type pointer. var pointerTypeSyntax = PointerType(IdentifierName(nameof(ES_TypeInfo))); // Add the type pointer. argsList.Add(Argument(PointerLiteral(type, pointerTypeSyntax))); // Add the "pinned" bool. argsList.Add(Token(SyntaxKind.CommaToken)); argsList.Add(Argument(BoolLiteral(false))); // Add the value to assign. if (assignValue is not null) { argsList.Add(Token(SyntaxKind.CommaToken)); if (isReference) { assignValue = CastExpression(intPtrType, assignValue); } argsList.Add(Argument(assignValue)); } // Generate the function call. ExpressionSyntax ret = InvocationExpression(accessExpr) .WithArgumentList(ArgumentList(SeparatedListSpan <ArgumentSyntax> (argsList.Span))); if (isReference) { ret = CastExpression(PointerType(roslynType), ret); } return(ret); }
private static string MangleDefaultConstructorName(ES_TypeInfo *typeName, bool isStatic) { // Sample name: "struct.System.Numerics__Vector2" using var mangleChars = new StructPooledList <char> (CL_ClearMode.Auto); // The prefix. if (!isStatic) { mangleChars.AddRange("defaultConstructor!"); } else { mangleChars.AddRange("defaultStaticConstructor!"); } // The namespace. var namespaceName = typeName->Name.NamespaceName.Span; ES_Encodings.Identifier.GetChars(namespaceName, mangleChars.AddSpan(namespaceName.Length)); // The mangled namespace separator. mangleChars.Add('_', 2); // The function name. var structName = typeName->Name.TypeName.Span; ES_Encodings.Identifier.GetChars(structName, mangleChars.AddSpan(structName.Length)); return(mangleChars.Span.GetPooledString()); }
private static void CompileStruct(ref PassData passData, ESIR_Struct structDef) { using var memberTypes = new StructPooledList <SyntaxNode> (CL_ClearMode.Auto); var mangledStructName = MangleTypeName(structDef.Type); // Create the struct's members. foreach (var member in structDef.Members.Elements) { switch (member.Kind) { case ESIR_NodeKind.Field when member is ESIR_Field fieldDef: { var roslynType = GetRoslynType(fieldDef.Type.Pointer); var variableName = fieldDef.Name.GetPooledString(ES_Encodings.Identifier); var variablesList = SingletonSeparatedList(VariableDeclarator(Identifier(variableName))); memberTypes.Add( FieldDeclaration( VariableDeclaration( roslynType ).WithVariables(variablesList) ).WithModifiers(TokenList( Token(SyntaxKind.PublicKeyword) )).WithAttributeLists(SingletonList(SingletonAttributeList( Attribute_FieldOffset(fieldDef.Offset) ))) ); break; } case ESIR_NodeKind.StaticField: // Ignore. break; default: throw new NotImplementedException("Member type not implemented."); } } // Generate the struct declaration. passData.Types.Add( StructDeclaration( mangledStructName ).WithMembers( ListSpan(memberTypes.Span) ).WithModifiers(TokenList( Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.UnsafeKeyword) )).WithAttributeLists(SingletonList( SingletonAttributeList( Attribute_StructLayout( nameof(LayoutKind.Explicit), null, LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(structDef.Type->RuntimeSize)) ) ) )) ); }
private static ExpressionSyntax CompileCode_NewArray(ES_ArrayTypeData *arrayType, ReadOnlySpan <ExpressionData> ranks, ExpressionSyntax?elemAssignValue) { Debug.Assert(arrayType->DimensionsCount == ranks.Length); // Get the roslyn type. var roslynArrType = GetRoslynType(&arrayType->TypeInfo); var roslynElemType = GetRoslynType(arrayType->ElementType); /** Construct the args list **/ using var argsList = new StructPooledList <SyntaxNodeOrToken> (CL_ClearMode.Auto); argsList.EnsureCapacity(1 + ranks.Length * 2 + (elemAssignValue is not null ? 2 : 0)); // Add the "pinned" bool. argsList.Add(Argument(BoolLiteral(false))); // Add the ranks. foreach (var rank in ranks) { Debug.Assert(rank.Value is not null); argsList.Add(Token(SyntaxKind.CommaToken)); argsList.Add(Argument(rank.Value !)); } // Add the value to assign, if any. if (elemAssignValue is not null) { argsList.Add(Token(SyntaxKind.CommaToken)); argsList.Add(Argument(elemAssignValue)); } /** Generate the function call **/ var ret = InvocationExpression(MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(MangleTypeName(&arrayType->TypeInfo)), IdentifierName(ArrayAllocFuncName) )).WithArgumentList(ArgumentList(SeparatedListSpan <ArgumentSyntax> (argsList.Span))); return(ret); }
private void TypeSizing_SizeType([NotNull] ES_TypeInfo *type, ArrayPointer <nint> refListRefType) { Debug.Assert(Environment is not null); Debug.Assert(EnvironmentBuilder is not null); if (type->Flags.HasFlag(ES_TypeFlag.Analyzed)) { return; } var hasRefs = !type->Flags.HasFlag(ES_TypeFlag.NoRefs); switch (type->TypeTag) { case ES_TypeTag.Array: case ES_TypeTag.Interface: case ES_TypeTag.Reference: { type->RuntimeSize = sizeof(void *); type->RefsList = refListRefType; type->Flags &= ~ES_TypeFlag.NoRefs; type->Flags |= ES_TypeFlag.Analyzed; return; } case ES_TypeTag.Void: case ES_TypeTag.Bool: case ES_TypeTag.Int: case ES_TypeTag.Float: case ES_TypeTag.Function: case ES_TypeTag.Enum: type->Flags |= ES_TypeFlag.Analyzed; return; case ES_TypeTag.Const: case ES_TypeTag.Immutable: { var constData = (ES_ConstData *)type; TypeSizing_SizeType(constData->InnerType, refListRefType); type->RuntimeSize = constData->InnerType->RuntimeSize; type->RefsList = constData->InnerType->RefsList; type->Flags = constData->InnerType->Flags | ES_TypeFlag.Analyzed; return; } case ES_TypeTag.Struct: case ES_TypeTag.Class: break; default: throw new NotImplementedException("Type not implemented yet."); } using var refsList = new StructPooledList <nint> (CL_ClearMode.Auto); var curOffs = 0; foreach (var memberAddr in type->MembersList.MembersList.Span) { var member = memberAddr.Address; if (member->MemberType != ES_MemberType.Field) { continue; } if (member->Flags.HasFlag(ES_MemberFlags.Static)) { continue; } var field = (ES_MemberData_Variable *)member; field->Offset = curOffs; TypeSizing_SizeType(field->Type, refListRefType); curOffs += field->Type->RuntimeSize; foreach (var refOffs in field->Type->RefsList.Span) { refsList.Add(field->Offset + refOffs); } hasRefs |= !field->Type->Flags.HasFlag(ES_TypeFlag.NoRefs); } type->RuntimeSize = curOffs; type->RefsList = ArrayPointer <nint> .Null; if (refsList.Count > 0) { type->RefsList = EnvironmentBuilder.MemoryManager.GetArrayAligned <nint> (refsList.Count, sizeof(nint)); refsList.Span.CopyTo(type->RefsList.Span); } type->Flags &= ~ES_TypeFlag.NoRefs; if (!hasRefs) { type->Flags |= ES_TypeFlag.NoRefs; } type->Flags |= ES_TypeFlag.Analyzed; }