private WriteBack AddressOfWriteBackCore(IndexExpression node) { // emit instance, if any LocalBuilder?instanceLocal = null; Type? instanceType = null; if (node.Object != null) { EmitInstance(node.Object, out instanceType); // store in local IL.Emit(OpCodes.Dup); IL.Emit(OpCodes.Stloc, instanceLocal = GetInstanceLocal(instanceType)); } // Emit indexes. We don't allow byref args, so no need to worry // about write-backs or EmitAddress var n = node.ArgumentCount; var args = new LocalBuilder[n]; for (var i = 0; i < n; i++) { var arg = node.GetArgument(i); EmitExpression(arg); var argLocal = GetLocal(arg.Type); IL.Emit(OpCodes.Dup); IL.Emit(OpCodes.Stloc, argLocal); args[i] = argLocal; } // emit the get EmitGetIndexCall(node, instanceType); // emit the address of the value var valueLocal = GetLocal(node.Type); IL.Emit(OpCodes.Stloc, valueLocal); IL.Emit(OpCodes.Ldloca, valueLocal); // Set the property after the method call // don't re-evaluate anything return(@this => { if (instanceLocal != null) { @this.IL.Emit(OpCodes.Ldloc, instanceLocal); @this.FreeLocal(instanceLocal); } foreach (var arg in args) { @this.IL.Emit(OpCodes.Ldloc, arg); @this.FreeLocal(arg); } @this.IL.Emit(OpCodes.Ldloc, valueLocal); @this.FreeLocal(valueLocal); @this.EmitSetIndexCall(node, instanceLocal?.LocalType); }); }
private void AddressOf(IndexExpression node, Type type) { if (!TypeUtils.AreEquivalent(type, node.Type) || node.Indexer != null) { EmitExpressionAddress(node, type); return; } if (node.Object == null) { throw new ArgumentException(string.Empty, nameof(node)); } if (node.ArgumentCount == 1) { EmitExpression(node.Object); EmitExpression(node.GetArgument(0)); IL.Emit(OpCodes.Ldelema, node.Type); } else { var address = node.Object.Type.GetMethod("Address", BindingFlags.Public | BindingFlags.Instance); EmitMethodCall(node.Object, address, node); } }
protected override Expression VisitIndex(IndexExpression node) { if (node.Object != null) { Visit(node.Object); } else { Debug.Assert(node.Indexer != null); Out(node.Indexer.DeclaringType.Name); } if (node.Indexer != null) { Out('.'); Out(node.Indexer.Name); } Out('['); for (int i = 0, n = node.ArgumentCount(); i < n; i++) { if (i > 0) { Out(", "); } Visit(node.GetArgument(i)); } Out(']'); return(node); }
private WriteBack AddressOfWriteBackCore(IndexExpression node) { // emit instance, if any LocalBuilder instanceLocal = null; Type instanceType = null; if (node.Object != null) { EmitInstance(node.Object, out instanceType); // store in local _ilg.Emit(OpCodes.Dup); _ilg.Emit(OpCodes.Stloc, instanceLocal = GetInstanceLocal(instanceType)); } // Emit indexes. We don't allow byref args, so no need to worry // about write-backs or EmitAddress int n = node.ArgumentCount; var args = new LocalBuilder[n]; for (var i = 0; i < n; i++) { Expression arg = node.GetArgument(i); EmitExpression(arg); LocalBuilder argLocal = GetLocal(arg.Type); _ilg.Emit(OpCodes.Dup); _ilg.Emit(OpCodes.Stloc, argLocal); args[i] = argLocal; } // emit the get EmitGetIndexCall(node, instanceType); // emit the address of the value LocalBuilder valueLocal = GetLocal(node.Type); _ilg.Emit(OpCodes.Stloc, valueLocal); _ilg.Emit(OpCodes.Ldloca, valueLocal); // Set the property after the method call // don't re-evaluate anything return @this => { if (instanceLocal != null) { @this._ilg.Emit(OpCodes.Ldloc, instanceLocal); @this.FreeLocal(instanceLocal); } foreach (LocalBuilder arg in args) { @this._ilg.Emit(OpCodes.Ldloc, arg); @this.FreeLocal(arg); } @this._ilg.Emit(OpCodes.Ldloc, valueLocal); @this.FreeLocal(valueLocal); @this.EmitSetIndexCall(node, instanceLocal?.LocalType); }; }
private void AddressOf(IndexExpression node, Type type) { if (!TypeUtils.AreEquivalent(type, node.Type) || node.Indexer != null) { EmitExpressionAddress(node, type); return; } if (node.ArgumentCount == 1) { EmitExpression(node.Object); EmitExpression(node.GetArgument(0)); _ilg.Emit(OpCodes.Ldelema, node.Type); } else { MethodInfo address = node.Object.Type.GetMethod("Address", BindingFlags.Public | BindingFlags.Instance); EmitMethodCall(node.Object, address, node); } }
private WriteBack AddressOfWriteBack(IndexExpression node) { if (node.Indexer == null || !node.Indexer.CanWrite) { return null; } // emit instance, if any LocalBuilder instanceLocal = null; Type instanceType = null; if (node.Object != null) { EmitInstance(node.Object, instanceType = node.Object.Type); // store in local _ilg.Emit(OpCodes.Dup); _ilg.Emit(OpCodes.Stloc, instanceLocal = GetInstanceLocal(instanceType)); } // Emit indexes. We don't allow byref args, so no need to worry // about write-backs or EmitAddress var n = node.ArgumentCount; List<LocalBuilder> args = new List<LocalBuilder>(n); for (var i = 0; i < n; i++) { var arg = node.GetArgument(i); EmitExpression(arg); var argLocal = GetLocal(arg.Type); _ilg.Emit(OpCodes.Dup); _ilg.Emit(OpCodes.Stloc, argLocal); args.Add(argLocal); } // emit the get EmitGetIndexCall(node, instanceType); // emit the address of the value var valueLocal = GetLocal(node.Type); _ilg.Emit(OpCodes.Stloc, valueLocal); _ilg.Emit(OpCodes.Ldloca, valueLocal); // Set the property after the method call // don't re-evaluate anything return delegate () { if (instanceLocal != null) { _ilg.Emit(OpCodes.Ldloc, instanceLocal); FreeLocal(instanceLocal); } foreach (var arg in args) { _ilg.Emit(OpCodes.Ldloc, arg); FreeLocal(arg); } _ilg.Emit(OpCodes.Ldloc, valueLocal); FreeLocal(valueLocal); EmitSetIndexCall(node, instanceType); }; }
private WriteBack AddressOfWriteBack(IndexExpression node) { if (node.Indexer == null || !node.Indexer.CanWrite) { return(null); } // emit instance, if any LocalBuilder instanceLocal = null; Type instanceType = null; if (node.Object != null) { EmitInstance(node.Object, instanceType = node.Object.Type); _ilg.Emit(OpCodes.Dup); _ilg.Emit(OpCodes.Stloc, instanceLocal = GetLocal(instanceType)); } // Emit indexes. We don't allow byref args, so no need to worry // about write-backs or EmitAddress var n = node.ArgumentCount; List <LocalBuilder> args = new List <LocalBuilder>(n); for (var i = 0; i < n; i++) { var arg = node.GetArgument(i); EmitExpression(arg); var argLocal = GetLocal(arg.Type); _ilg.Emit(OpCodes.Dup); _ilg.Emit(OpCodes.Stloc, argLocal); args.Add(argLocal); } // emit the get EmitGetIndexCall(node, instanceType); // emit the address of the value var valueLocal = GetLocal(node.Type); _ilg.Emit(OpCodes.Stloc, valueLocal); _ilg.Emit(OpCodes.Ldloca, valueLocal); // Set the property after the method call // don't re-evaluate anything return(delegate() { if (instanceLocal != null) { _ilg.Emit(OpCodes.Ldloc, instanceLocal); FreeLocal(instanceLocal); } foreach (var arg in args) { _ilg.Emit(OpCodes.Ldloc, arg); FreeLocal(arg); } _ilg.Emit(OpCodes.Ldloc, valueLocal); FreeLocal(valueLocal); EmitSetIndexCall(node, instanceType); }); }