ToUInt32() 공개 정적인 메소드

Pops the value on the stack, converts it to an unsigned integer, then pushes the integer result onto the stack. Large numbers wrap (i.e. 4294967296 -> 0).
public static ToUInt32 ( ILGenerator generator, PrimitiveType fromType ) : void
generator ILGenerator The IL generator.
fromType PrimitiveType The type to convert from.
리턴 void
예제 #1
0
        /// <summary>
        /// Outputs the values needed to get or set this reference.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public void GenerateReference(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            string             propertyName     = null;
            TypeOfMemberAccess memberAccessType = DetermineTypeOfMemberAccess(optimizationInfo, out propertyName);

            if (memberAccessType == TypeOfMemberAccess.ArrayIndex)
            {
                // Array indexer
                // -------------

                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);
                lhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToObject(generator, lhs.ResultType, optimizationInfo);

                // Load the right-hand side and convert to a uint32.
                var rhs = this.GetOperand(1);
                rhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToUInt32(generator, rhs.ResultType);
            }
            else if (memberAccessType == TypeOfMemberAccess.Static)
            {
                // Named property access (e.g. x = y.property or x = y['property'])
                // ----------------------------------------------------------------

                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);
                lhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToObject(generator, lhs.ResultType, optimizationInfo);
            }
            else
            {
                // Dynamic property access
                // -----------------------

                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);
                lhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToObject(generator, lhs.ResultType, optimizationInfo);

                // Load the value and convert it to a string.
                var rhs = this.GetOperand(1);
                rhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToString(generator, rhs.ResultType);
            }
        }
예제 #2
0
        /// <summary>
        /// Pushes the value of the reference onto the stack.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        /// <param name="throwIfUnresolvable"> <c>true</c> to throw a ReferenceError exception if
        /// the name is unresolvable; <c>false</c> to output <c>null</c> instead. </param>
        public void GenerateGet(ILGenerator generator, OptimizationInfo optimizationInfo, bool throwIfUnresolvable)
        {
            string propertyName = null;
            bool   isArrayIndex = false;

            // Right-hand-side can be a property name (a.b)
            if (this.OperatorType == OperatorType.MemberAccess)
            {
                var rhs = this.GetOperand(1) as NameExpression;
                if (rhs == null)
                {
                    throw new JavaScriptException(optimizationInfo.Engine, "SyntaxError", "Invalid member access", optimizationInfo.SourceSpan.StartLine, optimizationInfo.Source.Path, optimizationInfo.FunctionName);
                }
                propertyName = rhs.Name;
            }

            // Or a constant indexer (a['b'])
            if (this.OperatorType == OperatorType.Index)
            {
                var rhs = this.GetOperand(1) as LiteralExpression;
                if (rhs != null && (PrimitiveTypeUtilities.IsNumeric(rhs.ResultType) || rhs.ResultType == PrimitiveType.String))
                {
                    propertyName = TypeConverter.ToString(rhs.Value);

                    // Or a array index (a[0])
                    if (rhs.ResultType == PrimitiveType.Int32 || (propertyName != null && Library.ArrayInstance.ParseArrayIndex(propertyName) != uint.MaxValue))
                    {
                        isArrayIndex = true;
                    }
                }
            }

            if (isArrayIndex == true)
            {
                // Array indexer
                // -------------
                // xxx = object[index]

                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);
                lhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToObject(generator, lhs.ResultType, optimizationInfo);

                // Load the right-hand side and convert to a uint32.
                var rhs = this.GetOperand(1);
                rhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToUInt32(generator, rhs.ResultType);

                // Call the indexer.
                generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_Int);
            }
            else if (propertyName != null)
            {
                //// Load the left-hand side and convert to an object instance.
                //var lhs = this.GetOperand(0);
                //lhs.GenerateCode(generator, optimizationInfo);
                //EmitConversion.ToObject(generator, lhs.ResultType);

                //// Call Get(string)
                //generator.LoadString(propertyName);
                //generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_String);



                // Named property access (e.g. x = y.property)
                // -------------------------------------------
                // __object_cacheKey = null;
                // __object_property_cachedIndex = 0;
                // ...
                // if (__object_cacheKey != object.InlineCacheKey)
                //     xxx = object.InlineGetPropertyValue("property", out __object_property_cachedIndex, out __object_cacheKey)
                // else
                //     xxx = object.InlinePropertyValues[__object_property_cachedIndex];

                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);
                lhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToObject(generator, lhs.ResultType, optimizationInfo);

                // TODO: share these variables somehow.
                var cacheKey    = generator.DeclareVariable(typeof(object));
                var cachedIndex = generator.DeclareVariable(typeof(int));

                // Store the object into a temp variable.
                var objectInstance = generator.DeclareVariable(PrimitiveType.Object);
                generator.StoreVariable(objectInstance);

                // if (__object_cacheKey != object.InlineCacheKey)
                generator.LoadVariable(cacheKey);
                generator.LoadVariable(objectInstance);
                generator.Call(ReflectionHelpers.ObjectInstance_InlineCacheKey);
                var elseClause = generator.CreateLabel();
                generator.BranchIfEqual(elseClause);

                // value = object.InlineGetProperty("property", out __object_property_cachedIndex, out __object_cacheKey)
                generator.LoadVariable(objectInstance);
                generator.LoadString(propertyName);
                generator.LoadAddressOfVariable(cachedIndex);
                generator.LoadAddressOfVariable(cacheKey);
                generator.Call(ReflectionHelpers.ObjectInstance_InlineGetPropertyValue);

                var endOfIf = generator.CreateLabel();
                generator.Branch(endOfIf);

                // else
                generator.DefineLabelPosition(elseClause);

                // value = object.InlinePropertyValues[__object_property_cachedIndex];
                generator.LoadVariable(objectInstance);
                generator.Call(ReflectionHelpers.ObjectInstance_InlinePropertyValues);
                generator.LoadVariable(cachedIndex);
                generator.LoadArrayElement(typeof(object));

                // End of the if statement
                generator.DefineLabelPosition(endOfIf);
            }
            else
            {
                // Dynamic property access
                // -----------------------
                // xxx = object.Get(x)

                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);
                lhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToObject(generator, lhs.ResultType, optimizationInfo);

                // Load the property name and convert to a string.
                var rhs = this.GetOperand(1);
                rhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToString(generator, rhs.ResultType);

                // Call Get(string)
                generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_String);
            }
        }
