Skip to content

Commit 83ee1f4

Browse files
committed
implements basic support for fields (#342, #345)
1 parent 8b3b514 commit 83ee1f4

13 files changed

Lines changed: 94 additions & 50 deletions

File tree

Cecilifier.ApiDriver.MonoCecil/MonoCecilGeneratorDriver.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ public static void Main(string[] args)
6262

6363
public void EmitCilInstruction<T>(IVisitorContext context, IlContext il, OpCode opCode, T? operand, string? comment = null)
6464
{
65-
var operandStr = operand == null ? string.Empty : $", {operand}";
65+
var operandStr = operand switch
66+
{
67+
CilOperandValue cilOperand => $", {cilOperand.Value}",
68+
_ => operand == null ? string.Empty : $", {operand}"
69+
};
6670
context.Generate($"{il.VariableName}.Emit({opCode.ConstantName()}{operandStr});{(comment != null ? $" // {comment}" : string.Empty)}");
6771
context.WriteNewLine();
6872
}

Cecilifier.ApiDriver.SystemReflectionMetadata/SystemReflectionMetadataDefinitionsFactory.cs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,31 +115,22 @@ public IEnumerable<string> Method(IVisitorContext context, string declaringTypeN
115115
public IEnumerable<string> Constructor(IVisitorContext context, MemberDefinitionContext memberDefinitionContext, string typeName, bool isStatic, string methodAccessibility, string[] paramTypes, string? methodDefinitionPropertyValues = null)
116116
{
117117
var parameterlessCtorSignatureVar = context.Naming.SyntheticVariable("parameterlessCtorSignature", ElementKind.LocalVariable);
118-
var ctorBlobIndexVar = context.Naming.SyntheticVariable("parameterlessCtorBlobIndex", ElementKind.LocalVariable);
119-
120118
yield return Format(
121119
$$"""
122120
var {{parameterlessCtorSignatureVar}} = new BlobBuilder();
123121
new BlobEncoder({{parameterlessCtorSignatureVar}})
124122
.MethodSignature(isInstanceMethod: {{ (!isStatic).ToKeyword()}})
125123
.Parameters(0, returnType => returnType.Void(), parameters => { });
126-
127-
var {{ctorBlobIndexVar}} = metadata.GetOrAddBlob({{parameterlessCtorSignatureVar}});
128-
129-
var objectCtorMemberRef = metadata.AddMemberReference(
130-
{{memberDefinitionContext.ParentDefinitionVariableName}},
131-
metadata.GetOrAddString(".ctor"),
132-
{{ctorBlobIndexVar}});
133124
""");
134125

135-
((SystemReflectionMetadataContext) context).DelayedDefinitionsManager.RegisterMethodDefinition( memberDefinitionContext.ParentDefinitionVariableName, (ctx, methodRecord) =>
126+
((SystemReflectionMetadataContext) context).DelayedDefinitionsManager.RegisterMethodDefinition(memberDefinitionContext.ParentDefinitionVariableName, (ctx, methodRecord) =>
136127
{
137128
var ctorDefVar = ctx.Naming.SyntheticVariable("ctor", ElementKind.LocalVariable);
138129
ctx.Generate($"""
139130
var {ctorDefVar} = metadata.AddMethodDefinition(
140-
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
131+
{(isStatic ? "MethodAttributes.Private | MethodAttributes.Static" : "MethodAttributes.Public")} | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
141132
MethodImplAttributes.IL | MethodImplAttributes.Managed,
142-
metadata.GetOrAddString(".ctor"),
133+
metadata.GetOrAddString("{(isStatic ? ".cctor" : ".ctor")}"),
143134
metadata.GetOrAddBlob({parameterlessCtorSignatureVar}),
144135
methodBodyStream.AddMethodBody({memberDefinitionContext.IlContext.VariableName}),
145136
parameterList: {methodRecord.FirstParameterHandle});
@@ -163,7 +154,7 @@ public IEnumerable<string> Field(IVisitorContext context, in MemberDefinitionCon
163154
BlobBuilder {fieldSignatureVar} = new();
164155
new BlobEncoder({fieldSignatureVar})
165156
.FieldSignature()
166-
{typedTypeResolver.ResolveForEncoder(fieldType, TargetEncoderKind.Field, false)};
157+
.{typedTypeResolver.ResolveForEncoder(fieldType, TargetEncoderKind.Field, false)};
167158
168159
var {memberDefinitionContext.MemberDefinitionVariableName} = metadata.AddFieldDefinition({fieldAttributes}, metadata.GetOrAddString("{fieldOrEvent.Name}"), metadata.GetOrAddBlob({fieldSignatureVar}));
169160
"""

Cecilifier.ApiDriver.SystemReflectionMetadata/SystemReflectionMetadataGeneratorDriver.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Reflection.Emit;
2+
using System.Text;
23
using Cecilifier.Core;
34
using Cecilifier.Core.ApiDriver;
45
using Cecilifier.Core.AST;
@@ -125,7 +126,8 @@ public IlContext NewIlContext(IVisitorContext context, string memberName, string
125126

126127
public void EmitCilInstruction<T>(IVisitorContext context, IlContext il, OpCode opCode, T? operand, string? comment = null)
127128
{
128-
context.Generate($"{il.VariableName}.OpCode(ILOpCode.{opCode.OpCodeName()});{(comment != null ? $" // {comment}" : string.Empty)}");
129+
var mappedOpCodeName = MapSystemReflectionOpCodeNameToSystemReflectionMetadata(opCode);
130+
context.Generate($"{il.VariableName}.OpCode(ILOpCode.{mappedOpCodeName});{(comment != null ? $" // {comment}" : string.Empty)}");
129131
context.WriteNewLine();
130132
if (operand != null)
131133
{
@@ -139,6 +141,10 @@ public void EmitCilInstruction<T>(IVisitorContext context, IlContext il, OpCode
139141
context.Generate($"{il.VariableName}.Token({handle.VariableName});");
140142
break;
141143

144+
case CilOperandValue operandValue:
145+
context.Generate($"{il.VariableName}.CodeBuilder.Write{operandValue.Type.Name}({operandValue.Value});");
146+
break;
147+
142148
default:
143149
//TODO: Fix name of WriteX() method to be called; it is not always derivable from the type
144150
context.Generate($"{il.VariableName}.CodeBuilder.Write{operand.GetType().Name}({operand});");
@@ -152,4 +158,18 @@ public void EmitCilInstruction(IVisitorContext context, IlContext il, OpCode opC
152158
{
153159
EmitCilInstruction<string>(context, il, opCode, null);
154160
}
161+
162+
private static string MapSystemReflectionOpCodeNameToSystemReflectionMetadata(OpCode opCode)
163+
{
164+
var reflectionOpCodeName = opCode.OpCodeName();
165+
if (reflectionOpCodeName.StartsWith("Ldc_"))
166+
{
167+
StringBuilder buffer = new(reflectionOpCodeName);
168+
buffer[4] = Char.ToLower(buffer[4]); // Ldc_Ix => Ldc_ix, Ldc_Rx => Ldc_rx, etc.
169+
return buffer.ToString();
170+
}
171+
172+
return reflectionOpCodeName;
173+
}
174+
155175
}

Cecilifier.ApiDriver.SystemReflectionMetadata/TypeSystem/SystemReflectionMetadataMemberResolver.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,28 @@ public string ResolveDefaultConstructor(ITypeSymbol type, string derivedTypeVar)
6060
return voidParameterlessMethodRef.VariableName;
6161
}
6262

63-
public string ResolveField(IFieldSymbol field) => throw new NotImplementedException();
63+
public string ResolveField(IFieldSymbol field)
64+
{
65+
var found = context.DefinitionVariables.GetVariable(field.Name, VariableMemberKind.Field, field.ContainingType.ToDisplayString());
66+
if (found.IsValid)
67+
return found.VariableName;
68+
69+
var declaringTypeVar = context.DefinitionVariables.GetVariable(field.ContainingType.ToDisplayString(), VariableMemberKind.Type, field.ContainingType.ContainingType?.ToDisplayString());
70+
declaringTypeVar.ThrowIfVariableIsNotValid();
71+
72+
var fieldSignatureVarName = context.Naming.SyntheticVariable($"{field.ToValidVariableName()}Signature", ElementKind.LocalVariable);
73+
var fieldRefVarName = context.Naming.SyntheticVariable(field.Name, ElementKind.Field);
74+
var typeResolver = (SystemReflectionMetadataTypeResolver) context.TypeResolver;
75+
context.Generate($"""
76+
BlobBuilder {fieldSignatureVarName} = new();
77+
new BlobEncoder({fieldSignatureVarName}).FieldSignature().{typeResolver.ResolveForEncoder(field.Type, TargetEncoderKind.Field, false)};
78+
var {fieldRefVarName} = metadata.AddMemberReference({declaringTypeVar.VariableName}, metadata.GetOrAddString("{field.Name}"), metadata.GetOrAddBlob({fieldSignatureVarName}));
79+
""");
80+
81+
context.WriteNewLine();
82+
83+
context.DefinitionVariables.RegisterNonMethod(field.ContainingType.ToDisplayString(), field.Name, VariableMemberKind.Field, fieldRefVarName);
84+
85+
return fieldRefVarName;
86+
}
6487
}

Cecilifier.ApiDriver.SystemReflectionMetadata/TypeSystem/SystemReflectionMetadataTypeResolver.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,10 @@ public string ResolveForEncoder(ITypeSymbol type, TargetEncoderKind encoderKind,
4444
}
4545

4646
if (type.IsPrimitiveType())
47-
return $"{(encoderKind == TargetEncoderKind.Field ? "" : "Type()")}.{type.MetadataName}()";
47+
return $"{(encoderKind == TargetEncoderKind.Field ? "" : "Type().")}{type.MetadataName}()";
4848

49-
return $"""
50-
Type(isByRef: {isByRef.ToKeyword()})
51-
.Type(
52-
{ResolveAny(type)},
53-
isValueType: {type.IsValueType.ToKeyword()})
54-
""";
49+
return (encoderKind == TargetEncoderKind.Field ? "" : $"Type(isByRef: {isByRef.ToKeyword()}).") +
50+
$"Type({ResolveAny(type)}, isValueType: {type.IsValueType.ToKeyword()})";
5551
}
5652

5753
public override string ResolvePredefinedType(ITypeSymbol type) => $"""

Cecilifier.Core.Tests/Tests/Integration/FieldsTestCase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Cecilifier.Core.Tests.Integration
88
{
99
[TestFixture(typeof(MonoCecilContext))]
1010
[TestFixture(typeof(SystemReflectionMetadataContext))]
11-
[EnableForContext<SystemReflectionMetadataContext>(nameof(TestSingleField))]
11+
[EnableForContext<SystemReflectionMetadataContext>(nameof(TestSingleField), nameof(TestStatic))]
1212
public class FieldsTestCase<TResource> : ResourceTestBase<TResource> where TResource : IVisitorContext
1313
{
1414
[Test]

Cecilifier.Core/AST/AssignmentVisitor.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Collections.Generic;
22
using System;
33
using System.Reflection.Emit;
4+
using Cecilifier.Core.ApiDriver;
45
using Microsoft.CodeAnalysis;
56
using Microsoft.CodeAnalysis.CSharp;
67
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -214,7 +215,7 @@ bool HandleIndexer(SyntaxNode node, LinkedListNode<string> lastInstructionLoadin
214215
private void EmitIndirectStore(ITypeSymbol typeBeingStored)
215216
{
216217
var indirectStoreOpCode = typeBeingStored.StindOpCodeFor();
217-
Context.EmitCilInstruction(ilVar, indirectStoreOpCode, indirectStoreOpCode == OpCodes.Stobj ? Context.TypeResolver.ResolveAny(typeBeingStored.ElementTypeSymbolOf()) : null);
218+
Context.ApiDriver.EmitCilInstruction(Context, ilVar, indirectStoreOpCode, indirectStoreOpCode == OpCodes.Stobj ? Context.TypeResolver.ResolveAny(typeBeingStored.ElementTypeSymbolOf()) : null);
218219
}
219220

220221
private void PropertyAssignment(IdentifierNameSyntax node, IPropertySymbol property)
@@ -238,7 +239,7 @@ private void PropertyAssignment(IdentifierNameSyntax node, IPropertySymbol prope
238239
private void FieldAssignment(IFieldSymbol field, IdentifierNameSyntax name)
239240
{
240241
if (field.IsVolatile)
241-
Context.EmitCilInstruction(ilVar, OpCodes.Volatile);
242+
Context.ApiDriver.EmitCilInstruction(Context, ilVar, OpCodes.Volatile);
242243

243244
field.EnsureFieldExists(Context, name);
244245
var fieldReference = field.FieldResolverExpression(Context);
@@ -274,7 +275,7 @@ private void MemberAssignment(ITypeSymbol memberType, RefKind memberRefKind, str
274275
}
275276
else
276277
{
277-
Context.EmitCilInstruction(ilVar, storeOpCode, memberReference);
278+
Context.ApiDriver.EmitCilInstruction(Context, ilVar, storeOpCode, new CilMetadataHandle(memberReference));
278279
}
279280
}
280281

Cecilifier.Core/AST/ConstructorDeclarationVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ private void ProcessFieldInitialization(TypeDeclarationSyntax declaringClass, Il
193193
? OpCodes.Stsfld
194194
: OpCodes.Stfld;
195195

196-
Context.EmitCilInstruction(ctorBodyIL, fieldStoreOpCode, fieldVarDef.VariableName);
196+
Context.ApiDriver.EmitCilInstruction(Context, ctorBodyIL, fieldStoreOpCode, new CilMetadataHandle(fieldVarDef.VariableName));
197197
}
198198

199199
// Handles property initialization...

0 commit comments

Comments
 (0)