Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CodeGen: implement the wide architecture set #356

Merged
merged 58 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
f556c45
(#354) CodeGen: implement the wide architecture set
ForNeVeR Dec 11, 2022
2c8853a
(#354) Runtime: introduce the CPtr type
ForNeVeR Dec 11, 2022
15ed227
(#354) FunctionType: add a TODO about the wide architecture
ForNeVeR Dec 13, 2022
244b6bd
(#354) Docs: document the current decision on pointer portability
ForNeVeR Feb 12, 2023
8ed11c6
(#354) CPtr, FPtr: add tests
ForNeVeR Feb 12, 2023
7c73251
(#354) VoidPtr, FuncPtr
ForNeVeR Feb 17, 2023
3833c05
(#354) Add more tests
ForNeVeR Feb 17, 2023
bfbbec1
(#354) Functions: add TODO
ForNeVeR Feb 21, 2023
6f39aa4
(#356) Docs: document the new pointer types in the architecture set d…
ForNeVeR Jul 29, 2023
7cf15f0
(#384) Docs: more clarification
ForNeVeR Jul 29, 2023
b5512a0
(#354) Docs: more clarifications
ForNeVeR Jul 29, 2023
665c544
Merge branch 'main' into feature/354.wide-arch
ForNeVeR Jul 29, 2023
ec67da2
(#354) Roll back the runtime lib changes
ForNeVeR Aug 5, 2023
704d062
(#354) Runtime: roll back the unnecessary changes
ForNeVeR Aug 12, 2023
1fefa3a
(#354) Apply test data diff
ForNeVeR Aug 13, 2023
e74fb50
(#356) Test fixes
ForNeVeR Aug 17, 2023
a43396e
(#354) Tests: add .NET interop tests
ForNeVeR Aug 17, 2023
a1689a2
(#354) Tests: add .NET pointer interop tests
ForNeVeR Aug 17, 2023
b97e32a
(#356) Refactor CodeGenNetInteropTests
ForNeVeR Aug 19, 2023
e63f01a
(#354) Tests: add CSharpCompilationUtil
ForNeVeR Aug 21, 2023
95a209d
(#354) Tests: compile C# projects with unsafe enabled
ForNeVeR Aug 25, 2023
9a5e3a4
(#354) Finish .NET compilation support for tests
ForNeVeR Aug 27, 2023
2424b21
(#354) Tests: add a test for CPtr in struct generation
ForNeVeR Aug 29, 2023
b4ef7d7
(#354) Basic support for new runtime wide pointer wrappers
ForNeVeR Aug 29, 2023
4350ca1
(#354) CodeGen: support CPtr interop on the Wide architecture
ForNeVeR Sep 2, 2023
e6b682d
(#354) CodeGen: add a test for CPtr<CPtr<T>>
ForNeVeR Sep 6, 2023
8667d7d
(#354) More tests for pointer interop
ForNeVeR Oct 30, 2023
a653fb7
Merge remote-tracking branch 'origin/main' into feature/354.wide-arch
ForNeVeR Oct 30, 2023
3f530d6
(#354) Fix compilation, deduplicate some redundant tests
ForNeVeR Oct 30, 2023
d94ea64
(#354) CodeGen: implement generic delegate cache
ForNeVeR Oct 31, 2023
19b4a1e
(#354) CodeGen: fix the remaining tests
ForNeVeR Oct 31, 2023
2d4c688
(#354) CodeGen: more tests for the various types of pointer interop
ForNeVeR Oct 31, 2023
84e53f9
(#354) CodeGen: match compatibility ptr types with the actual pointer…
ForNeVeR Nov 2, 2023
8e894e0
(#354) FunctionCallExpression: extract the type conversion into a sep…
ForNeVeR Nov 2, 2023
2e93313
(#354) CodeGen: groundwork for CLR type conversion
ForNeVeR Nov 2, 2023
fc71a17
(#354) CodeGen: call implicit cast operator for VoidPtr
ForNeVeR Nov 5, 2023
ee109a1
(#354) CodeGen: emit additional type case before calling the cast ope…
ForNeVeR Nov 5, 2023
6614b32
Merge remote-tracking branch 'origin/main' into feature/354.wide-arch
ForNeVeR Nov 5, 2023
e64f5d5
(#354) CodeGen: move further on CPtr cast operator
ForNeVeR Nov 11, 2023
e4c9183
(#354) CodeGen: support proper CPtr interop
ForNeVeR Nov 13, 2023
1a9bf18
(#354) FuncPtr conversion via constructor
ForNeVeR Nov 17, 2023
118e2d7
Merge branch 'main' into feature/354.wide-arch
ForNeVeR Nov 17, 2023
862f518
(#354) Tests: fix for unsafe class
ForNeVeR Nov 18, 2023
12b22d4
(#354) CodeGen: improve validation of vararg CLI imports
ForNeVeR Nov 18, 2023
3259db0
(#354) Tests: fix the runtimes properly
ForNeVeR Nov 18, 2023
10d1cd7
(#354) CodeGen: add integration tests
ForNeVeR Nov 19, 2023
193c090
(#354) CodeGen: proper FuncPtr conversion
ForNeVeR Nov 19, 2023
44c0f1a
(#354) CodeGen: add an integration test for function pointers inside …
ForNeVeR Nov 21, 2023
72ced1b
(#354) TODO sweep, better typoe checks
ForNeVeR Nov 21, 2023
0b133df
Merge branch 'main' into feature/354.wide-arch
ForNeVeR Nov 21, 2023
69a5c06
(#354) FunctionInfo: add a TODO
ForNeVeR Nov 23, 2023
4b2783f
(#354) Integration tests: drop an incorrect project item
ForNeVeR Nov 23, 2023
ad2fcd6
(#354) IntegrationTestContext: code cleanup
ForNeVeR Nov 23, 2023
443597e
(#354) Docs: small improvement
ForNeVeR Nov 23, 2023
b76311e
(#78, #285, #487, #488, #489, #490, #491, #492) Connect TODOs with th…
ForNeVeR Nov 23, 2023
79e2967
(#487, #493) Connect TODOs with the issues
ForNeVeR Nov 23, 2023
171fbee
WipException.ToDo: better documentation
ForNeVeR Nov 23, 2023
d76e339
Build: use the last version of JetBrains.Annotations everywhere
ForNeVeR Nov 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion Cesium.CodeGen.Tests/ArchitectureDependentCodeTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;

namespace Cesium.CodeGen.Tests;

public class ArchitectureDependentCodeTests : CodeGenTestBase
{
[MustUseReturnValue]
private static Task DoTest(TargetArchitectureSet arch, string source)
private static Task DoTest(TargetArchitectureSet arch, [StringSyntax("cpp")] string source)
{
var assembly = GenerateAssembly(runtime: default, arch: arch, sources: source);
return VerifyTypes(assembly, arch);
Expand All @@ -15,6 +16,7 @@ private static Task DoTest(TargetArchitectureSet arch, string source)
[InlineData(TargetArchitectureSet.Bit64)]
[InlineData(TargetArchitectureSet.Bit32)]
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Wide)]
public Task StaticArray(TargetArchitectureSet arch) => DoTest(arch, """
int main(void)
{
Expand All @@ -28,6 +30,7 @@ int main(void)
[InlineData(TargetArchitectureSet.Bit64)]
[InlineData(TargetArchitectureSet.Bit32)]
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Wide)]
public Task StructArray(TargetArchitectureSet arch) => DoTest(arch, """
typedef struct { char *ptr; } foo;

Expand All @@ -42,6 +45,7 @@ int main(void)
// TODO[#355]: [InlineData(TargetArchitectureSet.Bit64)]
// TODO[#355]: [InlineData(TargetArchitectureSet.Bit32)]
[InlineData(TargetArchitectureSet.Dynamic)]
// TODO[#355] [InlineData(TargetArchitectureSet.Wide)]
public Task TwoMemberStructArray(TargetArchitectureSet arch) => DoTest(arch, """
typedef struct { char *ptr; int len; } foo;

Expand All @@ -56,6 +60,7 @@ int main(void)
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Bit64)]
[InlineData(TargetArchitectureSet.Bit32)]
[InlineData(TargetArchitectureSet.Wide)]
public Task PointerArrayMemberAssign(TargetArchitectureSet arch) => DoTest(arch, """
int main(void)
{
Expand All @@ -69,6 +74,7 @@ int main(void)
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Bit64)]
[InlineData(TargetArchitectureSet.Bit32)]
[InlineData(TargetArchitectureSet.Wide)]
public Task PointerFunctionSignature(TargetArchitectureSet arch) => DoTest(arch, """
int foo(void *x)
{
Expand All @@ -80,11 +86,41 @@ int foo(void *x)
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Bit64)]
[InlineData(TargetArchitectureSet.Bit32)]
[InlineData(TargetArchitectureSet.Wide)]
public Task FunctionPointerParameter(TargetArchitectureSet arch) => DoTest(arch, """
typedef void (*func)(int, int);
typedef void (*v_func)(void);

int foo(func x) { return 0; }
int v_foo(v_func x) { return 0; }
""");

[Theory]
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Bit64)]
[InlineData(TargetArchitectureSet.Bit32)]
[InlineData(TargetArchitectureSet.Wide)]
public Task FunctionPointerStructMember(TargetArchitectureSet arch) => DoTest(arch, """
typedef void (*func)(int);
struct Foo
{
func x;
};
""");
// TODO[#487]: empty-paren-func ptr
// TODO[#487]: vararg-func ptr

[Theory]
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Bit64)]
[InlineData(TargetArchitectureSet.Bit32)]
[InlineData(TargetArchitectureSet.Wide)]
public Task StructWithNestedFuncPtr(TargetArchitectureSet arch) => DoTest(arch, """
typedef int (*func)(void);
typedef int (*hostFunc)(func);
typedef struct
{
hostFunc foo;
} foo;
""");
}
36 changes: 31 additions & 5 deletions Cesium.CodeGen.Tests/ArchitectureDependentTypeTests.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,59 @@
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;

namespace Cesium.CodeGen.Tests;

public class ArchitectureDependentTypeTests : CodeGenTestBase
{
[MustUseReturnValue]
private static Task DoTest(TargetArchitectureSet arch, string source, string @namespace = "", string globalTypeFqn = "")
private static Task DoTest(
TargetArchitectureSet arch,
[StringSyntax("cpp")] string source)
{
var assembly = GenerateAssembly(
default,
arch,
@namespace: @namespace,
globalTypeFqn: globalTypeFqn,
@namespace: "",
globalTypeFqn: "",
sources: source);
return VerifyTypes(assembly, arch);
}

[Theory]
[InlineData(TargetArchitectureSet.Bit64)]
[InlineData(TargetArchitectureSet.Bit32)]
public Task StructWithPointer(TargetArchitectureSet arch) => DoTest(arch, """
[InlineData(TargetArchitectureSet.Wide)]
public Task StructWithPointerArray(TargetArchitectureSet arch) => DoTest(arch, """
typedef struct
{
char *x[1];
} foo;
""");

[Theory]
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Bit64)]
[InlineData(TargetArchitectureSet.Bit32)]
[InlineData(TargetArchitectureSet.Wide)]
public Task StructWithPointer(TargetArchitectureSet arch) => DoTest(arch, """
typedef struct
{
char *x;
} foo;
""");

[Theory]
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Wide)]
public Task StructWithDoublePointer(TargetArchitectureSet arch) => DoTest(arch, """
typedef struct
{
int **x;
} foo;
""");

[Fact(DisplayName = "Struct with a fixed array of a pointer type isn't supported for dynamic architecture")]
public void StructWithPointerDynamic() => DoesNotCompile("""
public void StructWithPointerArrayDynamic() => DoesNotCompile("""
typedef struct
{
char *x[1];
Expand Down
3 changes: 2 additions & 1 deletion Cesium.CodeGen.Tests/Cesium.CodeGen.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2022.1.0" />
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="Verify.Xunit" Version="16.3.5" />
<PackageReference Include="xunit" Version="2.4.1" />
Expand All @@ -24,6 +24,7 @@

<ItemGroup>
<ProjectReference Include="..\Cesium.CodeGen\Cesium.CodeGen.csproj" />
<ProjectReference Include="..\Cesium.Compiler\Cesium.Compiler.csproj" />
<ProjectReference Include="..\Cesium.Core\Cesium.Core.csproj" />
<ProjectReference Include="..\Cesium.Parser\Cesium.Parser.csproj" />
<ProjectReference Include="..\Cesium.Runtime\Cesium.Runtime.csproj" />
Expand Down
173 changes: 173 additions & 0 deletions Cesium.CodeGen.Tests/CodeGenNetInteropTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
using System.Diagnostics.CodeAnalysis;
using Cesium.Compiler;
using Cesium.Test.Framework;
using Xunit.Abstractions;

namespace Cesium.CodeGen.Tests;

// TODO[#488]: Make them run in parallel, as all the integration tests
public class CodeGenNetInteropTests : CodeGenTestBase
{
private readonly ITestOutputHelper _output;
public CodeGenNetInteropTests(ITestOutputHelper output)
{
_output = output;
}

private async Task DoTest(
TargetArchitectureSet architecture,
[StringSyntax("csharp")] string cSharpCode,
[StringSyntax("cpp")] string cCode)
{
var cSharpAssemblyPath = await CSharpCompilationUtil.CompileCSharpAssembly(
_output,
CSharpCompilationUtil.DefaultRuntime,
cSharpCode);
var (cesiumAssembly, assemblyContents) = GenerateAssembly(runtime: null, arch: architecture, sources: new[]{cCode}, referencePaths: new[] { cSharpAssemblyPath });
await VerifyTypes(cesiumAssembly, architecture);
await VerifyAssemblyRuns(assemblyContents.ToArray(), cSharpAssemblyPath);
}

private async Task VerifyAssemblyRuns(byte[] assemblyContentToRun, string referencePath)
{
var testDirectoryPath = Path.GetTempFileName();
File.Delete(testDirectoryPath);
Directory.CreateDirectory(testDirectoryPath);

try
{
var assemblyPath = Path.Combine(testDirectoryPath, "EntryPoint.dll");
var runtimeConfigPath = Path.ChangeExtension(assemblyPath, ".runtimeconfig.json");

await File.WriteAllBytesAsync(assemblyPath, assemblyContentToRun);
await File.WriteAllTextAsync(runtimeConfigPath, RuntimeConfig.EmitNet7());

DeployReferenceAssembly(CSharpCompilationUtil.CesiumRuntimeLibraryPath);
DeployReferenceAssembly(referencePath);

await ExecUtil.RunToSuccess(_output, "dotnet", testDirectoryPath, new[] { assemblyPath });
}
finally
{
Directory.Delete(testDirectoryPath, recursive: true);
}

void DeployReferenceAssembly(string assemblyPath)
{
var targetFilePath = Path.Combine(testDirectoryPath, Path.GetFileName(assemblyPath));
File.Copy(assemblyPath, targetFilePath);
}
}

[Theory]
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Wide)]
public Task PointerInterop(TargetArchitectureSet architecture) => DoTest(
architecture,
@"public static unsafe class Test
{
public static int Func(int* ptr) => 1;
}
", """
__cli_import("Test::Func")
int Func(int *ptr);

int main(void)
{
int x = 0;
return Func(&x) - 1;
}
""");

[Theory]
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Wide)]
public Task CPtrInterop(TargetArchitectureSet architecture) => DoTest(
architecture,
@"using Cesium.Runtime;
public static class Test
{
public static int Func(CPtr<int> ptr) => 1;
}
", """
__cli_import("Test::Func")
int Func(int *ptr);

int main(void)
{
int x = 0;
return Func(&x) - 1;
}
""");

[Theory]
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Wide)]
public Task VoidPtrInterop(TargetArchitectureSet architecture) => DoTest(
architecture,
@"using Cesium.Runtime;
public static class Test
{
public static int Func(VoidPtr ptr) => 1;
}
", """
__cli_import("Test::Func")
int Func(void *ptr);

int main(void)
{
int x = 0;
return Func(&x) - 1;
}
""");

[Theory]
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Wide)]
public Task FuncPtrInterop(TargetArchitectureSet architecture) => DoTest(
architecture,
@"using Cesium.Runtime;
public static class Test
{
public static int Func(FuncPtr<Func<int>> ptr) => 1;
}
", """
__cli_import("Test::Func")
int Func(int (*ptr)());

int myFunc()
{
return 0;
}

int main(void)
{
return Func(&myFunc) - 1;
}
""");

[Theory]
[InlineData(TargetArchitectureSet.Dynamic)]
[InlineData(TargetArchitectureSet.Wide)]
public Task FunctionPointerInterop(TargetArchitectureSet architecture) => DoTest(
architecture,
"""
public static unsafe class Test
{
public static int Func(delegate*<int> ptr) => 1;
}
""", """
__cli_import("Test::Func")
int Func(int (*ptr)());

int myFunc()
{
return 0;
}

int main(void)
{
return Func(&myFunc) - 1;
}
""");
}
Loading
Loading