Skip to content

Adding support for UnscopedRef #377

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

Merged
merged 2 commits into from
Aug 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal struct FieldDesc
public string ParentName { get; set; }
public int? Offset { get; set; }
public bool NeedsNewKeyword { get; set; }
public bool NeedsUnscopedRef { get; set; }
public bool HasBody { get; set; }
public string InheritedFrom { get; set; }
public CXSourceLocation? Location { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal struct FunctionOrDelegateDesc
public CXSourceLocation? Location { get; set; }
public bool HasBody { get; set; }
public bool IsInherited { get; set; }
public bool NeedsUnscopedRef { get; set; }

public bool IsVirtual
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ internal partial interface IOutputBuilder
void BeginSetter(bool aggressivelyInlined);
void EndSetter();

void BeginIndexer(AccessSpecifier accessSpecifier, bool isUnsafe);
void BeginIndexer(AccessSpecifier accessSpecifier, bool isUnsafe, bool needsUnscopedRef);
void WriteIndexer(string typeName);
void BeginIndexerParameters();
void EndIndexerParameters();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ public void WriteCustomAttribute(string attribute, Action callback = null)
{
AddUsingDirective("System.ComponentModel");
}
else if (attribute.Equals("UnscopedRef"))
{
AddUsingDirective("System.Diagnostics.CodeAnalysis");
}
else if (attribute.StartsWith("Guid(")|| attribute.Equals("Optional") || attribute.StartsWith("Optional, DefaultParameterValue("))
{
AddUsingDirective("System.Runtime.InteropServices");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,11 @@ public void BeginField(in FieldDesc desc)

desc.WriteCustomAttrs?.Invoke(desc.CustomAttrGeneratorData);

if (desc.NeedsUnscopedRef)
{
WriteCustomAttribute("UnscopedRef");
}

WriteIndented(GetAccessSpecifierString(desc.AccessSpecifier, isNested: true));
Write(' ');

Expand Down Expand Up @@ -463,6 +468,11 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM

desc.WriteCustomAttrs?.Invoke(desc.CustomAttrGeneratorData);

if (desc.NeedsUnscopedRef)
{
WriteCustomAttribute("UnscopedRef");
}

if (_isInMarkerInterface)
{
WriteIndentation();
Expand Down Expand Up @@ -906,9 +916,15 @@ public void EndSetter()
NeedsNewline = false;
}

public void BeginIndexer(AccessSpecifier accessSpecifier, bool isUnsafe)
public void BeginIndexer(AccessSpecifier accessSpecifier, bool isUnsafe, bool needsUnscopedRef)
{
NeedsNewline = true;

if (needsUnscopedRef)
{
WriteCustomAttribute("UnscopedRef");
}

WriteIndented(GetAccessSpecifierString(accessSpecifier, isNested: true));
Write(' ');
if (isUnsafe)
Expand Down
87 changes: 49 additions & 38 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,7 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl)
ParentName = GetRemappedCursorName(fieldDecl.Parent),
Offset = null,
NeedsNewKeyword = false,
NeedsUnscopedRef = _config.GeneratePreviewCode && !fieldDecl.IsBitField,
Location = fieldDecl.Location,
HasBody = true,
WriteCustomAttrs = static context => {
Expand Down Expand Up @@ -921,8 +922,7 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl)
}
}

var isSupportedFixedSizedBufferType =
isFixedSizedBuffer && IsSupportedFixedSizedBufferType(typeName);
var isSupportedFixedSizedBufferType = isFixedSizedBuffer && IsSupportedFixedSizedBufferType(typeName);

