1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Reflection; 6 using System.Reflection.Emit; 7 using System.Runtime.CompilerServices; 8 9 namespace System.Linq.Expressions.Compiler 10 { 11 internal sealed partial class CompilerScope 12 { 13 private abstract class Storage 14 { 15 internal readonly LambdaCompiler Compiler; 16 internal readonly ParameterExpression Variable; 17 Storage(LambdaCompiler compiler, ParameterExpression variable)18 internal Storage(LambdaCompiler compiler, ParameterExpression variable) 19 { 20 Compiler = compiler; 21 Variable = variable; 22 } 23 EmitLoad()24 internal abstract void EmitLoad(); EmitAddress()25 internal abstract void EmitAddress(); EmitStore()26 internal abstract void EmitStore(); 27 EmitStore(Storage value)28 internal virtual void EmitStore(Storage value) 29 { 30 value.EmitLoad(); 31 EmitStore(); 32 } 33 FreeLocal()34 internal virtual void FreeLocal() 35 { 36 } 37 } 38 39 private sealed class LocalStorage : Storage 40 { 41 private readonly LocalBuilder _local; 42 LocalStorage(LambdaCompiler compiler, ParameterExpression variable)43 internal LocalStorage(LambdaCompiler compiler, ParameterExpression variable) 44 : base(compiler, variable) 45 { 46 // ByRef variables are supported. This is used internally by 47 // the compiler when emitting an inlined lambda invoke, to 48 // handle ByRef parameters. BlockExpression prevents this 49 // from being exposed to user created trees. 50 51 // Set name if DebugInfoGenerator support is brought back. 52 _local = compiler.GetLocal(variable.IsByRef ? variable.Type.MakeByRefType() : variable.Type); 53 } 54 EmitLoad()55 internal override void EmitLoad() 56 { 57 Compiler.IL.Emit(OpCodes.Ldloc, _local); 58 } 59 EmitStore()60 internal override void EmitStore() 61 { 62 Compiler.IL.Emit(OpCodes.Stloc, _local); 63 } 64 EmitAddress()65 internal override void EmitAddress() 66 { 67 Compiler.IL.Emit(OpCodes.Ldloca, _local); 68 } 69 FreeLocal()70 internal override void FreeLocal() 71 { 72 Compiler.FreeLocal(_local); 73 } 74 } 75 76 private sealed class ArgumentStorage : Storage 77 { 78 private readonly int _argument; 79 ArgumentStorage(LambdaCompiler compiler, ParameterExpression p)80 internal ArgumentStorage(LambdaCompiler compiler, ParameterExpression p) 81 : base(compiler, p) 82 { 83 _argument = compiler.GetLambdaArgument(compiler.Parameters.IndexOf(p)); 84 } 85 EmitLoad()86 internal override void EmitLoad() 87 { 88 Compiler.IL.EmitLoadArg(_argument); 89 } 90 EmitStore()91 internal override void EmitStore() 92 { 93 Compiler.IL.EmitStoreArg(_argument); 94 } 95 EmitAddress()96 internal override void EmitAddress() 97 { 98 Compiler.IL.EmitLoadArgAddress(_argument); 99 } 100 } 101 102 private sealed class ElementBoxStorage : Storage 103 { 104 private readonly int _index; 105 private readonly Storage _array; 106 private readonly Type _boxType; 107 private readonly FieldInfo _boxValueField; 108 ElementBoxStorage(Storage array, int index, ParameterExpression variable)109 internal ElementBoxStorage(Storage array, int index, ParameterExpression variable) 110 : base(array.Compiler, variable) 111 { 112 _array = array; 113 _index = index; 114 _boxType = typeof(StrongBox<>).MakeGenericType(variable.Type); 115 _boxValueField = _boxType.GetField("Value"); 116 } 117 EmitLoad()118 internal override void EmitLoad() 119 { 120 EmitLoadBox(); 121 Compiler.IL.Emit(OpCodes.Ldfld, _boxValueField); 122 } 123 EmitStore()124 internal override void EmitStore() 125 { 126 LocalBuilder value = Compiler.GetLocal(Variable.Type); 127 Compiler.IL.Emit(OpCodes.Stloc, value); 128 EmitLoadBox(); 129 Compiler.IL.Emit(OpCodes.Ldloc, value); 130 Compiler.FreeLocal(value); 131 Compiler.IL.Emit(OpCodes.Stfld, _boxValueField); 132 } 133 EmitStore(Storage value)134 internal override void EmitStore(Storage value) 135 { 136 EmitLoadBox(); 137 value.EmitLoad(); 138 Compiler.IL.Emit(OpCodes.Stfld, _boxValueField); 139 } 140 EmitAddress()141 internal override void EmitAddress() 142 { 143 EmitLoadBox(); 144 Compiler.IL.Emit(OpCodes.Ldflda, _boxValueField); 145 } 146 EmitLoadBox()147 internal void EmitLoadBox() 148 { 149 _array.EmitLoad(); 150 Compiler.IL.EmitPrimitive(_index); 151 Compiler.IL.Emit(OpCodes.Ldelem_Ref); 152 Compiler.IL.Emit(OpCodes.Castclass, _boxType); 153 } 154 } 155 156 private sealed class LocalBoxStorage : Storage 157 { 158 private readonly LocalBuilder _boxLocal; 159 private readonly FieldInfo _boxValueField; 160 LocalBoxStorage(LambdaCompiler compiler, ParameterExpression variable)161 internal LocalBoxStorage(LambdaCompiler compiler, ParameterExpression variable) 162 : base(compiler, variable) 163 { 164 Type boxType = typeof(StrongBox<>).MakeGenericType(variable.Type); 165 _boxValueField = boxType.GetField("Value"); 166 167 // Set name if DebugInfoGenerator support is brought back. 168 _boxLocal = compiler.GetLocal(boxType); 169 } 170 EmitLoad()171 internal override void EmitLoad() 172 { 173 Compiler.IL.Emit(OpCodes.Ldloc, _boxLocal); 174 Compiler.IL.Emit(OpCodes.Ldfld, _boxValueField); 175 } 176 EmitAddress()177 internal override void EmitAddress() 178 { 179 Compiler.IL.Emit(OpCodes.Ldloc, _boxLocal); 180 Compiler.IL.Emit(OpCodes.Ldflda, _boxValueField); 181 } 182 EmitStore()183 internal override void EmitStore() 184 { 185 LocalBuilder value = Compiler.GetLocal(Variable.Type); 186 Compiler.IL.Emit(OpCodes.Stloc, value); 187 Compiler.IL.Emit(OpCodes.Ldloc, _boxLocal); 188 Compiler.IL.Emit(OpCodes.Ldloc, value); 189 Compiler.FreeLocal(value); 190 Compiler.IL.Emit(OpCodes.Stfld, _boxValueField); 191 } 192 EmitStore(Storage value)193 internal override void EmitStore(Storage value) 194 { 195 Compiler.IL.Emit(OpCodes.Ldloc, _boxLocal); 196 value.EmitLoad(); 197 Compiler.IL.Emit(OpCodes.Stfld, _boxValueField); 198 } 199 EmitStoreBox()200 internal void EmitStoreBox() 201 { 202 Compiler.IL.Emit(OpCodes.Stloc, _boxLocal); 203 } 204 FreeLocal()205 internal override void FreeLocal() 206 { 207 Compiler.FreeLocal(_boxLocal); 208 } 209 } 210 } 211 } 212