예제 #3
0
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // If a return value is not expected, generate only the side-effects.

            /*if (optimizationInfo.SuppressReturnValue == true)
             * {
             *  this.GenerateSideEffects(generator, optimizationInfo);
             *  return;
             * }*/

            // Special case the addition operator.
            if (this.OperatorType == OperatorType.Add)
            {
                GenerateAdd(generator, optimizationInfo);
                return;
            }

            // Special case the instanceof operator.
            if (this.OperatorType == OperatorType.InstanceOf)
            {
                GenerateInstanceOf(generator, optimizationInfo);
                return;
            }

            // Special case the in operator.
            if (this.OperatorType == OperatorType.In)
            {
                GenerateIn(generator, optimizationInfo);
                return;
            }

            // Special case the relational operators.
            if (this.OperatorType == OperatorType.LessThan ||
                this.OperatorType == OperatorType.LessThanOrEqual ||
                this.OperatorType == OperatorType.GreaterThan ||
                this.OperatorType == OperatorType.GreaterThanOrEqual)
            {
                GenerateRelational(generator, optimizationInfo);
                return;
            }

            // Special case the logical operators.
            if (this.OperatorType == OperatorType.LogicalAnd ||
                this.OperatorType == OperatorType.LogicalOr)
            {
                GenerateLogical(generator, optimizationInfo);
                return;
            }

            // Load the left hand side onto the stack.
            this.Left.GenerateCode(generator, optimizationInfo);

            // Convert the left argument.
            switch (this.OperatorType)
            {
            // Arithmetic operations.
            case OperatorType.Subtract:
            case OperatorType.Multiply:
            case OperatorType.Divide:
            case OperatorType.Modulo:
            case OperatorType.Exponentiation:
                EmitConversion.ToNumber(generator, this.Left.ResultType);
                break;

            // Bitwise operations.
            case OperatorType.BitwiseAnd:
            case OperatorType.BitwiseOr:
            case OperatorType.BitwiseXor:
            case OperatorType.LeftShift:
            case OperatorType.SignedRightShift:
            case OperatorType.UnsignedRightShift:
                EmitConversion.ToInt32(generator, this.Left.ResultType);
                break;

            // Equality operations.
            case OperatorType.Equal:
            case OperatorType.StrictlyEqual:
            case OperatorType.NotEqual:
            case OperatorType.StrictlyNotEqual:
                EmitConversion.ToAny(generator, this.Left.ResultType);
                break;
            }

            // Load the right hand side onto the stack.
            this.Right.GenerateCode(generator, optimizationInfo);

            // Convert the right argument.
            switch (this.OperatorType)
            {
            // Arithmetic operations.
            case OperatorType.Subtract:
            case OperatorType.Multiply:
            case OperatorType.Divide:
            case OperatorType.Modulo:
            case OperatorType.Exponentiation:
                EmitConversion.ToNumber(generator, this.Right.ResultType);
                break;

            // Bitwise operations.
            case OperatorType.BitwiseAnd:
            case OperatorType.BitwiseOr:
            case OperatorType.BitwiseXor:
                EmitConversion.ToInt32(generator, this.Right.ResultType);
                break;

            case OperatorType.LeftShift:
            case OperatorType.SignedRightShift:
            case OperatorType.UnsignedRightShift:
                EmitConversion.ToUInt32(generator, this.Right.ResultType);
                generator.LoadInt32(0x1F);
                generator.BitwiseAnd();
                break;

            // Equality operations.
            case OperatorType.Equal:
            case OperatorType.StrictlyEqual:
            case OperatorType.NotEqual:
            case OperatorType.StrictlyNotEqual:
                EmitConversion.ToAny(generator, this.Right.ResultType);
                break;
            }

            // Apply the operator.
            switch (this.OperatorType)
            {
            // Arithmetic operations.
            case OperatorType.Subtract:
                generator.Subtract();
                break;

            case OperatorType.Multiply:
                generator.Multiply();
                break;

            case OperatorType.Divide:
                generator.Divide();
                break;

            case OperatorType.Modulo:
                generator.Remainder();
                break;

            case OperatorType.Exponentiation:
                generator.CallStatic(ReflectionHelpers.Math_Pow);
                break;

            // Bitwise operations.
            case OperatorType.BitwiseAnd:
                generator.BitwiseAnd();
                break;

            case OperatorType.BitwiseOr:
                generator.BitwiseOr();
                break;

            case OperatorType.BitwiseXor:
                generator.BitwiseXor();
                break;

            // Shift operations.
            case OperatorType.LeftShift:
                generator.ShiftLeft();
                break;

            case OperatorType.SignedRightShift:
                generator.ShiftRight();
                break;

            case OperatorType.UnsignedRightShift:
                generator.ShiftRightUnsigned();
                EmitConversion.ToNumber(generator, PrimitiveType.UInt32);
                break;

            // Equality operations.
            case OperatorType.Equal:
                generator.Call(ReflectionHelpers.TypeComparer_Equals);
                break;

            case OperatorType.StrictlyEqual:
                generator.Call(ReflectionHelpers.TypeComparer_StrictEquals);
                break;

            case OperatorType.NotEqual:
                generator.Call(ReflectionHelpers.TypeComparer_Equals);
                generator.LoadBoolean(false);
                generator.CompareEqual();
                break;

            case OperatorType.StrictlyNotEqual:
                generator.Call(ReflectionHelpers.TypeComparer_StrictEquals);
                generator.LoadBoolean(false);
                generator.CompareEqual();
                break;

            default:
                throw new NotImplementedException(string.Format("Unsupported operator {0}", this.OperatorType));
            }
        }
