/// <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); } }