From 30d101461efc8fe4bfec65ecb77ef3fc171ede7d Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Wed, 19 Oct 2022 22:13:29 +0200 Subject: [PATCH 1/2] (#234) CodeGen: add a test for abstract parameter declarators --- Cesium.CodeGen.Tests/CodeGenTypeTests.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Cesium.CodeGen.Tests/CodeGenTypeTests.cs b/Cesium.CodeGen.Tests/CodeGenTypeTests.cs index 938877e6..acc66462 100644 --- a/Cesium.CodeGen.Tests/CodeGenTypeTests.cs +++ b/Cesium.CodeGen.Tests/CodeGenTypeTests.cs @@ -194,4 +194,15 @@ int main(void) { foo x; return x.nonExisting; }", "\"foo\" has no member named \"nonExisting\""); + + [Fact] + public Task ComplexStructDefinition() => DoTest(@"typedef void(*function)(int, const int*, const int*); +typedef struct { + int a; + int b[5]; + unsigned char c[64]; + function func; + + int array[80][5]; +} foo;"); } From c25eb92980d76003c53aa8501737d26382f1258d Mon Sep 17 00:00:00 2001 From: Friedrich von Never Date: Wed, 19 Oct 2022 22:51:18 +0200 Subject: [PATCH 2/2] (#234, #72) CodeGen: process a complex struct with a function-typed field --- ...Tests.ComplexStructDefinition.verified.txt | 49 ++++++++++++++++ .../Ir/Declarations/LocalDeclarationInfo.cs | 57 ++++++++++++++++--- Cesium.CodeGen/Ir/ParametersInfo.cs | 13 +++-- 3 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 Cesium.CodeGen.Tests/verified/CodeGenTypeTests.ComplexStructDefinition.verified.txt diff --git a/Cesium.CodeGen.Tests/verified/CodeGenTypeTests.ComplexStructDefinition.verified.txt b/Cesium.CodeGen.Tests/verified/CodeGenTypeTests.ComplexStructDefinition.verified.txt new file mode 100644 index 00000000..4e1c8e29 --- /dev/null +++ b/Cesium.CodeGen.Tests/verified/CodeGenTypeTests.ComplexStructDefinition.verified.txt @@ -0,0 +1,49 @@ +Module: Primary + Type: + + Type: foo + Nested types: + Type: foo/b + Pack: 0 + Size: 20 + Custom attributes: + - CompilerGeneratedAttribute() + - UnsafeValueTypeAttribute() + + Fields: + System.Int32 foo/b::FixedElementField + + Type: foo/c + Pack: 0 + Size: 64 + Custom attributes: + - CompilerGeneratedAttribute() + - UnsafeValueTypeAttribute() + + Fields: + System.Byte foo/c::FixedElementField + + Type: foo/array + Pack: 0 + Size: 1600 + Custom attributes: + - CompilerGeneratedAttribute() + - UnsafeValueTypeAttribute() + + Fields: + System.Int32* foo/array::FixedElementField + Fields: + System.Int32 foo::a + foo/b foo::b + Custom attributes: + - FixedBufferAttribute(System.Int32, 20) + + foo/c foo::c + Custom attributes: + - FixedBufferAttribute(System.Byte, 64) + + method System.Void *(System.Int32,System.Int32*,System.Int32*) foo::func + foo/array foo::array + Custom attributes: + - FixedBufferAttribute(System.Int32*, 1600) + diff --git a/Cesium.CodeGen/Ir/Declarations/LocalDeclarationInfo.cs b/Cesium.CodeGen/Ir/Declarations/LocalDeclarationInfo.cs index 5a0216c9..76d45af4 100644 --- a/Cesium.CodeGen/Ir/Declarations/LocalDeclarationInfo.cs +++ b/Cesium.CodeGen/Ir/Declarations/LocalDeclarationInfo.cs @@ -22,20 +22,25 @@ public static LocalDeclarationInfo Of(IReadOnlyList speci return new LocalDeclarationInfo(type, null, null); var (pointer, directDeclarator) = declarator; - if (pointer != null) - { - var (typeQualifiers, childPointer) = pointer; - if (typeQualifiers != null || childPointer != null) - throw new WipException(215, $"Complex pointer type is not supported, yet: {pointer}."); - - type = new PointerType(type); - } - + type = ProcessPointer(pointer, type); (type, var identifier) = ProcessDirectDeclarator(directDeclarator, type); return new LocalDeclarationInfo(type, identifier, cliImportMemberName); } + public static LocalDeclarationInfo Of( + IReadOnlyList specifiers, + AbstractDeclarator abstractDeclarator) + { + var (type, cliImportMemberName) = ProcessSpecifiers(specifiers); + + var (pointer, directAbstractDeclarator) = abstractDeclarator; + type = ProcessPointer(pointer, type); + type = ProcessDirectAbstractDeclarator(directAbstractDeclarator, type); + + return new LocalDeclarationInfo(type, Identifier: null, cliImportMemberName); + } + private static (IType, string? CliImportMemberName) ProcessSpecifiers( IReadOnlyList specifiers) { @@ -119,6 +124,19 @@ private static (IType, string? CliImportMemberName) ProcessSpecifiers( return (isConst ? new ConstType(type) : type, cliImportMemberName); } + private static IType ProcessPointer(Pointer? pointer, IType type) + { + if (pointer == null) return type; + + var (typeQualifiers, childPointer) = pointer; + if (typeQualifiers != null || childPointer != null) + throw new WipException(215, $"Complex pointer type is not supported, yet: {pointer}."); + + type = new PointerType(type); + + return type; + } + private static (IType, string? Identifier) ProcessDirectDeclarator(IDirectDeclarator directDeclarator, IType type) { string? identifier = null; @@ -224,6 +242,27 @@ private static (IType, string? Identifier) ProcessDirectDeclarator(IDirectDeclar return (type, identifier); } + private static IType ProcessDirectAbstractDeclarator( + IDirectAbstractDeclarator? directAbstractDeclarator, + IType type) + { + var current = directAbstractDeclarator; + while (current != null) + { + switch (current) + { + default: + throw new WipException( + 332, + $"Direct abstract declarator is not supported, yet: {current}."); + } + + current = current.Base; + } + + return type; + } + private static IType CreateArrayType(IType type, int size) { if (type is InPlaceArrayType inplaceArrayType) diff --git a/Cesium.CodeGen/Ir/ParametersInfo.cs b/Cesium.CodeGen/Ir/ParametersInfo.cs index cdd8f926..35dcd0c9 100644 --- a/Cesium.CodeGen/Ir/ParametersInfo.cs +++ b/Cesium.CodeGen/Ir/ParametersInfo.cs @@ -44,12 +44,13 @@ internal record ParameterInfo(IType Type, string? Name) public static ParameterInfo Of(ParameterDeclaration declaration) { var (specifiers, declarator, abstractDeclarator) = declaration; - if (abstractDeclarator != null) - throw new WipException( - 234, - $"Parameter with abstract declarator is not supported, yet: {declaration}."); - - var (type, identifier, cliImportMemberName) = LocalDeclarationInfo.Of(specifiers, declarator); + var (type, identifier, cliImportMemberName) = (declarator, abstractDeclarator) switch + { + (null, { }) => LocalDeclarationInfo.Of(specifiers, abstractDeclarator), + (_, null) => LocalDeclarationInfo.Of(specifiers, declarator), + _ => throw new AssertException( + $"Both declarator and abstract declarator found for declaration {declaration}.") + }; if (cliImportMemberName != null) throw new CompilationException("CLI import specifier isn't supported for a parameter.");