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; 6 using System.Collections.Generic; 7 using System.Diagnostics; 8 using System.Diagnostics.CodeAnalysis; 9 using System.Linq.Expressions; 10 using System.Reflection; 11 using Microsoft.CSharp.RuntimeBinder.Semantics; 12 13 namespace Microsoft.CSharp.RuntimeBinder 14 { 15 internal sealed class ExpressionTreeCallRewriter : ExprVisitorBase 16 { 17 ///////////////////////////////////////////////////////////////////////////////// 18 // Members 19 20 private sealed class ExpressionExpr : Expr 21 { 22 public readonly Expression Expression; ExpressionExpr(Expression e)23 public ExpressionExpr(Expression e) 24 : base(0) 25 { 26 Expression = e; 27 } 28 } 29 30 private readonly Dictionary<ExprCall, Expression> _DictionaryOfParameters; 31 private readonly Expression[] _ListOfParameters; 32 private readonly TypeManager _typeManager; 33 // Counts how many EXPRSAVEs we've encountered so we know which index into the 34 // parameter list we should be taking. 35 private int _currentParameterIndex; 36 37 ///////////////////////////////////////////////////////////////////////////////// 38 ExpressionTreeCallRewriter(TypeManager typeManager, Expression[] listOfParameters)39 private ExpressionTreeCallRewriter(TypeManager typeManager, Expression[] listOfParameters) 40 { 41 _typeManager = typeManager; 42 _DictionaryOfParameters = new Dictionary<ExprCall, Expression>(); 43 _ListOfParameters = listOfParameters; 44 } 45 46 ///////////////////////////////////////////////////////////////////////////////// 47 Rewrite(TypeManager typeManager, ExprBinOp binOp, Expression[] listOfParameters)48 public static Expression Rewrite(TypeManager typeManager, ExprBinOp binOp, Expression[] listOfParameters) 49 { 50 ExpressionTreeCallRewriter rewriter = new ExpressionTreeCallRewriter(typeManager, listOfParameters); 51 52 // We should have a ExprBinOp that's an EK_SEQUENCE. The RHS of our sequence 53 // should be a call to PM_EXPRESSION_LAMBDA. The LHS of our sequence is the 54 // set of declarations for the parameters that we'll need. 55 // Assert all of these first, and then unwrap them. 56 57 Debug.Assert(binOp != null); 58 Debug.Assert(binOp.Kind == ExpressionKind.Sequence); 59 Debug.Assert(binOp.OptionalRightChild is ExprCall); 60 Debug.Assert(((ExprCall)binOp.OptionalRightChild).PredefinedMethod == PREDEFMETH.PM_EXPRESSION_LAMBDA); 61 Debug.Assert(binOp.OptionalLeftChild != null); 62 63 // Visit the left to generate the parameter construction. 64 rewriter.Visit(binOp.OptionalLeftChild); 65 ExprCall call = (ExprCall)binOp.OptionalRightChild; 66 67 ExpressionExpr e = rewriter.Visit(call) as ExpressionExpr; 68 return e.Expression; 69 } 70 71 ///////////////////////////////////////////////////////////////////////////////// 72 VisitSAVE(ExprBinOp pExpr)73 protected override Expr VisitSAVE(ExprBinOp pExpr) 74 { 75 // Saves should have a LHS that is a CALL to PM_EXPRESSION_PARAMETER 76 // and a RHS that is a WRAP of that call. 77 ExprCall call = (ExprCall)pExpr.OptionalLeftChild; 78 Debug.Assert(call?.PredefinedMethod == PREDEFMETH.PM_EXPRESSION_PARAMETER); 79 Debug.Assert(pExpr.OptionalRightChild is ExprWrap); 80 81 Expression parameter = _ListOfParameters[_currentParameterIndex++]; 82 _DictionaryOfParameters.Add(call, parameter); 83 84 return null; 85 } 86 87 ///////////////////////////////////////////////////////////////////////////////// 88 VisitCALL(ExprCall pExpr)89 protected override Expr VisitCALL(ExprCall pExpr) 90 { 91 if (pExpr.PredefinedMethod == PREDEFMETH.PM_COUNT) 92 { 93 return pExpr; 94 } 95 96 Expression exp; 97 switch (pExpr.PredefinedMethod) 98 { 99 case PREDEFMETH.PM_EXPRESSION_LAMBDA: 100 return GenerateLambda(pExpr); 101 102 case PREDEFMETH.PM_EXPRESSION_CALL: 103 exp = GenerateCall(pExpr); 104 break; 105 106 case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX: 107 case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2: 108 exp = GenerateArrayIndex(pExpr); 109 break; 110 111 case PREDEFMETH.PM_EXPRESSION_CONVERT: 112 case PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED: 113 case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED: 114 case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED: 115 exp = GenerateConvert(pExpr); 116 break; 117 118 case PREDEFMETH.PM_EXPRESSION_PROPERTY: 119 exp = GenerateProperty(pExpr); 120 break; 121 122 case PREDEFMETH.PM_EXPRESSION_FIELD: 123 exp = GenerateField(pExpr); 124 break; 125 126 case PREDEFMETH.PM_EXPRESSION_INVOKE: 127 exp = GenerateInvoke(pExpr); 128 break; 129 130 case PREDEFMETH.PM_EXPRESSION_NEW: 131 exp = GenerateNew(pExpr); 132 break; 133 134 case PREDEFMETH.PM_EXPRESSION_ADD: 135 case PREDEFMETH.PM_EXPRESSION_AND: 136 case PREDEFMETH.PM_EXPRESSION_DIVIDE: 137 case PREDEFMETH.PM_EXPRESSION_EQUAL: 138 case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR: 139 case PREDEFMETH.PM_EXPRESSION_GREATERTHAN: 140 case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL: 141 case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT: 142 case PREDEFMETH.PM_EXPRESSION_LESSTHAN: 143 case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL: 144 case PREDEFMETH.PM_EXPRESSION_MODULO: 145 case PREDEFMETH.PM_EXPRESSION_MULTIPLY: 146 case PREDEFMETH.PM_EXPRESSION_NOTEQUAL: 147 case PREDEFMETH.PM_EXPRESSION_OR: 148 case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT: 149 case PREDEFMETH.PM_EXPRESSION_SUBTRACT: 150 case PREDEFMETH.PM_EXPRESSION_ORELSE: 151 case PREDEFMETH.PM_EXPRESSION_ANDALSO: 152 // Checked 153 case PREDEFMETH.PM_EXPRESSION_ADDCHECKED: 154 case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED: 155 case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED: 156 exp = GenerateBinaryOperator(pExpr); 157 break; 158 159 case PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED: 160 case PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED: 161 case PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED: 162 case PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED: 163 case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED: 164 case PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED: 165 case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED: 166 case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED: 167 case PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED: 168 case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED: 169 case PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED: 170 case PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED: 171 case PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED: 172 case PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED: 173 case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED: 174 case PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED: 175 case PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED: 176 case PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED: 177 // Checked 178 case PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED: 179 case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED: 180 case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED: 181 exp = GenerateUserDefinedBinaryOperator(pExpr); 182 break; 183 184 case PREDEFMETH.PM_EXPRESSION_NEGATE: 185 case PREDEFMETH.PM_EXPRESSION_NOT: 186 case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED: 187 exp = GenerateUnaryOperator(pExpr); 188 break; 189 190 case PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED: 191 case PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED: 192 case PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED: 193 case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED: 194 exp = GenerateUserDefinedUnaryOperator(pExpr); 195 break; 196 197 case PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE: 198 exp = GenerateConstantType(pExpr); 199 break; 200 201 case PREDEFMETH.PM_EXPRESSION_ASSIGN: 202 exp = GenerateAssignment(pExpr); 203 break; 204 205 default: 206 Debug.Assert(false, "Invalid Predefined Method in VisitCALL"); 207 throw Error.InternalCompilerError(); 208 } 209 210 return new ExpressionExpr(exp); 211 } 212 213 // ExpressionTreeRewriter has optimized away identity or up-cast conversions, leaving us with a bare parameter 214 // access. Just get the expression for that parameter so the lambda produced can be p0 => p0 215 protected override Expr VisitWRAP(ExprWrap pExpr) => new ExpressionExpr(GetExpression(pExpr)); 216 217 #region Generators 218 ///////////////////////////////////////////////////////////////////////////////// 219 GenerateLambda(ExprCall pExpr)220 private Expr GenerateLambda(ExprCall pExpr) 221 { 222 // We always call Lambda(body, arrayinit) where the arrayinit 223 // is the initialization of the parameters. 224 return Visit(((ExprList)pExpr.OptionalArguments).OptionalElement); 225 226 /* 227 * // Do we need to do this? 228 Expression e = (body as ExpressionExpr).Expression; 229 if (e.Type.IsValueType) 230 { 231 // If we have a value type, convert it to object so that boxing 232 // can happen. 233 234 e = Expression.Convert(body.Expression, typeof(object)); 235 } 236 * */ 237 } 238 239 ///////////////////////////////////////////////////////////////////////////////// 240 GenerateCall(ExprCall pExpr)241 private Expression GenerateCall(ExprCall pExpr) 242 { 243 // Our arguments are: object, methodinfo, parameters. 244 // The object is either an EXPRWRAP of a CALL, or a CALL that is a PM_CONVERT, whose 245 // argument is the WRAP of a CALL. Deal with that first. 246 247 ExprMethodInfo methinfo; 248 ExprArrayInit arrinit; 249 250 ExprList list = (ExprList)pExpr.OptionalArguments; 251 if (list.OptionalNextListNode is ExprList next) 252 { 253 methinfo = (ExprMethodInfo)next.OptionalElement; 254 arrinit = (ExprArrayInit)next.OptionalNextListNode; 255 } 256 else 257 { 258 methinfo = (ExprMethodInfo)list.OptionalNextListNode; 259 arrinit = null; 260 } 261 262 Expression obj = null; 263 MethodInfo m = GetMethodInfoFromExpr(methinfo); 264 Expression[] arguments = GetArgumentsFromArrayInit(arrinit); 265 266 if (m == null) 267 { 268 Debug.Assert(false, "How did we get a call that doesn't have a methodinfo?"); 269 throw Error.InternalCompilerError(); 270 } 271 272 // The DLR is expecting the instance for a static invocation to be null. If we have 273 // an instance method, fetch the object. 274 if (!m.IsStatic) 275 { 276 obj = GetExpression(((ExprList)pExpr.OptionalArguments).OptionalElement); 277 } 278 279 return Expression.Call(obj, m, arguments); 280 } 281 282 ///////////////////////////////////////////////////////////////////////////////// 283 GenerateArrayIndex(ExprCall pExpr)284 private Expression GenerateArrayIndex(ExprCall pExpr) 285 { 286 // We have two possibilities here - we're either a single index array, in which 287 // case we'll be PM_EXPRESSION_ARRAYINDEX, or we have multiple dimensions, 288 // in which case we are PM_EXPRESSION_ARRAYINDEX2. 289 // 290 // Our arguments then, are: object, index or object, indices. 291 ExprList list = (ExprList)pExpr.OptionalArguments; 292 Debug.Assert(list != null); 293 Expression obj = GetExpression(list.OptionalElement); 294 Expression[] indices; 295 296 if (pExpr.PredefinedMethod == PREDEFMETH.PM_EXPRESSION_ARRAYINDEX) 297 { 298 indices = new[] { GetExpression(list.OptionalNextListNode) }; 299 } 300 else 301 { 302 Debug.Assert(pExpr.PredefinedMethod == PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2); 303 indices = GetArgumentsFromArrayInit((ExprArrayInit)list.OptionalNextListNode); 304 } 305 return Expression.ArrayAccess(obj, indices); 306 } 307 308 ///////////////////////////////////////////////////////////////////////////////// 309 GenerateConvert(ExprCall pExpr)310 private Expression GenerateConvert(ExprCall pExpr) 311 { 312 PREDEFMETH pm = pExpr.PredefinedMethod; 313 Expression e; 314 Type t; 315 316 if (pm == PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED || 317 pm == PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED) 318 { 319 // If we have a user defined conversion, then we'll have the object 320 // as the first element, and another list as a second element. This list 321 // contains a TYPEOF as the first element, and the METHODINFO for the call 322 // as the second. 323 324 ExprList list = (ExprList)pExpr.OptionalArguments; 325 ExprList list2 = (ExprList)list.OptionalNextListNode; 326 e = GetExpression(list.OptionalElement); 327 t = ((ExprTypeOf)list2.OptionalElement).SourceType.AssociatedSystemType; 328 329 if (e.Type.MakeByRefType() == t) 330 { 331 // We're trying to convert from a type to its by ref type. Don't do that. 332 return e; 333 } 334 Debug.Assert((pExpr.Flags & EXPRFLAG.EXF_UNBOXRUNTIME) == 0); 335 336 MethodInfo m = GetMethodInfoFromExpr((ExprMethodInfo)list2.OptionalNextListNode); 337 338 if (pm == PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED) 339 { 340 return Expression.Convert(e, t, m); 341 } 342 return Expression.ConvertChecked(e, t, m); 343 } 344 else 345 { 346 Debug.Assert(pm == PREDEFMETH.PM_EXPRESSION_CONVERT || 347 pm == PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED); 348 349 // If we have a standard conversion, then we'll have some object as 350 // the first list element (ie a WRAP or a CALL), and then a TYPEOF 351 // as the second list element. 352 ExprList list = (ExprList)pExpr.OptionalArguments; 353 354 e = GetExpression(list.OptionalElement); 355 t = ((ExprTypeOf)list.OptionalNextListNode).SourceType.AssociatedSystemType; 356 357 if (e.Type.MakeByRefType() == t) 358 { 359 // We're trying to convert from a type to its by ref type. Don't do that. 360 return e; 361 } 362 363 if ((pExpr.Flags & EXPRFLAG.EXF_UNBOXRUNTIME) != 0) 364 { 365 // If we want to unbox this thing, return that instead of the convert. 366 return Expression.Unbox(e, t); 367 } 368 369 if (pm == PREDEFMETH.PM_EXPRESSION_CONVERT) 370 { 371 return Expression.Convert(e, t); 372 } 373 return Expression.ConvertChecked(e, t); 374 } 375 } 376 377 ///////////////////////////////////////////////////////////////////////////////// 378 GenerateProperty(ExprCall pExpr)379 private Expression GenerateProperty(ExprCall pExpr) 380 { 381 ExprList list = (ExprList)pExpr.OptionalArguments; 382 383 Expr instance = list.OptionalElement; 384 Expr nextNode = list.OptionalNextListNode; 385 ExprPropertyInfo propinfo; 386 ExprArrayInit arguments; 387 if (nextNode is ExprList nextList) 388 { 389 propinfo = nextList.OptionalElement as ExprPropertyInfo; 390 arguments = nextList.OptionalNextListNode as ExprArrayInit; 391 } 392 else 393 { 394 propinfo = nextNode as ExprPropertyInfo; 395 arguments = null; 396 } 397 398 PropertyInfo p = GetPropertyInfoFromExpr(propinfo); 399 400 if (p == null) 401 { 402 Debug.Assert(false, "How did we get a prop that doesn't have a propinfo?"); 403 throw Error.InternalCompilerError(); 404 } 405 406 if (arguments == null) 407 { 408 return Expression.Property(GetExpression(instance), p); 409 } 410 411 return Expression.Property(GetExpression(instance), p, GetArgumentsFromArrayInit(arguments)); 412 } 413 414 ///////////////////////////////////////////////////////////////////////////////// 415 GenerateField(ExprCall pExpr)416 private Expression GenerateField(ExprCall pExpr) 417 { 418 ExprList list = (ExprList)pExpr.OptionalArguments; 419 ExprFieldInfo fieldInfo = (ExprFieldInfo)list.OptionalNextListNode; 420 Debug.Assert(fieldInfo != null); 421 Type t = fieldInfo.FieldType.AssociatedSystemType; 422 FieldInfo f = fieldInfo.Field.AssociatedFieldInfo; 423 424 // This is to ensure that for embedded nopia types, we have the 425 // appropriate local type from the member itself; this is possible 426 // because nopia types are not generic or nested. 427 if (!t.IsGenericType && !t.IsNested) 428 { 429 t = f.DeclaringType; 430 } 431 432 // Now find the generic'ed one if we're generic. 433 if (t.IsGenericType) 434 { 435 f = t.GetField(f.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); 436 } 437 438 return Expression.Field(GetExpression(list.OptionalElement), f); 439 } 440 441 ///////////////////////////////////////////////////////////////////////////////// 442 GenerateInvoke(ExprCall pExpr)443 private Expression GenerateInvoke(ExprCall pExpr) 444 { 445 ExprList list = (ExprList)pExpr.OptionalArguments; 446 447 return Expression.Invoke( 448 GetExpression(list.OptionalElement), 449 GetArgumentsFromArrayInit(list.OptionalNextListNode as ExprArrayInit)); 450 } 451 452 ///////////////////////////////////////////////////////////////////////////////// 453 GenerateNew(ExprCall pExpr)454 private Expression GenerateNew(ExprCall pExpr) 455 { 456 ExprList list = (ExprList)pExpr.OptionalArguments; 457 458 var constructor = GetConstructorInfoFromExpr(list.OptionalElement as ExprMethodInfo); 459 var arguments = GetArgumentsFromArrayInit(list.OptionalNextListNode as ExprArrayInit); 460 return Expression.New(constructor, arguments); 461 } 462 463 ///////////////////////////////////////////////////////////////////////////////// 464 GenerateConstantType(ExprCall pExpr)465 private Expression GenerateConstantType(ExprCall pExpr) 466 { 467 ExprList list = (ExprList)pExpr.OptionalArguments; 468 469 return Expression.Constant( 470 GetObject(list.OptionalElement), 471 ((ExprTypeOf)list.OptionalNextListNode).SourceType.AssociatedSystemType); 472 } 473 474 ///////////////////////////////////////////////////////////////////////////////// 475 GenerateAssignment(ExprCall pExpr)476 private Expression GenerateAssignment(ExprCall pExpr) 477 { 478 ExprList list = (ExprList)pExpr.OptionalArguments; 479 480 return Expression.Assign( 481 GetExpression(list.OptionalElement), 482 GetExpression(list.OptionalNextListNode)); 483 } 484 485 ///////////////////////////////////////////////////////////////////////////////// 486 GenerateBinaryOperator(ExprCall pExpr)487 private Expression GenerateBinaryOperator(ExprCall pExpr) 488 { 489 ExprList list = (ExprList)pExpr.OptionalArguments; 490 Debug.Assert(list != null); 491 Expression arg1 = GetExpression(list.OptionalElement); 492 Expression arg2 = GetExpression(list.OptionalNextListNode); 493 494 switch (pExpr.PredefinedMethod) 495 { 496 case PREDEFMETH.PM_EXPRESSION_ADD: 497 return Expression.Add(arg1, arg2); 498 case PREDEFMETH.PM_EXPRESSION_AND: 499 return Expression.And(arg1, arg2); 500 case PREDEFMETH.PM_EXPRESSION_DIVIDE: 501 return Expression.Divide(arg1, arg2); 502 case PREDEFMETH.PM_EXPRESSION_EQUAL: 503 return Expression.Equal(arg1, arg2); 504 case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR: 505 return Expression.ExclusiveOr(arg1, arg2); 506 case PREDEFMETH.PM_EXPRESSION_GREATERTHAN: 507 return Expression.GreaterThan(arg1, arg2); 508 case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL: 509 return Expression.GreaterThanOrEqual(arg1, arg2); 510 case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT: 511 return Expression.LeftShift(arg1, arg2); 512 case PREDEFMETH.PM_EXPRESSION_LESSTHAN: 513 return Expression.LessThan(arg1, arg2); 514 case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL: 515 return Expression.LessThanOrEqual(arg1, arg2); 516 case PREDEFMETH.PM_EXPRESSION_MODULO: 517 return Expression.Modulo(arg1, arg2); 518 case PREDEFMETH.PM_EXPRESSION_MULTIPLY: 519 return Expression.Multiply(arg1, arg2); 520 case PREDEFMETH.PM_EXPRESSION_NOTEQUAL: 521 return Expression.NotEqual(arg1, arg2); 522 case PREDEFMETH.PM_EXPRESSION_OR: 523 return Expression.Or(arg1, arg2); 524 case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT: 525 return Expression.RightShift(arg1, arg2); 526 case PREDEFMETH.PM_EXPRESSION_SUBTRACT: 527 return Expression.Subtract(arg1, arg2); 528 case PREDEFMETH.PM_EXPRESSION_ORELSE: 529 return Expression.OrElse(arg1, arg2); 530 case PREDEFMETH.PM_EXPRESSION_ANDALSO: 531 return Expression.AndAlso(arg1, arg2); 532 533 // Checked 534 case PREDEFMETH.PM_EXPRESSION_ADDCHECKED: 535 return Expression.AddChecked(arg1, arg2); 536 case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED: 537 return Expression.MultiplyChecked(arg1, arg2); 538 case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED: 539 return Expression.SubtractChecked(arg1, arg2); 540 541 default: 542 Debug.Assert(false, "Invalid Predefined Method in GenerateBinaryOperator"); 543 throw Error.InternalCompilerError(); 544 } 545 } 546 547 ///////////////////////////////////////////////////////////////////////////////// 548 GenerateUserDefinedBinaryOperator(ExprCall pExpr)549 private Expression GenerateUserDefinedBinaryOperator(ExprCall pExpr) 550 { 551 ExprList list = (ExprList)pExpr.OptionalArguments; 552 Expression arg1 = GetExpression(list.OptionalElement); 553 Expression arg2 = GetExpression(((ExprList)list.OptionalNextListNode).OptionalElement); 554 555 list = (ExprList)list.OptionalNextListNode; 556 MethodInfo methodInfo; 557 bool bIsLifted = false; 558 if (list.OptionalNextListNode is ExprList next) 559 { 560 ExprConstant isLifted = (ExprConstant)next.OptionalElement; 561 Debug.Assert(isLifted != null); 562 bIsLifted = isLifted.Val.Int32Val == 1; 563 methodInfo = GetMethodInfoFromExpr((ExprMethodInfo)next.OptionalNextListNode); 564 } 565 else 566 { 567 methodInfo = GetMethodInfoFromExpr((ExprMethodInfo)list.OptionalNextListNode); 568 } 569 570 switch (pExpr.PredefinedMethod) 571 { 572 case PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED: 573 return Expression.Add(arg1, arg2, methodInfo); 574 case PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED: 575 return Expression.And(arg1, arg2, methodInfo); 576 case PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED: 577 return Expression.Divide(arg1, arg2, methodInfo); 578 case PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED: 579 return Expression.Equal(arg1, arg2, bIsLifted, methodInfo); 580 case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED: 581 return Expression.ExclusiveOr(arg1, arg2, methodInfo); 582 case PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED: 583 return Expression.GreaterThan(arg1, arg2, bIsLifted, methodInfo); 584 case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED: 585 return Expression.GreaterThanOrEqual(arg1, arg2, bIsLifted, methodInfo); 586 case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED: 587 return Expression.LeftShift(arg1, arg2, methodInfo); 588 case PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED: 589 return Expression.LessThan(arg1, arg2, bIsLifted, methodInfo); 590 case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED: 591 return Expression.LessThanOrEqual(arg1, arg2, bIsLifted, methodInfo); 592 case PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED: 593 return Expression.Modulo(arg1, arg2, methodInfo); 594 case PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED: 595 return Expression.Multiply(arg1, arg2, methodInfo); 596 case PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED: 597 return Expression.NotEqual(arg1, arg2, bIsLifted, methodInfo); 598 case PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED: 599 return Expression.Or(arg1, arg2, methodInfo); 600 case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED: 601 return Expression.RightShift(arg1, arg2, methodInfo); 602 case PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED: 603 return Expression.Subtract(arg1, arg2, methodInfo); 604 case PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED: 605 return Expression.OrElse(arg1, arg2, methodInfo); 606 case PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED: 607 return Expression.AndAlso(arg1, arg2, methodInfo); 608 609 // Checked 610 case PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED: 611 return Expression.AddChecked(arg1, arg2, methodInfo); 612 case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED: 613 return Expression.MultiplyChecked(arg1, arg2, methodInfo); 614 case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED: 615 return Expression.SubtractChecked(arg1, arg2, methodInfo); 616 617 default: 618 Debug.Assert(false, "Invalid Predefined Method in GenerateUserDefinedBinaryOperator"); 619 throw Error.InternalCompilerError(); 620 } 621 } 622 623 ///////////////////////////////////////////////////////////////////////////////// 624 GenerateUnaryOperator(ExprCall pExpr)625 private Expression GenerateUnaryOperator(ExprCall pExpr) 626 { 627 PREDEFMETH pm = pExpr.PredefinedMethod; 628 Expression arg = GetExpression(pExpr.OptionalArguments); 629 630 switch (pm) 631 { 632 case PREDEFMETH.PM_EXPRESSION_NOT: 633 return Expression.Not(arg); 634 635 case PREDEFMETH.PM_EXPRESSION_NEGATE: 636 return Expression.Negate(arg); 637 638 case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED: 639 return Expression.NegateChecked(arg); 640 641 default: 642 Debug.Assert(false, "Invalid Predefined Method in GenerateUnaryOperator"); 643 throw Error.InternalCompilerError(); 644 } 645 } 646 647 ///////////////////////////////////////////////////////////////////////////////// 648 GenerateUserDefinedUnaryOperator(ExprCall pExpr)649 private Expression GenerateUserDefinedUnaryOperator(ExprCall pExpr) 650 { 651 PREDEFMETH pm = pExpr.PredefinedMethod; 652 ExprList list = (ExprList)pExpr.OptionalArguments; 653 Expression arg = GetExpression(list.OptionalElement); 654 MethodInfo methodInfo = GetMethodInfoFromExpr((ExprMethodInfo)list.OptionalNextListNode); 655 656 switch (pm) 657 { 658 case PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED: 659 return Expression.Not(arg, methodInfo); 660 661 case PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED: 662 return Expression.Negate(arg, methodInfo); 663 664 case PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED: 665 return Expression.UnaryPlus(arg, methodInfo); 666 667 case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED: 668 return Expression.NegateChecked(arg, methodInfo); 669 670 default: 671 Debug.Assert(false, "Invalid Predefined Method in GenerateUserDefinedUnaryOperator"); 672 throw Error.InternalCompilerError(); 673 } 674 } 675 #endregion 676 677 #region Helpers 678 ///////////////////////////////////////////////////////////////////////////////// 679 GetExpression(Expr pExpr)680 private Expression GetExpression(Expr pExpr) 681 { 682 if (pExpr is ExprWrap wrap) 683 { 684 return _DictionaryOfParameters[(ExprCall)wrap.OptionalExpression]; 685 } 686 else if (pExpr is ExprConstant) 687 { 688 Debug.Assert(pExpr.Type is NullType); 689 return null; 690 } 691 else 692 { 693 // We can have a convert node or a call of a user defined conversion. 694 ExprCall call = (ExprCall)pExpr; 695 Debug.Assert(call != null); 696 PREDEFMETH pm = call.PredefinedMethod; 697 Debug.Assert(pm == PREDEFMETH.PM_EXPRESSION_CONVERT || 698 pm == PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED || 699 pm == PREDEFMETH.PM_EXPRESSION_NEWARRAYINIT || 700 pm == PREDEFMETH.PM_EXPRESSION_CALL || 701 pm == PREDEFMETH.PM_EXPRESSION_PROPERTY || 702 pm == PREDEFMETH.PM_EXPRESSION_FIELD || 703 pm == PREDEFMETH.PM_EXPRESSION_ARRAYINDEX || 704 pm == PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2 || 705 pm == PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE || 706 pm == PREDEFMETH.PM_EXPRESSION_NEW || 707 708 // Binary operators. 709 pm == PREDEFMETH.PM_EXPRESSION_ASSIGN || 710 pm == PREDEFMETH.PM_EXPRESSION_ADD || 711 pm == PREDEFMETH.PM_EXPRESSION_AND || 712 pm == PREDEFMETH.PM_EXPRESSION_DIVIDE || 713 pm == PREDEFMETH.PM_EXPRESSION_EQUAL || 714 pm == PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR || 715 pm == PREDEFMETH.PM_EXPRESSION_GREATERTHAN || 716 pm == PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL || 717 pm == PREDEFMETH.PM_EXPRESSION_LEFTSHIFT || 718 pm == PREDEFMETH.PM_EXPRESSION_LESSTHAN || 719 pm == PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL || 720 pm == PREDEFMETH.PM_EXPRESSION_MODULO || 721 pm == PREDEFMETH.PM_EXPRESSION_MULTIPLY || 722 pm == PREDEFMETH.PM_EXPRESSION_NOTEQUAL || 723 pm == PREDEFMETH.PM_EXPRESSION_OR || 724 pm == PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT || 725 pm == PREDEFMETH.PM_EXPRESSION_SUBTRACT || 726 pm == PREDEFMETH.PM_EXPRESSION_ORELSE || 727 pm == PREDEFMETH.PM_EXPRESSION_ANDALSO || 728 pm == PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED || 729 pm == PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED || 730 pm == PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED || 731 pm == PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED || 732 pm == PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED || 733 pm == PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED || 734 pm == PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED || 735 pm == PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED || 736 pm == PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED || 737 pm == PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED || 738 pm == PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED || 739 pm == PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED || 740 pm == PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED || 741 pm == PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED || 742 pm == PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED || 743 pm == PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED || 744 pm == PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED || 745 pm == PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED || 746 747 // Checked binary 748 pm == PREDEFMETH.PM_EXPRESSION_ADDCHECKED || 749 pm == PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED || 750 pm == PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED || 751 pm == PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED || 752 pm == PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED || 753 pm == PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED || 754 755 // Unary operators. 756 pm == PREDEFMETH.PM_EXPRESSION_NOT || 757 pm == PREDEFMETH.PM_EXPRESSION_NEGATE || 758 pm == PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED || 759 pm == PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED || 760 pm == PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED || 761 762 // Checked unary 763 pm == PREDEFMETH.PM_EXPRESSION_NEGATECHECKED || 764 pm == PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED || 765 pm == PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED || 766 pm == PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED 767 ); 768 769 switch (pm) 770 { 771 case PREDEFMETH.PM_EXPRESSION_CALL: 772 return GenerateCall(call); 773 774 case PREDEFMETH.PM_EXPRESSION_CONVERT: 775 case PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED: 776 case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED: 777 case PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED: 778 return GenerateConvert(call); 779 780 case PREDEFMETH.PM_EXPRESSION_NEWARRAYINIT: 781 { 782 ExprList list = (ExprList)call.OptionalArguments; 783 return 784 Expression.NewArrayInit( 785 ((ExprTypeOf)list.OptionalElement).SourceType.AssociatedSystemType, 786 GetArgumentsFromArrayInit((ExprArrayInit)list.OptionalNextListNode)); 787 } 788 789 case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX: 790 case PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2: 791 return GenerateArrayIndex(call); 792 793 case PREDEFMETH.PM_EXPRESSION_NEW: 794 return GenerateNew(call); 795 796 case PREDEFMETH.PM_EXPRESSION_PROPERTY: 797 return GenerateProperty(call); 798 799 case PREDEFMETH.PM_EXPRESSION_FIELD: 800 return GenerateField(call); 801 802 case PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE: 803 return GenerateConstantType(call); 804 805 case PREDEFMETH.PM_EXPRESSION_ASSIGN: 806 return GenerateAssignment(call); 807 808 case PREDEFMETH.PM_EXPRESSION_ADD: 809 case PREDEFMETH.PM_EXPRESSION_AND: 810 case PREDEFMETH.PM_EXPRESSION_DIVIDE: 811 case PREDEFMETH.PM_EXPRESSION_EQUAL: 812 case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR: 813 case PREDEFMETH.PM_EXPRESSION_GREATERTHAN: 814 case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL: 815 case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT: 816 case PREDEFMETH.PM_EXPRESSION_LESSTHAN: 817 case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL: 818 case PREDEFMETH.PM_EXPRESSION_MODULO: 819 case PREDEFMETH.PM_EXPRESSION_MULTIPLY: 820 case PREDEFMETH.PM_EXPRESSION_NOTEQUAL: 821 case PREDEFMETH.PM_EXPRESSION_OR: 822 case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT: 823 case PREDEFMETH.PM_EXPRESSION_SUBTRACT: 824 case PREDEFMETH.PM_EXPRESSION_ORELSE: 825 case PREDEFMETH.PM_EXPRESSION_ANDALSO: 826 // Checked 827 case PREDEFMETH.PM_EXPRESSION_ADDCHECKED: 828 case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED: 829 case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED: 830 return GenerateBinaryOperator(call); 831 832 case PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED: 833 case PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED: 834 case PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED: 835 case PREDEFMETH.PM_EXPRESSION_EQUAL_USER_DEFINED: 836 case PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED: 837 case PREDEFMETH.PM_EXPRESSION_GREATERTHAN_USER_DEFINED: 838 case PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL_USER_DEFINED: 839 case PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED: 840 case PREDEFMETH.PM_EXPRESSION_LESSTHAN_USER_DEFINED: 841 case PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL_USER_DEFINED: 842 case PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED: 843 case PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED: 844 case PREDEFMETH.PM_EXPRESSION_NOTEQUAL_USER_DEFINED: 845 case PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED: 846 case PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED: 847 case PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED: 848 case PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED: 849 case PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED: 850 // Checked 851 case PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED: 852 case PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED: 853 case PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED: 854 return GenerateUserDefinedBinaryOperator(call); 855 856 case PREDEFMETH.PM_EXPRESSION_NOT: 857 case PREDEFMETH.PM_EXPRESSION_NEGATE: 858 case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED: 859 return GenerateUnaryOperator(call); 860 861 case PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED: 862 case PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED: 863 case PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED: 864 case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED: 865 return GenerateUserDefinedUnaryOperator(call); 866 867 default: 868 Debug.Assert(false, "Invalid Predefined Method in GetExpression"); 869 throw Error.InternalCompilerError(); 870 } 871 } 872 } 873 874 ///////////////////////////////////////////////////////////////////////////////// 875 GetObject(Expr pExpr)876 private object GetObject(Expr pExpr) 877 { 878 for (;;) 879 { 880 if (pExpr is ExprCast cast) 881 { 882 pExpr = cast.Argument; 883 } 884 else if (pExpr is ExprTypeOf typeOf) 885 { 886 return typeOf.SourceType.AssociatedSystemType; 887 } 888 else if (pExpr is ExprMethodInfo methodInfo) 889 { 890 return GetMethodInfoFromExpr(methodInfo); 891 } 892 else if (pExpr is ExprConstant constant) 893 { 894 ConstVal val = constant.Val; 895 CType underlyingType = pExpr.Type; 896 object objval; 897 898 if (pExpr.Type is NullType) 899 { 900 return null; 901 } 902 903 if (pExpr.Type.isEnumType()) 904 { 905 underlyingType = underlyingType.getAggregate().GetUnderlyingType(); 906 } 907 908 switch (Type.GetTypeCode(underlyingType.AssociatedSystemType)) 909 { 910 case TypeCode.Boolean: 911 objval = val.BooleanVal; 912 break; 913 case TypeCode.SByte: 914 objval = val.SByteVal; 915 break; 916 case TypeCode.Byte: 917 objval = val.ByteVal; 918 break; 919 case TypeCode.Int16: 920 objval = val.Int16Val; 921 break; 922 case TypeCode.UInt16: 923 objval = val.UInt16Val; 924 break; 925 case TypeCode.Int32: 926 objval = val.Int32Val; 927 break; 928 case TypeCode.UInt32: 929 objval = val.UInt32Val; 930 break; 931 case TypeCode.Int64: 932 objval = val.Int64Val; 933 break; 934 case TypeCode.UInt64: 935 objval = val.UInt64Val; 936 break; 937 case TypeCode.Single: 938 objval = val.SingleVal; 939 break; 940 case TypeCode.Double: 941 objval = val.DoubleVal; 942 break; 943 case TypeCode.Decimal: 944 objval = val.DecimalVal; 945 break; 946 case TypeCode.Char: 947 objval = val.CharVal; 948 break; 949 case TypeCode.String: 950 objval = val.StringVal; 951 break; 952 default: 953 objval = val.ObjectVal; 954 break; 955 } 956 957 return pExpr.Type.isEnumType() ? Enum.ToObject(pExpr.Type.AssociatedSystemType, objval) : objval; 958 } 959 else if (pExpr is ExprZeroInit zeroInit) 960 { 961 return Activator.CreateInstance(zeroInit.Type.AssociatedSystemType); 962 } 963 else 964 { 965 Debug.Assert(false, "Invalid Expr in GetObject"); 966 throw Error.InternalCompilerError(); 967 } 968 } 969 } 970 971 ///////////////////////////////////////////////////////////////////////////////// 972 GetArgumentsFromArrayInit(ExprArrayInit arrinit)973 private Expression[] GetArgumentsFromArrayInit(ExprArrayInit arrinit) 974 { 975 List<Expression> expressions = new List<Expression>(); 976 977 if (arrinit != null) 978 { 979 Expr list = arrinit.OptionalArguments; 980 while (list != null) 981 { 982 Expr p; 983 if (list is ExprList pList) 984 { 985 p = pList.OptionalElement; 986 list = pList.OptionalNextListNode; 987 } 988 else 989 { 990 p = list; 991 list = null; 992 } 993 994 expressions.Add(GetExpression(p)); 995 } 996 997 Debug.Assert(expressions.Count == arrinit.DimensionSizes[0]); 998 } 999 1000 return expressions.ToArray(); 1001 } 1002 1003 ///////////////////////////////////////////////////////////////////////////////// 1004 GetMethodInfoFromExpr(ExprMethodInfo methinfo)1005 private MethodInfo GetMethodInfoFromExpr(ExprMethodInfo methinfo) 1006 { 1007 // To do this, we need to construct a type array of the parameter types, 1008 // get the parent constructed type, and get the method from it. 1009 1010 AggregateType aggType = methinfo.Method.Ats; 1011 MethodSymbol methSym = methinfo.Method.Meth(); 1012 1013 TypeArray genericParams = _typeManager.SubstTypeArray(methSym.Params, aggType, methSym.typeVars); 1014 CType genericReturn = _typeManager.SubstType(methSym.RetType, aggType, methSym.typeVars); 1015 1016 Type type = aggType.AssociatedSystemType; 1017 MethodInfo methodInfo = methSym.AssociatedMemberInfo as MethodInfo; 1018 1019 // This is to ensure that for embedded nopia types, we have the 1020 // appropriate local type from the member itself; this is possible 1021 // because nopia types are not generic or nested. 1022 if (!type.IsGenericType && !type.IsNested) 1023 { 1024 type = methodInfo.DeclaringType; 1025 } 1026 1027 // We need to find the associated methodinfo on the instantiated type. 1028 foreach (MethodInfo m in type.GetRuntimeMethods()) 1029 { 1030 #if UNSUPPORTEDAPI 1031 if ((m.MetadataToken != methodInfo.MetadataToken) || (m.Module != methodInfo.Module)) 1032 #else 1033 if (!m.HasSameMetadataDefinitionAs(methodInfo)) 1034 #endif 1035 { 1036 continue; 1037 } 1038 1039 Debug.Assert((m.Name == methodInfo.Name) && 1040 (m.GetParameters().Length == genericParams.Count) && 1041 (TypesAreEqual(m.ReturnType, genericReturn.AssociatedSystemType))); 1042 1043 bool bMatch = true; 1044 ParameterInfo[] parameters = m.GetParameters(); 1045 for (int i = 0; i < genericParams.Count; i++) 1046 { 1047 if (!TypesAreEqual(parameters[i].ParameterType, genericParams[i].AssociatedSystemType)) 1048 { 1049 bMatch = false; 1050 break; 1051 } 1052 } 1053 if (bMatch) 1054 { 1055 if (m.IsGenericMethod) 1056 { 1057 int size = methinfo.Method.TypeArgs?.Count ?? 0; 1058 Type[] typeArgs = new Type[size]; 1059 if (size > 0) 1060 { 1061 for (int i = 0; i < methinfo.Method.TypeArgs.Count; i++) 1062 { 1063 typeArgs[i] = methinfo.Method.TypeArgs[i].AssociatedSystemType; 1064 } 1065 } 1066 return m.MakeGenericMethod(typeArgs); 1067 } 1068 1069 return m; 1070 } 1071 } 1072 1073 Debug.Assert(false, "Could not find matching method"); 1074 throw Error.InternalCompilerError(); 1075 } 1076 1077 ///////////////////////////////////////////////////////////////////////////////// 1078 GetConstructorInfoFromExpr(ExprMethodInfo methinfo)1079 private ConstructorInfo GetConstructorInfoFromExpr(ExprMethodInfo methinfo) 1080 { 1081 // To do this, we need to construct a type array of the parameter types, 1082 // get the parent constructed type, and get the method from it. 1083 1084 AggregateType aggType = methinfo.Method.Ats; 1085 MethodSymbol methSym = methinfo.Method.Meth(); 1086 1087 TypeArray genericInstanceParams = _typeManager.SubstTypeArray(methSym.Params, aggType); 1088 Type type = aggType.AssociatedSystemType; 1089 ConstructorInfo ctorInfo = (ConstructorInfo)methSym.AssociatedMemberInfo; 1090 1091 // This is to ensure that for embedded nopia types, we have the 1092 // appropriate local type from the member itself; this is possible 1093 // because nopia types are not generic or nested. 1094 if (!type.IsGenericType && !type.IsNested) 1095 { 1096 type = ctorInfo.DeclaringType; 1097 } 1098 1099 foreach (ConstructorInfo c in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) 1100 { 1101 #if UNSUPPORTEDAPI 1102 if ((c.MetadataToken != ctorInfo.MetadataToken) || (c.Module != ctorInfo.Module)) 1103 #else 1104 if (!c.HasSameMetadataDefinitionAs(ctorInfo)) 1105 #endif 1106 { 1107 continue; 1108 } 1109 Debug.Assert(c.GetParameters() == null || c.GetParameters().Length == genericInstanceParams.Count); 1110 1111 bool bMatch = true; 1112 ParameterInfo[] parameters = c.GetParameters(); 1113 for (int i = 0; i < genericInstanceParams.Count; i++) 1114 { 1115 if (!TypesAreEqual(parameters[i].ParameterType, genericInstanceParams[i].AssociatedSystemType)) 1116 { 1117 bMatch = false; 1118 break; 1119 } 1120 } 1121 if (bMatch) 1122 { 1123 return c; 1124 } 1125 } 1126 1127 Debug.Assert(false, "Could not find matching constructor"); 1128 throw Error.InternalCompilerError(); 1129 } 1130 1131 ///////////////////////////////////////////////////////////////////////////////// 1132 GetPropertyInfoFromExpr(ExprPropertyInfo propinfo)1133 private PropertyInfo GetPropertyInfoFromExpr(ExprPropertyInfo propinfo) 1134 { 1135 // To do this, we need to construct a type array of the parameter types, 1136 // get the parent constructed type, and get the property from it. 1137 1138 AggregateType aggType = propinfo.Property.Ats; 1139 PropertySymbol propSym = propinfo.Property.Prop(); 1140 1141 TypeArray genericInstanceParams = _typeManager.SubstTypeArray(propSym.Params, aggType, null); 1142 1143 Type type = aggType.AssociatedSystemType; 1144 PropertyInfo propertyInfo = propSym.AssociatedPropertyInfo; 1145 1146 // This is to ensure that for embedded nopia types, we have the 1147 // appropriate local type from the member itself; this is possible 1148 // because nopia types are not generic or nested. 1149 if (!type.IsGenericType && !type.IsNested) 1150 { 1151 type = propertyInfo.DeclaringType; 1152 } 1153 1154 foreach (PropertyInfo p in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) 1155 { 1156 #if UNSUPPORTEDAPI 1157 if ((p.MetadataToken != propertyInfo.MetadataToken) || (p.Module != propertyInfo.Module)) 1158 #else 1159 if (!p.HasSameMetadataDefinitionAs(propertyInfo)) 1160 { 1161 #endif 1162 continue; 1163 } 1164 Debug.Assert((p.Name == propertyInfo.Name) && 1165 (p.GetIndexParameters() == null || p.GetIndexParameters().Length == genericInstanceParams.Count)); 1166 1167 bool bMatch = true; 1168 ParameterInfo[] parameters = p.GetSetMethod(true) != null ? 1169 p.GetSetMethod(true).GetParameters() : p.GetGetMethod(true).GetParameters(); 1170 for (int i = 0; i < genericInstanceParams.Count; i++) 1171 { 1172 if (!TypesAreEqual(parameters[i].ParameterType, genericInstanceParams[i].AssociatedSystemType)) 1173 { 1174 bMatch = false; 1175 break; 1176 } 1177 } 1178 if (bMatch) 1179 { 1180 return p; 1181 } 1182 } 1183 1184 Debug.Assert(false, "Could not find matching property"); 1185 throw Error.InternalCompilerError(); 1186 } 1187 1188 ///////////////////////////////////////////////////////////////////////////////// 1189 TypesAreEqual(Type t1, Type t2)1190 private bool TypesAreEqual(Type t1, Type t2) 1191 { 1192 if (t1 == t2) 1193 { 1194 return true; 1195 } 1196 1197 return t1.IsEquivalentTo(t2); 1198 } 1199 #endregion 1200 } 1201 } 1202