if (isFixedSizedBuffer)
{
Expand Down Expand Up @@ -1004,53 +1004,63 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl)
{
code.WriteIndented("return ");

if (!isFixedSizedBuffer)
{
code.AddUsingDirective("System.Runtime.InteropServices");
code.Write("ref MemoryMarshal.GetReference(");
}

if (!isFixedSizedBuffer || isSupportedFixedSizedBufferType)
{
code.Write("MemoryMarshal.CreateSpan(ref ");
}

if (isIndirectPointerField)
{
code.Write("this");
}
else
if (desc.NeedsUnscopedRef && !isFixedSizedBuffer)
{
code.Write("ref ");
code.Write(contextName);
code.Write('.');
code.Write(escapedName);
}

if (isFixedSizedBuffer)
else
{
if (isSupportedFixedSizedBufferType)
if (!isFixedSizedBuffer)
{
code.AddUsingDirective("System.Runtime.InteropServices");
code.Write("ref MemoryMarshal.GetReference(");
}

if (!isFixedSizedBuffer || isSupportedFixedSizedBufferType)
{
code.Write("[0], ");
code.Write(Math.Max((type.CanonicalType as ConstantArrayType)?.Size ?? 0, 1));
code.Write("MemoryMarshal.CreateSpan(ref ");
}

if (isIndirectPointerField)
{
code.Write("this");
}
else
{
code.Write(".AsSpan(");
code.Write(contextName);
code.Write('.');
code.Write(escapedName);
}
}
else
{
code.Write(", 1)");
}

code.Write(')');
if (isFixedSizedBuffer)
{
if (isSupportedFixedSizedBufferType)
{
code.Write("[0], ");
code.Write(Math.Max((type.CanonicalType as ConstantArrayType)?.Size ?? 0, 1));
}
else
{
code.Write(".AsSpan(");
}
}
else
{
code.Write(", 1)");
}

if (isIndirectPointerField)
{
code.Write('.');
code.Write(contextName);
code.Write('.');
code.Write(escapedName);
code.Write(')');

if (isIndirectPointerField)
{
code.Write('.');
code.Write(contextName);
code.Write('.');
code.Write(escapedName);
}
}

code.WriteSemicolon();
Expand Down Expand Up @@ -2829,7 +2839,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co

if (generateCompatibleCode || isUnsafeElementType)
{
_outputBuilder.BeginIndexer(AccessSpecifier.Public, generateCompatibleCode && !isUnsafeElementType);
_outputBuilder.BeginIndexer(AccessSpecifier.Public, isUnsafe: generateCompatibleCode && !isUnsafeElementType, needsUnscopedRef: false);
_outputBuilder.WriteIndexer($"ref {arrayTypeName}");
_outputBuilder.BeginIndexerParameters();
var param = new ParameterDesc {
Expand Down Expand Up @@ -2862,7 +2872,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
}
else
{
_outputBuilder.BeginIndexer(AccessSpecifier.Public, false);
_outputBuilder.BeginIndexer(AccessSpecifier.Public, isUnsafe: false, needsUnscopedRef: _config.GeneratePreviewCode);
_outputBuilder.WriteIndexer($"ref {arrayTypeName}");
_outputBuilder.BeginIndexerParameters();
var param = new ParameterDesc {
Expand Down Expand Up @@ -2904,6 +2914,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
ReturnType = $"Span<{arrayTypeName}>",
Location = constantOrIncompleteArray.Location,
HasBody = true,
NeedsUnscopedRef = _config.GeneratePreviewCode,
};

var isUnsafe = false;
Expand Down
4 changes: 3 additions & 1 deletion sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1806,6 +1806,7 @@ private string EscapeAndStripName(string name)
}

internal static string EscapeCharacter(char value) => value switch {
'\0' => "\\0",
'\\' => "\\\\",
'\r' => "\\r",
'\n' => "\\n",
Expand All @@ -1814,7 +1815,8 @@ private string EscapeAndStripName(string name)
_ => value.ToString(),
};

internal static string EscapeString(string value) => value.Replace("\\", "\\\\")
internal static string EscapeString(string value) => value.Replace("\0", "\\0")
.Replace("\\", "\\\\")
.Replace("\r", "\\r")
.Replace("\n", "\\n")
.Replace("\t", "\\t")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ public void BeginSetter(bool aggressivelyInlined)

public void EndSetter() => _ = _sb.Append("</set>");

public void BeginIndexer(AccessSpecifier accessSpecifier, bool isUnsafe)
public void BeginIndexer(AccessSpecifier accessSpecifier, bool isUnsafe, bool needsUnscopedRef)
{
_ = _sb.Append("<indexer access=\"");
_ = _sb.Append(accessSpecifier.AsString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1428,7 +1428,8 @@ void MyFunction()
}
";

var expectedOutputContents = @"using System.Runtime.InteropServices;
var expectedOutputContents = @"using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;

namespace ClangSharp.Test
{
Expand All @@ -1439,11 +1440,12 @@ public partial struct MyUnion
[NativeTypeName(""MyUnion::(anonymous struct at ClangUnsavedFile.h:3:5)"")]
public _Anonymous_e__Struct Anonymous;

[UnscopedRef]
public ref int a
{
get
{
return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1));
return ref Anonymous.a;
}
}

Expand Down
Loading