Example #1
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;
             * }*/

            // Emit the condition.
            var condition = this.GetOperand(0);

            condition.GenerateCode(generator, optimizationInfo);

            // Convert the condition to a boolean.
            EmitConversion.ToBool(generator, condition.ResultType);

            // Branch if the condition is false.
            var startOfElse = generator.CreateLabel();

            generator.BranchIfFalse(startOfElse);

            // Calculate the result type.
            var outputType = this.ResultType;

            // Emit the second operand and convert it to the result type.
            var operand2 = this.GetOperand(1);

            operand2.GenerateCode(generator, optimizationInfo);
            EmitConversion.Convert(generator, operand2.ResultType, outputType, optimizationInfo);

            // Branch to the end.
            var end = generator.CreateLabel();

            generator.Branch(end);
            generator.DefineLabelPosition(startOfElse);

            // Emit the third operand and convert it to the result type.
            var operand3 = this.GetOperand(2);

            operand3.GenerateCode(generator, optimizationInfo);
            EmitConversion.Convert(generator, operand3.ResultType, outputType, optimizationInfo);

            // Define the end label.
            generator.DefineLabelPosition(end);
        }
        internal override void Set(ILGenerator generator, OptimizationInfo optimizationInfo, bool rIU, Type valueType, SetValueMethod value)
        {
            // Resolve if needed:
            if (Field == null && Property == null)
            {
                Resolve(valueType);
            }
            else
            {
                // Update type, potentially forcing the variable to change type
                // (unless it's a fixed property, in which case the value being set changes type instead):
                if (Property == null)
                {
                    // Fixed property - var changes type:
                    Type = valueType;
                }
            }

            ILLocalVariable localVar = null;

            // Is the return value of this set in use?
            // E.g. var x=obj.x=14;
            if (rIU)
            {
                // It's in use and 'obj.x' is not static.

                // Output the value twice:
                value(true);

                // If it's not static then we now have [obj][value][value] on the stack.
                // Calling the set method would fail (as it'll operate on the duplicated value).
                // So, we have to pop one off and re-add it after.

                if (!IsStatic)
                {
                    // Note that if it's static, no 'obj' reference goes onto the stack anyway.

                    // At this point, we have our target object followed by two copies of the value.
                    // For the following Call/StoreField to work correctly, we must store the 2nd copy into a local.
                    localVar = generator.DeclareVariable(valueType);

                    // Store into the local:
                    generator.StoreVariable(localVar);
                }
            }
            else
            {
                // Output the value just once:
                value(false);
            }

            if (_Type != valueType)
            {
                // Convert if needed:
                EmitConversion.Convert(generator, valueType, _Type, optimizationInfo);
            }

            if (Property != null)
            {
                // Call the set method:
                generator.Call(Property.SetMethod);
            }
            else
            {
                // Load the field:
                generator.StoreField(Field);
            }

            if (localVar != null)
            {
                // Reload the 2nd copy of the value:
                generator.LoadVariable(localVar);
            }
        }