Ejemplo n.º 1
0
		/// <summary>
		/// Emits instructions to conform a required access type.
		/// </summary>
		/// <param name="callExpression">Expression emitting the call.</param>
		/// <param name="loadAddress">Whether to load an address of the return value.</param>
		/// <param name="result">The type code of a top item of the evaluation stack.</param>
		public void EmitReturnValueHandling(Expression/*!*/ callExpression, bool loadAddress, ref PhpTypeCode result)
		{
			Debug.Assert(callExpression != null);

			if (loadAddress)
			{
                if (result == PhpTypeCode.PhpReference)
				{
					// LOADADDR STACK.Value;
					il.Emit(OpCodes.Ldflda, Fields.PhpReference_Value);
				}
				else
				{
                    if (result == PhpTypeCode.Void)
                        il.Emit(OpCodes.Ldnull);
                    
                    // local = STACK; 
					// LOADADDR local;
					LocalBuilder local = il.GetTemporaryLocal(PhpTypeCodeEnum.ToType(result), true);
					il.Stloc(local);
					il.Ldloca(local);
				}
				result = PhpTypeCode.ObjectAddress;
				return;
			}

			switch (callExpression.GetAccess())
			{
				case AccessType.None:

					// return value is discarded:
					if (result != PhpTypeCode.Void)
					{
						il.Emit(OpCodes.Pop);
						result = PhpTypeCode.Void;
					}
					break;

				case AccessType.ReadUnknown:
				case AccessType.ReadRef:

					if (result != PhpTypeCode.PhpReference)
					{
						// return value is "boxed" to PhpReference:
						if (result != PhpTypeCode.Void)
						{
							EmitBoxing(result);
							EmitVariableCopy(CopyReason.ReturnedByCopy, callExpression);
							il.Emit(OpCodes.Newobj, Constructors.PhpReference_Object);
						}
						else
						{
							il.Emit(OpCodes.Newobj, Constructors.PhpReference_Void);
						}

						result = PhpTypeCode.PhpReference;
					}
					break;

				case AccessType.Read:

					if (result == PhpTypeCode.PhpReference)
					{
						// return value is dereferenced:
						il.Emit(OpCodes.Ldfld, Fields.PhpReference_Value);
						result = PhpTypeCode.Object;
					}
					else if (result == PhpTypeCode.Void)
					{
						// null value is loaded as a result:
						il.Emit(OpCodes.Ldnull);
						result = PhpTypeCode.Object;
					}
					break;

				default:
					Debug.Fail(null);
					break;
			}
		}