forked from dotnet/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStubCodeContext.cs
146 lines (125 loc) · 5.78 KB
/
StubCodeContext.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
namespace Microsoft.Interop
{
public abstract record StubCodeContext
{
/// <summary>
/// Code generation stage
/// </summary>
public enum Stage
{
/// <summary>
/// Invalid stage
/// </summary>
Invalid,
/// <summary>
/// Perform any setup required
/// </summary>
Setup,
/// <summary>
/// Convert managed data to native data
/// </summary>
Marshal,
/// <summary>
/// Pin data in preparation for calling the generated P/Invoke
/// </summary>
Pin,
/// <summary>
/// Convert managed data to native data, assuming that any values pinned in the <see cref="Pin"/> stage are pinned.
/// </summary>
PinnedMarshal,
/// <summary>
/// Call the generated P/Invoke
/// </summary>
/// <remarks>
/// <see cref="IMarshallingGenerator.AsArgument(TypePositionInfo)"/> should provide the
/// argument to pass to the P/Invoke
/// </remarks>
Invoke,
/// <summary>
/// Capture native values to ensure that we do not leak if an exception is thrown during unmarshalling
/// </summary>
UnmarshalCapture,
/// <summary>
/// Convert native data to managed data
/// </summary>
Unmarshal,
/// <summary>
/// Notify a marshaller object that the Invoke stage and all stages preceding the Invoke stage
/// successfully completed without any exceptions.
/// </summary>
NotifyForSuccessfulInvoke,
/// <summary>
/// Perform any cleanup required
/// </summary>
Cleanup,
/// <summary>
/// Convert native data to managed data even in the case of an exception during
/// the non-cleanup phases.
/// </summary>
GuaranteedUnmarshal
}
/// <summary>
/// The current stage being generated.
/// </summary>
public Stage CurrentStage { get; init; } = Stage.Invalid;
/// <summary>
/// <c>CustomTypeMarshallingDirection.In</c> means method import like <c>[LibraryImport]</c>.
/// <c>CustomTypeMarshallingDirection.Out</c> means method export like in <c>[UnmanagedCallersOnly]</c> or in <c>[JSExport]</c>
/// </summary>
public CustomTypeMarshallingDirection Direction { get; init; } = CustomTypeMarshallingDirection.In;
/// <summary>
/// Gets the currently targeted framework and version for stub code generation.
/// </summary>
/// <returns>A framework value and version.</returns>
public abstract (TargetFramework framework, Version version) GetTargetFramework();
/// <summary>
/// The stub emits code that runs in a single stack frame and the frame spans over the native context.
/// </summary>
/// <remarks>
/// Stubs that emit code into a single frame that spans the native context can do two things:
/// <list type="bullet">
/// <item> A <c>fixed</c> statement can be used on an individual value in the <see cref="Stage.Pin"/> stage and the pointer can be passed to native code.</item>
/// <item>Memory can be allocated via the <c>stackalloc</c> keyword and will live through the full native context of the call.</item>
/// </list>
/// </remarks>
public abstract bool SingleFrameSpansNativeContext { get; }
/// <summary>
/// Additional variables other than the {managedIdentifier} and {nativeIdentifier} variables can be added to the stub to track additional state for the marshaller in the stub in the Setup phase, and they will live across all phases of the stub.
/// </summary>
/// <remarks>
/// When this property is <c>false</c>, any additional variables can only be considered to have the state they had immediately after the Setup phase.
/// </remarks>
public abstract bool AdditionalTemporaryStateLivesAcrossStages { get; }
/// <summary>
/// If this context is a nested context, return the parent context. Otherwise, return <c>null</c>.
/// </summary>
public StubCodeContext? ParentContext { get; protected init; }
/// <summary>
/// Suffix for all generated native identifiers.
/// </summary>
public const string GeneratedNativeIdentifierSuffix = "_native";
/// <summary>
/// Get managed and native instance identifiers for the <paramref name="info"/>
/// </summary>
/// <param name="info">Object for which to get identifiers</param>
/// <returns>Managed and native identifiers</returns>
public virtual (string managed, string native) GetIdentifiers(TypePositionInfo info)
{
return (info.InstanceIdentifier, $"__{info.InstanceIdentifier.TrimStart('@')}{GeneratedNativeIdentifierSuffix}");
}
/// <summary>
/// Compute identifiers that are unique for this generator
/// </summary>
/// <param name="info">TypePositionInfo the new identifier is used in service of.</param>
/// <param name="name">Name of variable.</param>
/// <returns>New identifier name for use.</returns>
public virtual string GetAdditionalIdentifier(TypePositionInfo info, string name)
{
return $"{GetIdentifiers(info).native}__{name}";
}
}
}