-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
Replace RuntimeHelpers.CreateSpan<T>(LdMemberToken)
with new T[] { }
#3380
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -143,6 +143,40 @@ internal static bool TransformSpanTArrayInitialization(NewObj inst, StatementTra | |||
return false; | ||||
} | ||||
|
||||
internal static bool TransformRuntimeHelpersCreateSpanInitialization(Call inst, StatementTransformContext context, out ILInstruction replacement) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thoughts on the method name? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not really, I am bad at naming things... 😅 ... luckily I had nine months to name my children... |
||||
{ | ||||
replacement = null; | ||||
if (!context.Settings.ArrayInitializers) | ||||
return false; | ||||
if (MatchRuntimeHelpersCreateSpan(inst, context, out var elementType, out var field)) | ||||
{ | ||||
if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) | ||||
{ | ||||
var valuesList = new List<ILInstruction>(); | ||||
var initialValue = field.GetInitialValue(context.PEFile, context.TypeSystem); | ||||
var elementTypeSize = elementType.GetSize(); | ||||
if (elementTypeSize <= 0 || initialValue.Length % elementTypeSize != 0) | ||||
return false; | ||||
|
||||
var size = initialValue.Length / elementTypeSize; | ||||
if (context.Settings.Utf8StringLiterals && | ||||
elementType.IsKnownType(KnownTypeCode.Byte) && | ||||
DecodeUTF8String(initialValue, size, out string text)) | ||||
{ | ||||
replacement = new LdStrUtf8(text); | ||||
return true; | ||||
} | ||||
if (DecodeArrayInitializer(elementType, initialValue, new[] { size }, valuesList)) | ||||
{ | ||||
var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, new ArrayType(context.TypeSystem, elementType)); | ||||
replacement = BlockFromInitializer(tempStore, elementType, new[] { size }, valuesList.ToArray()); | ||||
return true; | ||||
} | ||||
Comment on lines
+162
to
+174
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the same as for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could do that, yes... |
||||
} | ||||
} | ||||
return false; | ||||
} | ||||
|
||||
private static unsafe bool DecodeUTF8String(BlobReader blob, int size, out string text) | ||||
{ | ||||
if (size > blob.RemainingBytes) | ||||
|
@@ -187,6 +221,27 @@ static bool MatchSpanTCtorWithPointerAndSize(NewObj newObj, StatementTransformCo | |||
return true; | ||||
} | ||||
|
||||
static bool MatchRuntimeHelpersCreateSpan(Call inst, StatementTransformContext context, out IType elementType, out FieldDefinition field) | ||||
{ | ||||
field = default; | ||||
elementType = null; | ||||
IType type = inst.Method.DeclaringType; | ||||
if (type.Namespace != "System.Runtime.CompilerServices" || type.Name != "RuntimeHelpers" || type.TypeParameterCount != 0) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this the right way to check? Should I have created a "known" type? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There already exists
Although that's missing the check for I don't think it's necessary to add a known type for this... |
||||
return false; | ||||
if (inst.Arguments.Count != 1) | ||||
return false; | ||||
IMethod method = inst.Method; | ||||
if (method.Name != "CreateSpan" || method.TypeArguments.Count != 1) | ||||
return false; | ||||
Comment on lines
+231
to
+235
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should I be checking the full method signature? I noticed that the other handler doesn't check argument types. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. checking more is usually better than checking less... note that the code in that file is very old and thus is not using some of the helpers and is not following the style of later transform implementations There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Addendum: for methods we usually check the name, the number of parameters and then validate all the arguments, so checking the parameter types is usually not necessary. |
||||
elementType = method.TypeArguments[0]; | ||||
if (!inst.Arguments[0].UnwrapConv(ConversionKind.StopGCTracking).MatchLdMemberToken(out var member)) | ||||
return false; | ||||
if (member.MetadataToken.IsNil) | ||||
return false; | ||||
field = context.PEFile.Metadata.GetFieldDefinition((FieldDefinitionHandle)member.MetadataToken); | ||||
return true; | ||||
} | ||||
|
||||
bool DoTransformMultiDim(ILFunction function, Block body, int pos) | ||||
{ | ||||
if (pos >= body.Instructions.Count - 2) | ||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I have put these in a new file and modified the options? It currently fails for Roslyn v1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason why these tests are "correctness" tests and not "pretty" tests?
It seems like this is a relatively new language feature... you can simply use the
CSx
preprocessor symbol that matches the earliest version of C# where this feature is supported.