[API Proposal]: Support ref fields in System.Reflection.Metadata.Ecma335.BlobEncoder
cston opened this issue · 10 comments
Background and motivation
Provide methods in System.Reflection.Metadata.Ecma335.BlobEncoder
to more directly support emitting ref fields, consistent with the corresponding APIs provided for emitting ref parameters and ref locals.
API Proposal
Provide a FieldTypeEncoder
type similar to ParameterTypeEncoder
and LocalVariableTypeEncoder
.
namespace System.Reflection.Metadata.Ecma335
{
public readonly struct BlobEncoder
{
public FieldTypeEncoder FieldTypeEncoder();
}
public readonly struct FieldTypeEncoder
{
public BlobBuilder Builder { get; }
public FieldTypeEncoder(BlobBuilder builder);
public CustomModifiersEncoder CustomModifiers();
public SignatureTypeEncoder Type(bool isByRef = false);
public void TypedReference();
}
}
API Usage
var blobBuilder = new BlobBuilder();
var encoder = new BlobEncoder(blobBuilder);
var fieldEncoder = encoder.FieldTypeEncoder();
// Ref custom modifiers: modopt(object)
var customModifiersEncoder = fieldEncoder.CustomModifiers();
customModifiersEncoder.AddModifier(MetadataTokens.TypeReferenceHandle(2), isOptional: true);
// Type: int&
var typeEncoder = fieldEncoder.Type(isByRef: true);
typeEncoder.PrimitiveType(PrimitiveTypeCode.Int32);
Alternative Designs
The alternative is the existing API which requires emitting SignatureTypeCode.ByReference
and creating a CustomModifierEncoder
explicitly. The existing API is sufficient, but inconsistent with the support for ref parameters and ref locals.
Using the existing API:
var blobBuilder = new BlobBuilder();
var encoder = new BlobEncoder(blobBuilder);
var typeEncoder = encoder.FieldSignature();
// Ref custom modifiers: modopt(object)
var customModifiersEncoder = new CustomModifiersEncoder(blobBuilder);
customModifiersEncoder.AddModifier(MetadataTokens.TypeReferenceHandle(2), isOptional: true);
// Type: int&
typeEncoder.Builder.WriteByte((byte)SignatureTypeCode.ByReference);
typeEncoder.PrimitiveType(PrimitiveTypeCode.Int32);
Risks
BlobEncoder
already includes a FieldSignature
method that returns an encoder for a field type, so having two distinct field encoder methods may be confusing.
public readonly struct BlobEncoder
{
public SignatureTypeEncoder FieldSignature();
public FieldTypeEncoder FieldTypeEncoder();
}
Tagging subscribers to this area: @dotnet/area-system-reflection-metadata
See info in area-owners.md if you want to be subscribed.
Issue Details
Background and motivation
Provide methods in System.Reflection.Metadata.Ecma335.BlobEncoder
to more directly support emitting ref fields, consistent with the corresponding APIs provided for emitting ref parameters and ref locals.
API Proposal
Provide a FieldTypeEncoder
type similar to ParameterTypeEncoder
and LocalVariableTypeEncoder
.
namespace System.Reflection.Metadata.Ecma335
{
public readonly struct BlobEncoder
{
public FieldTypeEncoder FieldTypeEncoder();
}
public readonly struct FieldTypeEncoder
{
public BlobBuilder Builder { get; }
public FieldTypeEncoder(BlobBuilder builder);
public CustomModifiersEncoder CustomModifiers();
public SignatureTypeEncoder Type(bool isByRef = false);
}
}
API Usage
var blobBuilder = new BlobBuilder();
var encoder = new BlobEncoder(blobBuilder);
var fieldEncoder = encoder.FieldTypeEncoder();
// Ref custom modifiers: modopt(object)
var customModifiersEncoder = fieldEncoder.CustomModifiers();
customModifiersEncoder.AddModifier(MetadataTokens.TypeReferenceHandle(2), isOptional: true);
// Type: int&
var typeEncoder = fieldEncoder.Type(isByRef: true);
typeEncoder.PrimitiveType(PrimitiveTypeCode.Int32);
Alternative Designs
The alternative is the existing API which requires emitting SignatureTypeCode.ByReference
and creating a CustomModifierEncoder
explicitly. The existing API is sufficient, but inconsistent with the support for ref parameters and ref locals.
Using the existing API:
var blobBuilder = new BlobBuilder();
var encoder = new BlobEncoder(blobBuilder);
// Ref custom modifiers: modopt(object)
var customModifiersEncoder = new CustomModifiersEncoder(blobBuilder);
customModifiersEncoder.AddModifier(MetadataTokens.TypeReferenceHandle(2), isOptional: true);
// Type: int&
var typeEncoder = encoder.FieldSignature();
typeEncoder.Builder.WriteByte((byte)SignatureTypeCode.ByReference);
typeEncoder.PrimitiveType(PrimitiveTypeCode.Int32);
Risks
No response
Author: | cston |
---|---|
Assignees: | - |
Labels: |
|
Milestone: | - |
@cston Will the following be needed with this new API. It is in the usage example but is also noted in the Alternative design in a manner that implies it wouldn't be needed if this new API was adopted.
// Ref custom modifiers: modopt(object)
var customModifiersEncoder = fieldEncoder.CustomModifiers();
customModifiersEncoder.AddModifier(MetadataTokens.TypeReferenceHandle(2), isOptional: true);
Edit Nevermind. A new instance is being created rather than using the existing one in the fieldEncoder
instance.
A new instance is being created rather than using the existing one in the
fieldEncoder
instance.
Actually, in both examples an instance of CustomModifiersEncoder
is created. The only difference is that the proposed FieldTypeEncoder
type includes a CustomModifiers()
method that makes it slightly more obvious how to obtain a CustomModifiersEncoder
.
The overall difference between use of the existing API and the proposed API is small. It's perhaps just a question of whether the API for emitting fields should be aligned with the existing APIs for locals and parameters.
- Let's call the method
BlobEncoder
justField
namespace System.Reflection.Metadata.Ecma335;
public partial readonly struct BlobEncoder
{
public FieldTypeEncoder Field();
}
public readonly struct FieldTypeEncoder
{
public BlobBuilder Builder { get; }
public FieldTypeEncoder(BlobBuilder builder);
public CustomModifiersEncoder CustomModifiers();
public SignatureTypeEncoder Type(bool isByRef = false);
public void TypedReference();
}
I'm working on this.
@teo-tsirpanis Please wait for @cston to confirm he doesn't already have an implementation. Work to support ref
fields is close to complete and it is possible the work has been done just not posted yet.
Please wait for @cston to confirm he doesn't already have an implementation.
I have not implemented this. The compiler is currently using the existing API.
Thanks @cston. @teo-tsirpanis Looking forward to the PR.