Skip to content

Commit

Permalink
Fix extracting functions with attributes (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
lithiumtoast authored Apr 7, 2024
1 parent 5b396f1 commit 27242e8
Show file tree
Hide file tree
Showing 14 changed files with 175 additions and 46 deletions.
23 changes: 23 additions & 0 deletions src/c/tests/functions/function_attributed/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"inputFilePath": "./main.c",
"userIncludeDirectories": [
"../../../production/ffi_helper/include"
],
"ignoredIncludeFiles": [
"../../../production/ffi_helper/include/ffi_helper.h"
],
"targetPlatforms": {
"windows": {
"x86_64-pc-windows-msvc": {},
"aarch64-pc-windows-msvc": {}
},
"macos": {
"aarch64-apple-darwin": {},
"x86_64-apple-darwin": {},
},
"linux": {
"x86_64-unknown-linux-gnu": {},
"aarch64-unknown-linux-gnu": {}
}
}
}
5 changes: 5 additions & 0 deletions src/c/tests/functions/function_attributed/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <stdio.h>
#include "ffi_helper.h"

extern FFI_API_DECL __attribute__((malloc)) void* __cdecl function_attributed(size_t size);

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace c2ffi.Data.Serialization
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "8.0.9.3103")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "8.0.9.8001")]
public partial class JsonSerializerContextCFfiCrossPlatform
{
private readonly static global::System.Text.Json.JsonSerializerOptions s_defaultOptions = new()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace c2ffi.Data.Serialization
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "8.0.9.3103")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "8.0.9.8001")]
public partial class JsonSerializerContextCFfiTargetPlatform
{
private readonly static global::System.Text.Json.JsonSerializerOptions s_defaultOptions = new()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,41 +89,20 @@ public CTypeInfo VisitType(
return string.IsNullOrEmpty(commentString) ? null : commentString;
}

public ExploreNodeInfo CreateNodeInfo(
public ExploreNodeInfo CreateTopLevelNodeInfo(
CNodeKind nodeKind,
clang.CXCursor clangCursor)
{
var cursorName = clangCursor.Spelling();
var cursorType = clang.clang_getCursorType(clangCursor);
return CreateNodeInfo(nodeKind, cursorName, clangCursor, cursorType, null);
}
var clangCursorName = clangCursor.Spelling();
var clangCursorType = clang.clang_getCursorType(clangCursor);

public ExploreNodeInfo CreateNodeInfo(
CNodeKind kind,
string name,
clang.CXCursor clangCursor,
clang.CXType clangType,
ExploreNodeInfo? parentInfo)
{
var location = ParseContext.Location(clangCursor);
var typeName = clangType.Spelling();
var sizeOf = ParseContext.SizeOf(kind, clangType);
var alignOf = ParseContext.AlignOf(kind, clangType);

var result = new ExploreNodeInfo
var clangCursorTypeCanonical = clangCursorType;
if (clangCursorType.kind == clang.CXTypeKind.CXType_Attributed)
{
NodeKind = kind,
Name = name,
TypeName = typeName,
Type = clangType,
Cursor = clangCursor,
Location = location,
Parent = parentInfo,
SizeOf = sizeOf,
AlignOf = alignOf
};
clangCursorTypeCanonical = clang.clang_Type_getModifiedType(clangCursorType);
}

return result;
return CreateNodeInfo(nodeKind, clangCursorName, clangCursor, clangCursorTypeCanonical, null);
}

public void Dispose()
Expand Down Expand Up @@ -257,6 +236,34 @@ private CTypeInfo VisitTypeInternal(
return typeInfo;
}

private ExploreNodeInfo CreateNodeInfo(
CNodeKind kind,
string name,
clang.CXCursor clangCursor,
clang.CXType clangType,
ExploreNodeInfo? parentInfo)
{
var location = ParseContext.Location(clangCursor);
var typeName = clangType.Spelling();
var sizeOf = ParseContext.SizeOf(kind, clangType);
var alignOf = ParseContext.AlignOf(kind, clangType);

var result = new ExploreNodeInfo
{
NodeKind = kind,
Name = name,
TypeName = typeName,
Type = clangType,
Cursor = clangCursor,
Location = location,
Parent = parentInfo,
SizeOf = sizeOf,
AlignOf = alignOf
};

return result;
}

private static ImmutableDictionary<CNodeKind, NodeExplorer> GetNodeHandlers(IServiceProvider services)
{
var result = new Dictionary<CNodeKind, NodeExplorer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private void VisitFunctions(ExploreContext context, ParseContext parseContext)

private void VisitFunction(ExploreContext context, clang.CXCursor clangCursor)
{
var info = context.CreateNodeInfo(CNodeKind.Function, clangCursor);
var info = context.CreateTopLevelNodeInfo(CNodeKind.Function, clangCursor);
context.TryEnqueueNode(info);
}

Expand All @@ -99,7 +99,7 @@ private void VisitVariables(ExploreContext context, ParseContext parseContext)

private void VisitVariable(ExploreContext context, clang.CXCursor clangCursor)
{
var info = context.CreateNodeInfo(CNodeKind.Variable, clangCursor);
var info = context.CreateTopLevelNodeInfo(CNodeKind.Variable, clangCursor);
context.TryEnqueueNode(info);
}

Expand All @@ -114,7 +114,7 @@ private void VisitMacroObjects(ExploreContext context, ParseContext parseContext

private void VisitMacroObject(ExploreContext context, clang.CXCursor clangCursor)
{
var info = context.CreateNodeInfo(CNodeKind.MacroObject, clangCursor);
var info = context.CreateTopLevelNodeInfo(CNodeKind.MacroObject, clangCursor);
context.TryEnqueueNode(info);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// <auto-generated/>
#nullable enable
// <auto-generated/>
#nullable enable

namespace c2ffi.Tool.Commands.Extract.Domain.Explore.Context
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved.
// Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information.

using c2ffi.Tests.Library.Models;
using FluentAssertions;

#pragma warning disable CA1707

namespace c2ffi.Tests.EndToEnd.Extract.Functions.function_attributed;

public class Test : ExtractFfiTest
{
private const string FunctionName = "function_attributed";

[Fact]
public void Function()
{
var ffis = GetTargetPlatformFfis(
$"src/c/tests/functions/{FunctionName}/config.json");
Assert.True(ffis.Length > 0);

foreach (var ffi in ffis)
{
FfiFunctionExists(ffi);
}
}

private void FfiFunctionExists(CTestFfiTargetPlatform ffi)
{
var function = ffi.GetFunction(FunctionName);
function.CallingConvention.Should().Be("cdecl");

var returnType = function.ReturnType;
returnType.Name.Should().Be("void *");
returnType.SizeOf.Should().Be(ffi.PointerSize);
returnType.AlignOf.Should().Be(ffi.PointerSize);
returnType.NodeKind.Should().Be("pointer");
returnType.InnerType.Should().NotBeNull();
returnType.InnerType!.Name.Should().Be("void");
returnType.InnerType!.NodeKind.Should().Be("primitive");
returnType.InnerType.InnerType.Should().BeNull();

function.Parameters.Should().NotBeEmpty();
function.Parameters.Length.Should().Be(1);
var parameter = function.Parameters[0];
parameter.Name.Should().Be("size");
parameter.Type.Name.Should().Be("size_t");
parameter.Type.InnerType.Should().NotBeNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ private static void FfiFunctionExists(CTestFfiTargetPlatform ffi)
function.Parameters.Length.Should().Be(1);
var parameter = function.Parameters[0];
parameter.Name.Should().Be("a");
parameter.TypeName.Should().Be("int");
parameter.Type.Name.Should().Be("int");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ private static void FfiFunctionExists(CTestFfiTargetPlatform ffi)

var parameter1 = function.Parameters[0];
parameter1.Name.Should().Be("a");
parameter1.TypeName.Should().Be("uint8_t");
parameter1.Type.Name.Should().Be("uint8_t");

var parameter2 = function.Parameters[1];
parameter2.Name.Should().Be("b");
parameter2.TypeName.Should().Be("uint16_t");
parameter2.Type.Name.Should().Be("uint16_t");

var parameter3 = function.Parameters[2];
parameter3.Name.Should().Be("c");
parameter3.TypeName.Should().Be("uint32_t");
parameter3.Type.Name.Should().Be("uint32_t");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Bottlenose Labs Inc. (https://github.com/bottlenoselabs). All rights reserved.
// Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information.

using c2ffi.Tests.Library.Models;
using FluentAssertions;
using Xunit;

#pragma warning disable CA1707

namespace c2ffi.Tests.EndToEnd.Merge.Functions.function_attributed;

public class Test : MergeFfisTest
{
private const string FunctionName = "function_attributed";

[Fact]
public void Function()
{
var ffi = GetCrossPlatformFfi(
$"src/c/tests/functions/{FunctionName}/ffi");
FfiFunctionExists(ffi);
}

private void FfiFunctionExists(CTestFfiCrossPlatform ffi)
{
var function = ffi.GetFunction(FunctionName);
function.CallingConvention.Should().Be("cdecl");

var returnType = function.ReturnType;
returnType.Name.Should().Be("void *");
returnType.NodeKind.Should().Be("pointer");
returnType.InnerType.Should().NotBeNull();
returnType.InnerType!.Name.Should().Be("void");
returnType.InnerType!.NodeKind.Should().Be("primitive");
returnType.InnerType.InnerType.Should().BeNull();

function.Parameters.Should().NotBeEmpty();
function.Parameters.Length.Should().Be(1);
var parameter = function.Parameters[0];
parameter.Name.Should().Be("size");
parameter.Type.Name.Should().Be("size_t");
parameter.Type.InnerType.Should().NotBeNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ private void FfiFunctionExists(CTestFfiCrossPlatform ffi)
function.Parameters.Length.Should().Be(1);
var parameter = function.Parameters[0];
parameter.Name.Should().Be("a");
parameter.TypeName.Should().Be("int");
parameter.Type.Name.Should().Be("int");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ private static void FfiFunctionExists(CTestFfiCrossPlatform ffi)

var parameter1 = function.Parameters[0];
parameter1.Name.Should().Be("a");
parameter1.TypeName.Should().Be("uint8_t");
parameter1.Type.Name.Should().Be("uint8_t");

var parameter2 = function.Parameters[1];
parameter2.Name.Should().Be("b");
parameter2.TypeName.Should().Be("uint16_t");
parameter2.Type.Name.Should().Be("uint16_t");

var parameter3 = function.Parameters[2];
parameter3.Name.Should().Be("c");
parameter3.TypeName.Should().Be("uint32_t");
parameter3.Type.Name.Should().Be("uint32_t");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ public class CTestFunctionParameter
{
public string Name { get; }

public string TypeName { get; }
public CTestTypeInfo Type { get; }

public CTestFunctionParameter(CFunctionParameter functionParameter)
{
Name = functionParameter.Name;
TypeName = functionParameter.TypeInfo.Name;
Type = new CTestTypeInfo(functionParameter.TypeInfo);
}

public override string ToString()
Expand Down

0 comments on commit 27242e8

Please sign in to comment.