public override void GenerateCode(ILGenerator gen, CodeFlow cf) { CodeFlow.LoadEvaluationContext(gen); var leftDesc = LeftOperand.ExitDescriptor; var rightDesc = RightOperand.ExitDescriptor; var leftPrim = CodeFlow.IsValueType(leftDesc); var rightPrim = CodeFlow.IsValueType(rightDesc); cf.EnterCompilationScope(); LeftOperand.GenerateCode(gen, cf); cf.ExitCompilationScope(); if (leftPrim) { CodeFlow.InsertBoxIfNecessary(gen, leftDesc); } cf.EnterCompilationScope(); RightOperand.GenerateCode(gen, cf); cf.ExitCompilationScope(); if (rightPrim) { CodeFlow.InsertBoxIfNecessary(gen, rightDesc); } gen.Emit(OpCodes.Call, _equalityCheck); cf.PushDescriptor(TypeDescriptor.Z); }
public override void GenerateCode(ILGenerator gen, CodeFlow cf) { // pseudo: if (leftOperandValue) { result=true; } else { result=rightOperandValue; } var elseTarget = gen.DefineLabel(); var endIfTarget = gen.DefineLabel(); var result = gen.DeclareLocal(typeof(bool)); cf.EnterCompilationScope(); LeftOperand.GenerateCode(gen, cf); cf.UnboxBooleanIfNecessary(gen); cf.ExitCompilationScope(); gen.Emit(OpCodes.Brfalse, elseTarget); gen.Emit(OpCodes.Ldc_I4_1); gen.Emit(OpCodes.Stloc, result); gen.Emit(OpCodes.Br, endIfTarget); gen.MarkLabel(elseTarget); cf.EnterCompilationScope(); RightOperand.GenerateCode(gen, cf); cf.UnboxBooleanIfNecessary(gen); cf.ExitCompilationScope(); gen.Emit(OpCodes.Stloc, result); gen.MarkLabel(endIfTarget); gen.Emit(OpCodes.Ldloc, result); cf.PushDescriptor(_exitTypeDescriptor); }
public override void GenerateCode(ILGenerator gen, CodeFlow cf) { // May reach here without it computed if all elements are literals ComputeExitTypeDescriptor(); cf.EnterCompilationScope(); _children[0].GenerateCode(gen, cf); var lastDesc = cf.LastDescriptor() ?? throw new InvalidOperationException("No last descriptor"); if (!CodeFlow.IsValueType(lastDesc)) { gen.Emit(OpCodes.Unbox_Any, typeof(bool)); } cf.ExitCompilationScope(); var elseTarget = gen.DefineLabel(); var endOfIfTarget = gen.DefineLabel(); gen.Emit(OpCodes.Brfalse, elseTarget); cf.EnterCompilationScope(); _children[1].GenerateCode(gen, cf); if (!CodeFlow.IsValueType(_exitTypeDescriptor)) { lastDesc = cf.LastDescriptor(); if (lastDesc == null) { throw new InvalidOperationException("No last descriptor"); } CodeFlow.InsertBoxIfNecessary(gen, lastDesc); } cf.ExitCompilationScope(); gen.Emit(OpCodes.Br, endOfIfTarget); gen.MarkLabel(elseTarget); cf.EnterCompilationScope(); _children[2].GenerateCode(gen, cf); if (!CodeFlow.IsValueType(_exitTypeDescriptor)) { lastDesc = cf.LastDescriptor(); if (lastDesc == null) { throw new InvalidOperationException("No last descriptor"); } CodeFlow.InsertBoxIfNecessary(gen, lastDesc); } cf.ExitCompilationScope(); gen.MarkLabel(endOfIfTarget); cf.PushDescriptor(_exitTypeDescriptor); }
protected static void GenerateCodeForArgument(ILGenerator gen, CodeFlow cf, SpelNode argument, TypeDescriptor paramDesc) { cf.EnterCompilationScope(); argument.GenerateCode(gen, cf); var lastDesc = cf.LastDescriptor(); if (lastDesc == null) { throw new InvalidOperationException("No last descriptor"); } var valueTypeOnStack = CodeFlow.IsValueType(lastDesc); // Check if need to box it for the method reference? if (valueTypeOnStack && paramDesc.IsReferenceType) { CodeFlow.InsertBoxIfNecessary(gen, lastDesc); } else if (paramDesc.IsValueType && !paramDesc.IsBoxed && !valueTypeOnStack) { gen.Emit(OpCodes.Unbox_Any, paramDesc.Value); } else { // This would be unnecessary in the case of subtyping (e.g. method takes Number but Integer passed in) CodeFlow.InsertCastClass(gen, paramDesc); } cf.ExitCompilationScope(); }
public override void GenerateCode(ILGenerator gen, CodeFlow cf) { CodeFlow.LoadEvaluationContext(gen); var leftDesc = LeftOperand.ExitDescriptor; var rightDesc = RightOperand.ExitDescriptor; var leftPrim = CodeFlow.IsValueType(leftDesc); var rightPrim = CodeFlow.IsValueType(rightDesc); cf.EnterCompilationScope(); LeftOperand.GenerateCode(gen, cf); cf.ExitCompilationScope(); if (leftPrim) { CodeFlow.InsertBoxIfNecessary(gen, leftDesc); } cf.EnterCompilationScope(); RightOperand.GenerateCode(gen, cf); cf.ExitCompilationScope(); if (rightPrim) { CodeFlow.InsertBoxIfNecessary(gen, rightDesc); } // returns bool gen.Emit(OpCodes.Call, _equalityCheck); // Invert the boolean var result = gen.DeclareLocal(typeof(bool)); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Ceq); gen.Emit(OpCodes.Stloc, result); gen.Emit(OpCodes.Ldloc, result); cf.PushDescriptor(TypeDescriptor.Z); }
public override void GenerateCode(ILGenerator gen, CodeFlow cf) { // exit type descriptor can be null if both components are literal expressions ComputeExitTypeDescriptor(); cf.EnterCompilationScope(); _children[0].GenerateCode(gen, cf); var lastDesc = cf.LastDescriptor(); if (lastDesc == null) { throw new InvalidOperationException("No last descriptor"); } // if primitive result, boxed will be on stack CodeFlow.InsertBoxIfNecessary(gen, lastDesc); cf.ExitCompilationScope(); var ifResult = gen.DeclareLocal(typeof(bool)); var finalResult = gen.DeclareLocal(_exitTypeDescriptor.Value); var loadFinalResult = gen.DefineLabel(); // Save off child1 result var child1Result = gen.DeclareLocal(typeof(object)); gen.Emit(OpCodes.Stloc, child1Result); var child1IsNull = gen.DefineLabel(); gen.Emit(OpCodes.Ldloc, child1Result); // br if child1 null gen.Emit(OpCodes.Brfalse, child1IsNull); // Check for empty string gen.Emit(OpCodes.Ldstr, string.Empty); gen.Emit(OpCodes.Ldloc, child1Result); gen.Emit(OpCodes.Callvirt, _equalsMethod); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Ceq); // save empty string result gen.Emit(OpCodes.Stloc, ifResult); var loadCheckIfResults = gen.DefineLabel(); gen.Emit(OpCodes.Br, loadCheckIfResults); // Child1 null, load false for if result gen.MarkLabel(child1IsNull); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Stloc, ifResult); // Fall thru to check if results; // Mark Check if Results gen.MarkLabel(loadCheckIfResults); // Load if results; gen.Emit(OpCodes.Ldloc, ifResult); var callChild2 = gen.DefineLabel(); // If faild, call child2 for results gen.Emit(OpCodes.Brfalse, callChild2); // Final result is child 1, save final gen.Emit(OpCodes.Ldloc, child1Result); gen.Emit(OpCodes.Stloc, finalResult); gen.Emit(OpCodes.Br, loadFinalResult); gen.MarkLabel(callChild2); cf.EnterCompilationScope(); _children[1].GenerateCode(gen, cf); if (!CodeFlow.IsValueType(_exitTypeDescriptor)) { lastDesc = cf.LastDescriptor(); if (lastDesc == null) { throw new InvalidOperationException("No last descriptor"); } if (lastDesc == TypeDescriptor.V) { gen.Emit(OpCodes.Ldnull); } else { CodeFlow.InsertBoxIfNecessary(gen, lastDesc); } } cf.ExitCompilationScope(); gen.Emit(OpCodes.Stloc, finalResult); // Load final result on stack gen.MarkLabel(loadFinalResult); gen.Emit(OpCodes.Ldloc, finalResult); cf.PushDescriptor(_exitTypeDescriptor); }