public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen) { var type = TargetType.GetClrType(); var member = ResolveMember(type); if (member is IXamlIlProperty prop) { codeGen.Emit(OpCodes.Call, prop.Getter); return(XamlIlNodeEmitResult.Type(0, prop.Getter.ReturnType)); } else if (member is IXamlIlField field) { if (field.IsLiteral) { TypeSystemHelpers.EmitFieldLiteral(field, codeGen); } else { codeGen.Emit(OpCodes.Ldsfld, field); } return(XamlIlNodeEmitResult.Type(0, field.FieldType)); } else { throw new XamlIlLoadException( $"Unable to resolve {Member} as static field, property, constant or enum value", this); } }
public static void EmitFieldLiteral(IXamlIlField field, IXamlIlEmitter codeGen) { var ftype = field.FieldType.IsEnum ? field.FieldType.GetEnumUnderlyingType() : field.FieldType; if (ftype.Name == "UInt64" || ftype.Name == "Int64") { codeGen.Emit(OpCodes.Ldc_I8, TypeSystemHelpers.ConvertLiteralToLong(field.GetLiteralValue())); } else if (ftype.Name == "Double") { codeGen.Emit(OpCodes.Ldc_R8, (double)field.GetLiteralValue()); } else if (ftype.Name == "Single") { codeGen.Emit(OpCodes.Ldc_R4, (float)field.GetLiteralValue()); } else if (ftype.Name == "String") { codeGen.Emit(OpCodes.Ldstr, (string)field.GetLiteralValue()); } else { codeGen.Emit(OpCodes.Ldc_I4, TypeSystemHelpers.ConvertLiteralToInt(field.GetLiteralValue())); } }
public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen) { if (!(node is XamlIlObjectInitializationNode init)) { return(null); } var supportInitType = context.Configuration.TypeMappings.SupportInitialize; var supportsInitialize = supportInitType != null && context.Configuration.TypeMappings.SupportInitialize .IsAssignableFrom(init.Type); if (supportsInitialize) { codeGen // We need a copy for/EndInit .Emit(OpCodes.Dup); if (!init.SkipBeginInit) { codeGen .Emit(OpCodes.Dup) .EmitCall(supportInitType.FindMethod(m => m.Name == "BeginInit")); } } var addToParentStack = context.RuntimeContext.ParentListField != null && !init.Type.IsValueType && context.GetOrCreateItem <XamlIlNeedsParentStackCache>().NeedsParentStack(node); if (addToParentStack) { using (var local = context.GetLocal(init.Type)) codeGen .Stloc(local.Local) .Ldloc(context.ContextLocal) .Ldloc(local.Local) .EmitCall(context.RuntimeContext.PushParentMethod) .Ldloc(local.Local); } context.Emit(init.Manipulation, codeGen, null); if (addToParentStack) { codeGen .Ldloc(context.ContextLocal) .EmitCall(context.RuntimeContext.PopParentMethod, true); } if (supportsInitialize) { codeGen .EmitCall(supportInitType.FindMethod(m => m.Name == "EndInit")); } return(XamlIlNodeEmitResult.Void(1)); }
public static IXamlIlEmitter DebugHatch(this IXamlIlEmitter emitter, string message) { #if DEBUG var debug = emitter.TypeSystem.GetType("XamlIl.XamlIlDebugHatch").FindMethod(m => m.Name == "Debug"); emitter.Emit(OpCodes.Ldstr, message); emitter.Emit(OpCodes.Call, debug); #endif return(emitter); }
public static IXamlIlEmitter EmitCall(this IXamlIlEmitter emitter, IXamlIlMethod method, bool swallowResult = false) { emitter.Emit(method.IsStatic ? OpCodes.Call : OpCodes.Callvirt, method); if (swallowResult && !(method.ReturnType.Namespace == "System" && method.ReturnType.Name == "Void")) { emitter.Emit(OpCodes.Pop); } return(emitter); }
/// <summary> /// void Populate(IServiceProvider sp, T target); /// </summary> void CompilePopulate(IXamlIlAstManipulationNode manipulation, Func <string, IXamlIlType, IXamlIlTypeBuilder> createSubType, IXamlIlEmitter codeGen, XamlIlContext context) { var emitContext = InitCodeGen(createSubType, codeGen, context, true); codeGen .Emit(OpCodes.Ldloc, emitContext.ContextLocal) .Emit(OpCodes.Ldarg_1) .Emit(OpCodes.Stfld, context.RootObjectField) .Emit(OpCodes.Ldarg_1); emitContext.Emit(manipulation, codeGen, null); codeGen.Emit(OpCodes.Ret); }
public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen) { if (!(node is XamlIlAstNewClrObjectNode n)) { return(null); } var type = n.Type.GetClrType(); var ctor = n.Constructor ?? type.FindConstructor(); if (ctor == null) { throw new XamlIlLoadException("Unable to find default constructor and no non-default one is specified", n); } for (var c = 0; c < n.Arguments.Count; c++) { context.Emit(n.Arguments[c], codeGen, ctor.Parameters[c]); } var gen = codeGen .Emit(OpCodes.Newobj, ctor); return(XamlIlNodeEmitResult.Type(0, type)); }
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen) { // Discard the stack value we are "supposed" to manipulate codeGen.Emit(OpCodes.Pop); context.Emit(Imperative, codeGen, null); return(XamlIlNodeEmitResult.Void(1)); }
/// <summary> /// void Populate(IServiceProvider sp, T target); /// </summary> void CompilePopulate(IFileSource fileSource, IXamlIlAstManipulationNode manipulation, Func <string, IXamlIlType, IXamlIlTypeBuilder> createSubType, IXamlIlEmitter codeGen, XamlIlContext context) { // Uncomment to inspect generated IL in debugger //codeGen = new RecordingIlEmitter(codeGen); var emitContext = InitCodeGen(fileSource, createSubType, codeGen, context, true); codeGen .Emit(OpCodes.Ldloc, emitContext.ContextLocal) .Emit(OpCodes.Ldarg_1) .Emit(OpCodes.Stfld, context.RootObjectField) .Emit(OpCodes.Ldloc, emitContext.ContextLocal) .Emit(OpCodes.Ldarg_1) .Emit(OpCodes.Stfld, context.IntermediateRootObjectField) .Emit(OpCodes.Ldarg_1); emitContext.Emit(manipulation, codeGen, null); codeGen.Emit(OpCodes.Ret); }
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen) { var rv = context.Emit(Value, codeGen, Local.Type); codeGen.Emit(OpCodes.Dup); context.StLocal(Local, codeGen); return(XamlIlNodeEmitResult.Type(0, rv.ReturnType)); }
public void StLocal(XamlIlAstCompilerLocalNode node, IXamlIlEmitter codeGen) { if (!_locals.TryGetValue(node, out var local)) { _locals[node] = local = codeGen.DefineLocal(node.Type); } codeGen.Emit(OpCodes.Stloc, local); }
public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen) { if (!(node is XamlIlPropertyAssignmentNode an)) return null; var callOp = an.Property.Setter.IsStatic ? OpCodes.Call : OpCodes.Callvirt; context.Emit(an.Value, codeGen, an.Property.Setter.Parameters.Last()); codeGen.Emit(callOp, an.Property.Setter); return XamlIlNodeEmitResult.Void(1); }
public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter ilgen) { if (!(node is XamlIlMarkupExtensionNode me)) { return(null); } XamlIlNeedsParentStackCache.Verify(context, node); var prop = context.ParentNodes().OfType <XamlIlPropertyAssignmentNode>().FirstOrDefault(); var needProvideValueTarget = me.ProvideValue.Parameters.Count != 0 && context.RuntimeContext.PropertyTargetObject != null && prop != null; void EmitPropertyDescriptor() { if (context.Configuration.TypeMappings.ProvideValueTargetPropertyEmitter ?.Invoke(context, ilgen, prop.Property) == true) { return; } ilgen.Ldstr(prop.Property.Name); } context.Emit(me.Value, ilgen, me.Value.Type.GetClrType()); if (me.ProvideValue.Parameters.Count > 0) { ilgen .Emit(OpCodes.Ldloc, context.ContextLocal); } if (needProvideValueTarget) { ilgen .Ldloc(context.ContextLocal); EmitPropertyDescriptor(); ilgen .Stfld(context.RuntimeContext.PropertyTargetProperty); } ilgen.EmitCall(me.ProvideValue); if (needProvideValueTarget) { ilgen .Ldloc(context.ContextLocal) .Ldnull() .Stfld(context.RuntimeContext.PropertyTargetProperty); } return(XamlIlNodeEmitResult.Type(0, me.ProvideValue.ReturnType)); }
public void LdLocal(XamlIlAstCompilerLocalNode node, IXamlIlEmitter codeGen) { if (_locals.TryGetValue(node, out var local)) { codeGen.Emit(OpCodes.Ldloc, local); } else { throw new XamlIlLoadException("Attempt to read uninitialized local variable", node); } }
XamlIlEmitContext InitCodeGen( IFileSource file, Func <string, IXamlIlType, IXamlIlTypeBuilder> createSubType, IXamlIlEmitter codeGen, XamlIlContext context, bool needContextLocal) { IXamlIlLocal contextLocal = null; if (needContextLocal) { contextLocal = codeGen.DefineLocal(context.ContextType); // Pass IService provider as the first argument to context factory codeGen .Emit(OpCodes.Ldarg_0); context.Factory(codeGen); codeGen.Emit(OpCodes.Stloc, contextLocal); } var emitContext = new XamlIlEmitContext(codeGen, _configuration, context, contextLocal, createSubType, file, Emitters); return(emitContext); }
public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen) { if (!(node is XamlIlPropertyValueManipulationNode pvm)) { return(null); } codeGen.Emit(pvm.Property.Getter.IsStatic ? OpCodes.Call : OpCodes.Callvirt, pvm.Property.Getter); context.Emit(pvm.Manipulation, codeGen, null); return(XamlIlNodeEmitResult.Void(1)); }
public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen) { if (!(node is XamlIlAstTextNode text)) { return(null); } if (!text.Type.GetClrType().Equals(context.Configuration.WellKnownTypes.String)) { throw new XamlIlLoadException("Text node type wasn't resolved to well-known System.String", node); } codeGen.Emit(OpCodes.Ldstr, text.Text); return(XamlIlNodeEmitResult.Type(0, text.Type.GetClrType())); }
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen) { if (Constant is string) { codeGen.Emit(OpCodes.Ldstr, (string)Constant); } else if (Constant is long || Constant is ulong) { codeGen.Emit(OpCodes.Ldc_I8, TypeSystemHelpers.ConvertLiteralToLong(Constant)); } else if (Constant is float f) { codeGen.Emit(OpCodes.Ldc_R4, f); } else if (Constant is double d) { codeGen.Emit(OpCodes.Ldc_R8, d); } else { codeGen.Emit(OpCodes.Ldc_I4, TypeSystemHelpers.ConvertLiteralToInt(Constant)); } return(XamlIlNodeEmitResult.Type(0, Type.GetClrType())); }
public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen) { if (!(node is XamlIlManipulationGroupNode group)) { return(null); } if (group.Children.Count == 0) { codeGen.Emit(OpCodes.Pop); } else { for (var c = 0; c < group.Children.Count; c++) { if (c != group.Children.Count - 1) { codeGen.Emit(OpCodes.Dup); } context.Emit(group.Children[c], codeGen, null); } } return(XamlIlNodeEmitResult.Void(1)); }
public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen) { if (!(node is XamlIlValueWithManipulationNode vwm)) { return(null); } var created = context.Emit(vwm.Value, codeGen, vwm.Type.GetClrType()); if (vwm.Manipulation != null && !(vwm.Manipulation is XamlIlManipulationGroupNode grp && grp.Children.Count == 0)) { codeGen.Emit(OpCodes.Dup); context.Emit(vwm.Manipulation, codeGen, null); } return(XamlIlNodeEmitResult.Type(0, created.ReturnType)); }
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen) { var type = Value.GetClrType(); var method = _systemType.Methods.FirstOrDefault(m => m.Name == "GetTypeFromHandle" && m.Parameters.Count == 1 && m.Parameters[0].Name == "RuntimeTypeHandle"); if (method == null) { throw new XamlIlTypeSystemException( $"Unable to find GetTypeFromHandle(RuntimeTypeHandle) on {_systemType.GetFqn()}"); } codeGen .Emit(OpCodes.Ldtoken, type) .Emit(OpCodes.Call, method); return(XamlIlNodeEmitResult.Type(0, _systemType)); }
void CompileBuild(IXamlIlAstValueNode rootInstance, Func <string, IXamlIlType, IXamlIlTypeBuilder> createSubType, IXamlIlEmitter codeGen, XamlIlContext context, IXamlIlMethod compiledPopulate) { var needContextLocal = !(rootInstance is XamlIlAstNewClrObjectNode newObj && newObj.Arguments.Count == 0); var emitContext = InitCodeGen(createSubType, codeGen, context, needContextLocal); var rv = codeGen.DefineLocal(rootInstance.Type.GetClrType()); emitContext.Emit(rootInstance, codeGen, rootInstance.Type.GetClrType()); codeGen .Emit(OpCodes.Stloc, rv) .Emit(OpCodes.Ldarg_0) .Emit(OpCodes.Ldloc, rv) .Emit(OpCodes.Call, compiledPopulate) .Emit(OpCodes.Ldloc, rv) .Emit(OpCodes.Ret); }
/// <summary> /// /// T Build(IServiceProvider sp); /// </summary> XamlIlEmitContext InitCodeGen(Func <string, IXamlIlType, IXamlIlTypeBuilder> createSubType, IXamlIlEmitter codeGen, XamlIlContext context, bool needContextLocal) { IXamlIlLocal contextLocal = null; if (needContextLocal) { contextLocal = codeGen.DefineLocal(context.ContextType); codeGen .Emit(OpCodes.Ldarg_0) .Emit(OpCodes.Newobj, context.Constructor) .Emit(OpCodes.Stloc, contextLocal); } var emitContext = new XamlIlEmitContext(codeGen, _configuration, context, contextLocal, createSubType, Emitters); return(emitContext); }
public static IXamlIlEmitter Ldtoken(this IXamlIlEmitter emitter, IXamlIlMethod method) => emitter.Emit(OpCodes.Ldtoken, method);
public static IXamlIlEmitter Ldtoken(this IXamlIlEmitter emitter, IXamlIlType type) => emitter.Emit(OpCodes.Ldtoken, type);
public static IXamlIlEmitter Pop(this IXamlIlEmitter emitter) => emitter.Emit(OpCodes.Pop);
public static IXamlIlEmitter Dup(this IXamlIlEmitter emitter) => emitter.Emit(OpCodes.Dup);
public static IXamlIlEmitter Ret(this IXamlIlEmitter emitter) => emitter.Emit(OpCodes.Ret);
public static IXamlIlEmitter Brtrue(this IXamlIlEmitter emitter, IXamlIlLabel label) => emitter.Emit(OpCodes.Brtrue, label);
public static IXamlIlEmitter Bgt(this IXamlIlEmitter emitter, IXamlIlLabel label) => emitter.Emit(OpCodes.Bgt, label);