-
Notifications
You must be signed in to change notification settings - Fork 517
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Rgen] Add the needed code to make the objc_msgSend signatures.
Add the code that will calculate the signature needed in the objc_msgSend which will be the method that calls the native objc message.
- Loading branch information
1 parent
9516bf1
commit 2706f5e
Showing
17 changed files
with
925 additions
and
35 deletions.
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
src/rgen/Microsoft.Macios.Generator/Attributes/MarshalDirective.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
|
||
namespace Microsoft.Macios.Generator.Attributes; | ||
|
||
record CustomMarshalDirective (string? NativePrefix, string? NativeSuffix, string? Library); | ||
|
||
static class ExportDataExtensions { | ||
|
||
public static bool ShouldMarshalNativeExceptions<T> (this ExportData<T> self) where T : Enum | ||
=> self switch { | ||
ExportData<ObjCBindings.Property> property => property.Flags.HasFlag (ObjCBindings.Property | ||
.CustomMarshalDirective), | ||
ExportData<ObjCBindings.Method> method => method.Flags.HasFlag ( | ||
ObjCBindings.Property.CustomMarshalDirective), | ||
_ => false, | ||
}; | ||
|
||
public static CustomMarshalDirective? ToCustomMarshalDirective<T> (this ExportData<T> self) where T : Enum | ||
{ | ||
var present = self switch { | ||
ExportData<ObjCBindings.Property> property => property.Flags.HasFlag (ObjCBindings.Property | ||
.CustomMarshalDirective), | ||
ExportData<ObjCBindings.Method> method => method.Flags.HasFlag ( | ||
ObjCBindings.Property.CustomMarshalDirective), | ||
_ => false, | ||
}; | ||
if (present) { | ||
return new (self.NativePrefix, self.NativeSuffix, self.Library); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.ObjCRuntime.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
using System.Text; | ||
using Microsoft.Macios.Generator.Attributes; | ||
using Microsoft.Macios.Generator.DataModel; | ||
using Microsoft.Macios.Generator.Extensions; | ||
using TypeInfo = Microsoft.Macios.Generator.DataModel.TypeInfo; | ||
|
||
namespace Microsoft.Macios.Generator.Emitters; | ||
|
||
static partial class BindingSyntaxFactory{ | ||
readonly static string objc_msgSend = "objc_msgSend"; | ||
readonly static string objc_msgSendSuper = "objc_msgSendSuper"; | ||
|
||
static string? GetObjCMessageSendMethodName<T> (ExportData<T> exportData, | ||
TypeInfo returnType, ImmutableArray<Parameter> parameters, bool isSuper = false, bool isStret = false) where T : Enum | ||
{ | ||
var flags = exportData.Flags; | ||
if (flags is null) | ||
// flags are not set, should be a bug, but we will return null | ||
return null; | ||
|
||
// the name of the objcSend method is calculated in the following way | ||
// {CustomMarshallPrefix}_{MarshallTypeOfReturnType}_{objcSendMsg}{stret?_stret}_{string.Join('_', MarshallTypeArgs)}{nativeException?_exception}{CustomMarsahllPostfix} | ||
// we will sue a sb to make things easy to follow | ||
var sb = new StringBuilder (); | ||
|
||
// first, decide if the user created a custom marshalling by checking the flags of the export data | ||
CustomMarshalDirective? customMarshalDirective = null; | ||
if (flags.HasCustomMarshalDirective ()) { | ||
customMarshalDirective = exportData.ToCustomMarshalDirective (); | ||
} | ||
|
||
if (customMarshalDirective?.NativePrefix is not null) { | ||
sb.Append (customMarshalDirective.NativePrefix); | ||
} else if (flags.HasMarshalNativeExceptions ()) { | ||
sb.Append ("xamarin_"); | ||
} | ||
|
||
// return types do not have a reference kind | ||
sb.Append (returnType.ToMarshallType (ReferenceKind.None)); | ||
sb.Append ('_'); | ||
// append the msg method based if it is for super or not, do not append '_' intimidatingly, since if we do | ||
// not have parameters, we are done | ||
sb.Append (isSuper ? objc_msgSendSuper : objc_msgSend); | ||
if (isStret) { | ||
sb.Append ("_stret"); | ||
} | ||
// loop over params and get their native handler name | ||
if (parameters.Length > 0) { | ||
sb.Append ('_'); | ||
sb.AppendJoin ('_', parameters.Select ( p => p.Type.ToMarshallType (p.ReferenceKind))); | ||
} | ||
|
||
// check if we do have a custom marshall exception set for the export | ||
|
||
// check any possible custom postfix naming | ||
if (customMarshalDirective?.NativeSuffix is not null) { | ||
sb.Append (customMarshalDirective.NativeSuffix); | ||
} else if (flags.HasMarshalNativeExceptions ()) { | ||
sb.Append ("_exception"); | ||
} | ||
return sb.ToString (); | ||
} | ||
|
||
public static (string? Getter, string? Setter) GetObjCMessageSendMethods (in Property property, bool isSuper = false, bool isStret = false) | ||
{ | ||
if (property.IsProperty) { | ||
// the getter and the setter depend of the accessors that have been ser for the property, we do not want | ||
// to calculate things that we wont use. The export data used will aslo depend if the getter/setter has a | ||
// export attr attached | ||
var getter = property.GetAccessor (AccessorKind.Getter); | ||
string? getterMsgSend = null; | ||
if (getter is not null) { | ||
var getterExportData = getter.Value.ExportPropertyData ?? property.ExportPropertyData; | ||
if (getterExportData is not null) { | ||
getterMsgSend = GetObjCMessageSendMethodName (getterExportData.Value, property.ReturnType, [], | ||
isSuper, isStret); | ||
} | ||
} | ||
|
||
var setter = property.GetAccessor (AccessorKind.Setter); | ||
string? setterMsgSend = null; | ||
if (setter is not null) { | ||
var setterExportData = setter.Value.ExportPropertyData ?? property.ExportPropertyData; | ||
if (setterExportData is not null) { | ||
setterMsgSend = GetObjCMessageSendMethodName (setterExportData.Value, TypeInfo.Void, | ||
[property.ValueParameter], isSuper, isStret); | ||
} | ||
} | ||
return (Getter: getterMsgSend, Setter: setterMsgSend); | ||
} | ||
|
||
return default; | ||
} | ||
|
||
public static string? GetObjCMessageSendMethod (in Method method, bool isSuper = false, bool isStret = false) | ||
=> GetObjCMessageSendMethodName (method.ExportMethodData, method.ReturnType, method.Parameters, isSuper, isStret); | ||
|
||
} |
Oops, something went wrong.