예제 #4
0
        /// <summary>
        /// Pops the value on the stack, converts it from an object to the given type, then pushes
        /// the result onto the stack.
        /// </summary>
        /// <param name="generator"> The IL generator. </param>
        /// <param name="toType"> The type to convert to. </param>
        /// <param name="convertToAddress"> <c>true</c> if the value is intended for use as an
        /// instance pointer; <c>false</c> otherwise. </param>
        internal static void EmitConversionToType(ILGenerator generator, Type toType, bool convertToAddress)
        {
            // Convert Null.Value to null if the target type is a reference type.
            ILLabel endOfNullCheck = null;

            if (toType.IsValueType == false)
            {
                var startOfElse = generator.CreateLabel();
                endOfNullCheck = generator.CreateLabel();
                generator.Duplicate();
                EmitHelpers.EmitNull(generator);
                generator.BranchIfNotEqual(startOfElse);
                generator.Pop();
                generator.LoadNull();
                generator.Branch(endOfNullCheck);
                generator.DefineLabelPosition(startOfElse);
            }

            switch (Type.GetTypeCode(toType))
            {
            case TypeCode.Boolean:
                EmitConversion.ToBool(generator, PrimitiveType.Any);
                break;

            case TypeCode.Byte:
                EmitConversion.ToInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.Char:
                EmitConversion.ToString(generator, PrimitiveType.Any);
                generator.Duplicate();
                generator.Call(ReflectionHelpers.String_Length);
                generator.LoadInt32(1);
                var endOfCharCheck = generator.CreateLabel();
                generator.BranchIfEqual(endOfCharCheck);
                EmitHelpers.EmitThrow(generator, ErrorType.TypeError, "Cannot convert string to char - the string must be exactly one character long");
                generator.DefineLabelPosition(endOfCharCheck);
                generator.LoadInt32(0);
                generator.Call(ReflectionHelpers.String_GetChars);
                break;

            case TypeCode.DBNull:
                throw new NotSupportedException("DBNull is not a supported parameter type.");

            case TypeCode.Decimal:
                EmitConversion.ToNumber(generator, PrimitiveType.Any);
                generator.NewObject(ReflectionHelpers.Decimal_Constructor_Double);
                break;

            case TypeCode.Double:
                EmitConversion.ToNumber(generator, PrimitiveType.Any);
                break;

            case TypeCode.Empty:
                throw new NotSupportedException("Empty is not a supported return type.");

            case TypeCode.Int16:
                EmitConversion.ToInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.Int32:
                EmitConversion.ToInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.Int64:
                EmitConversion.ToNumber(generator, PrimitiveType.Any);
                generator.ConvertToInt64();
                break;

            case TypeCode.DateTime:
            case TypeCode.Object:
                // Check if the type must be unwrapped.
                generator.Duplicate();
                generator.IsInstance(typeof(Jurassic.Library.ClrInstanceWrapper));
                var endOfUnwrapCheck = generator.CreateLabel();
                generator.BranchIfFalse(endOfUnwrapCheck);

                // Unwrap the wrapped instance.
                generator.Call(ReflectionHelpers.ClrInstanceWrapper_GetWrappedInstance);
                generator.DefineLabelPosition(endOfUnwrapCheck);

                // Value types must be unboxed.
                if (toType.IsValueType == true)
                {
                    if (convertToAddress == true)
                    {
                        // Unbox.
                        generator.Unbox(toType);
                    }
                    else
                    {
                        // Unbox and copy to the stack.
                        generator.UnboxAny(toType);
                    }

                    //// Calling methods on value required the address of the value type, not the value type itself.
                    //if (argument.Source == BinderArgumentSource.ThisValue && argument.Type.IsValueType == true)
                    //{
                    //    var temp = generator.CreateTemporaryVariable(argument.Type);
                    //    generator.StoreVariable(temp);
                    //    generator.LoadAddressOfVariable(temp);
                    //    generator.ReleaseTemporaryVariable(temp);
                    //}
                }


                break;

            case TypeCode.SByte:
                EmitConversion.ToInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.Single:
                EmitConversion.ToNumber(generator, PrimitiveType.Any);
                break;

            case TypeCode.String:
                EmitConversion.ToString(generator, PrimitiveType.Any);
                break;

            case TypeCode.UInt16:
                EmitConversion.ToInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.UInt32:
                EmitConversion.ToUInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.UInt64:
                EmitConversion.ToNumber(generator, PrimitiveType.Any);
                generator.ConvertToUnsignedInt64();
                break;
            }

            // Label the end of the null check.
            if (toType.IsValueType == false)
            {
                generator.DefineLabelPosition(endOfNullCheck);
            }
        }