private void GenerateInstanceMethodCode(ILGenerator gen, CodeFlow cf, MethodInfo targetMethod, Type targetType) { var stackDescriptor = cf.LastDescriptor(); if (stackDescriptor == null) { // Nothing on the stack but something is needed CodeFlow.LoadTarget(gen); stackDescriptor = TypeDescriptor.OBJECT; } Label?skipIfNullTarget = null; if (_nullSafe) { skipIfNullTarget = GenerateNullCheckCode(gen); } if (targetType.IsValueType) { if (stackDescriptor.IsBoxed || stackDescriptor.IsReferenceType) { gen.Emit(OpCodes.Unbox_Any, targetType); } var local = gen.DeclareLocal(targetType); gen.Emit(OpCodes.Stloc, local); gen.Emit(OpCodes.Ldloca, local); } else { if (stackDescriptor.Value != targetType) { CodeFlow.InsertCastClass(gen, new TypeDescriptor(targetType)); } } GenerateCodeForArguments(gen, cf, targetMethod, _children); if (targetType.IsValueType) { gen.Emit(OpCodes.Call, targetMethod); } else { gen.Emit(OpCodes.Callvirt, targetMethod); } if (_originalPrimitiveExitTypeDescriptor != null) { // The output of the accessor will be a primitive but from the block above it might be null, // so to have a 'common stack' element at skipIfNull target we need to box the primitive CodeFlow.InsertBoxIfNecessary(gen, _originalPrimitiveExitTypeDescriptor); } if (skipIfNullTarget.HasValue) { gen.MarkLabel(skipIfNullTarget.Value); } }
private void GenerateCode(FieldInfo field, ILGenerator gen, CodeFlow cf) { var stackDescriptor = cf.LastDescriptor(); if (stackDescriptor == null) { CodeFlow.LoadTarget(gen); stackDescriptor = Spring.TypeDescriptor.OBJECT; } if (!field.IsStatic) { // Instance if (field.DeclaringType.IsValueType) { if (stackDescriptor != null && stackDescriptor.IsBoxed) { gen.Emit(OpCodes.Unbox_Any, field.DeclaringType); } } else { if (stackDescriptor == null || field.DeclaringType != stackDescriptor.Value) { gen.Emit(OpCodes.Castclass, field.DeclaringType); } } gen.Emit(OpCodes.Ldfld, field); } else { // Static if (stackDescriptor != null) { // A static field/method call will not consume what is on the stack, // it needs to be popped off. gen.Emit(OpCodes.Pop); } if (field.IsLiteral) { EmitLiteralFieldCode(gen, field); } else { gen.Emit(OpCodes.Ldsfld, field); } } }
private void GenerateCode(MethodInfo method, ILGenerator gen, CodeFlow cf) { var stackDescriptor = cf.LastDescriptor(); if (stackDescriptor == null) { CodeFlow.LoadTarget(gen); stackDescriptor = Spring.TypeDescriptor.OBJECT; } if (!method.IsStatic) { // Instance if (method.DeclaringType.IsValueType) { if (stackDescriptor != null && stackDescriptor.IsBoxed) { gen.Emit(OpCodes.Unbox_Any, method.DeclaringType); } var vtLocal = gen.DeclareLocal(method.DeclaringType); gen.Emit(OpCodes.Stloc, vtLocal); gen.Emit(OpCodes.Ldloca, vtLocal); gen.Emit(OpCodes.Call, method); } else { if (stackDescriptor == null || method.DeclaringType != stackDescriptor.Value) { gen.Emit(OpCodes.Castclass, method.DeclaringType); } gen.Emit(OpCodes.Callvirt, method); } } else { // Static if (stackDescriptor != null) { // A static field/method call will not consume what is on the stack, // it needs to be popped off. gen.Emit(OpCodes.Pop); } gen.Emit(OpCodes.Call, method); } }
public override void GenerateCode(ILGenerator gen, CodeFlow cf) { if (_name.Equals(ROOT)) { CodeFlow.LoadTarget(gen); } else { gen.Emit(OpCodes.Ldarg_2); gen.Emit(OpCodes.Ldstr, _name); gen.Emit(OpCodes.Callvirt, GetLookUpVariableMethod()); } CodeFlow.InsertCastClass(gen, _exitTypeDescriptor); cf.PushDescriptor(_exitTypeDescriptor); }
public void GenerateCode(string propertyName, ILGenerator gen, CodeFlow cf) { var descriptor = cf.LastDescriptor(); if (descriptor == null || descriptor.Value != typeof(IDictionary)) { if (descriptor == null) { CodeFlow.LoadTarget(gen); } gen.Emit(OpCodes.Castclass, typeof(IDictionary)); } gen.Emit(OpCodes.Ldstr, propertyName); gen.Emit(OpCodes.Callvirt, _getItem); }
public override void GenerateCode(ILGenerator gen, CodeFlow cf) { var descriptor = cf.LastDescriptor(); if (descriptor == null) { CodeFlow.LoadTarget(gen); } if (_indexedType == IndexedType.ARRAY) { var arrayType = _exitTypeDescriptor.Value.MakeArrayType(); gen.Emit(OpCodes.Castclass, arrayType); var child = _children[0]; cf.EnterCompilationScope(); child.GenerateCode(gen, cf); cf.ExitCompilationScope(); gen.Emit(GetLdElemInsn(_exitTypeDescriptor.Value)); } else if (_indexedType == IndexedType.LIST) { gen.Emit(OpCodes.Castclass, typeof(IList)); cf.EnterCompilationScope(); _children[0].GenerateCode(gen, cf); cf.ExitCompilationScope(); gen.Emit(OpCodes.Callvirt, _listGetItemMethod); } else if (_indexedType == IndexedType.MAP) { gen.Emit(OpCodes.Castclass, typeof(IDictionary)); // Special case when the key is an unquoted string literal that will be parsed as // a property/field reference if (_children[0] is PropertyOrFieldReference reference) { var mapKeyName = reference.Name; gen.Emit(OpCodes.Ldstr, mapKeyName); } else { cf.EnterCompilationScope(); _children[0].GenerateCode(gen, cf); cf.ExitCompilationScope(); } gen.Emit(OpCodes.Callvirt, _dictionaryGetItemMethod); } else if (_indexedType == IndexedType.OBJECT) { if (_cachedReadAccessor is not ReflectivePropertyAccessor.OptimalPropertyAccessor accessor) { throw new InvalidOperationException("No cached read accessor"); } bool isStatic; var method = accessor.Member as MethodInfo; var field = accessor.Member as FieldInfo; if (method != null) { isStatic = method.IsStatic; } else { isStatic = field.IsStatic; } var targetType = accessor.Member.DeclaringType; if (!isStatic && (descriptor == null || targetType != descriptor.Value)) { gen.Emit(OpCodes.Castclass, targetType); } if (method != null) { if (isStatic) { gen.Emit(OpCodes.Call, method); } else { gen.Emit(OpCodes.Callvirt, method); } } else { if (isStatic) { gen.Emit(OpCodes.Ldsfld, field); } else { gen.Emit(OpCodes.Ldfld, field); } } } cf.PushDescriptor(_exitTypeDescriptor); }