/// <summary> /// Note a label's position if we are in mark mode /// </summary> /// <param name="info"></param> /// <param name="target"></param> /// <param name="ilg"></param> private static void MarkBranchTarget(ShortCircuitInfo info, Label target, FleeILGenerator ilg) { if (ilg.IsTemp == true) { info.Branches.MarkLabel(ilg, target); } }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { MethodInfo overloadedMethod = this.GetOverloadedAndOrOperator(); if ((overloadedMethod != null)) { // Emit a call to an overloaded operator this.EmitOverloadedOperatorCall(overloadedMethod, ilg, services); } else { Type resultType = this.ResultType; if (object.ReferenceEquals(resultType, typeof(bool))) { this.DoEmitLogical(ilg, services); } else { MyLeftChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, resultType, ilg); MyRightChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, resultType, ilg); EmitBitwiseOperation(ilg, _myOperation); } } }
/// <summary> /// Emit the end cases for a short-circuit /// </summary> /// <param name="info"></param> /// <param name="ilg"></param> /// <param name="endLabel"></param> private static void EmitTerminals(ShortCircuitInfo info, FleeILGenerator ilg, Label endLabel) { // Emit the false case if it was used if (info.Branches.HasLabel(OurFalseTerminalKey) == true) { Label falseLabel = info.Branches.FindLabel(OurFalseTerminalKey); // Mark the label and note its position ilg.MarkLabel(falseLabel); MarkBranchTarget(info, falseLabel, ilg); ilg.Emit(OpCodes.Ldc_I4_0); // If we also have a true terminal, then skip over it if (info.Branches.HasLabel(OurTrueTerminalKey) == true) { ilg.Emit(OpCodes.Br_S, endLabel); } } // Emit the true case if it was used if (info.Branches.HasLabel(OurTrueTerminalKey) == true) { Label trueLabel = info.Branches.FindLabel(OurTrueTerminalKey); // Mark the label and note its position ilg.MarkLabel(trueLabel); MarkBranchTarget(info, trueLabel, ilg); ilg.Emit(OpCodes.Ldc_I4_1); } }
/// <summary> /// Emit a short-circuited logical operation sequence /// The idea: Store all the leaf operands in a stack with the leftmost at the top and rightmost at the bottom. /// For each operand, emit it and try to find an end point for when it short-circuits. This means we go up through /// the stack of operators (ignoring siblings) until we find a different operation (then emit a branch to its right operand) /// or we reach the root (emit a branch to a true/false). /// Repeat the process for all operands and then emit the true/false/last operand end cases. /// </summary> /// <param name="ilg"></param> /// <param name="info"></param> /// <param name="services"></param> private void EmitLogical(FleeILGenerator ilg, ShortCircuitInfo info, IServiceProvider services) { // We always have an end label info.Branches.GetLabel(OurEndLabelKey, ilg); // Populate our data structures this.PopulateData(info); // Emit the sequence EmitLogicalShortCircuit(ilg, info, services); // Get the last operand ExpressionElement terminalOperand = (ExpressionElement)info.Operands.Pop(); // Emit it EmitOperand(terminalOperand, info, ilg, services); // And jump to the end Label endLabel = info.Branches.FindLabel(OurEndLabelKey); ilg.Emit(OpCodes.Br_S, endLabel); // Emit our true/false terminals EmitTerminals(info, ilg, endLabel); // Mark the end ilg.MarkLabel(endLabel); }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { BranchManager bm = new BranchManager(); bm.GetLabel("falseLabel", ilg); bm.GetLabel("endLabel", ilg); if (ilg.IsTemp == true) { // If this is a fake emit, then do a fake emit and return this.EmitConditional(ilg, services, bm); return; } FleeILGenerator ilgTemp = this.CreateTempFleeILGenerator(ilg); Utility.SyncFleeILGeneratorLabels(ilg, ilgTemp); // Emit fake conditional to get branch target positions this.EmitConditional(ilgTemp, services, bm); bm.ComputeBranches(); // Emit real conditional now that we have the branch target locations this.EmitConditional(ilg, services, bm); }
/// <summary> /// Emit a string concatenation /// </summary> /// <param name="ilg"></param> /// <param name="services"></param> private void EmitStringConcat(FleeILGenerator ilg, IServiceProvider services) { Type argType = default(Type); System.Reflection.MethodInfo concatMethodInfo = default(System.Reflection.MethodInfo); // Pick the most specific concat method if (this.AreBothChildrenOfType(typeof(string)) == true) { concatMethodInfo = _ourStringConcatMethodInfo; argType = typeof(string); } else { Debug.Assert(this.IsEitherChildOfType(typeof(string)), "one child must be a string"); concatMethodInfo = _ourObjectConcatMethodInfo; argType = typeof(object); } // Emit the operands and call the function MyLeftChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, argType, ilg); MyRightChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, argType, ilg); ilg.Emit(OpCodes.Call, concatMethodInfo); }
private void EmitOptimizedPower(FleeILGenerator ilg, bool emitOverflow, bool unsigned) { Int32LiteralElement right = (Int32LiteralElement)MyRightChild; if (right.Value == 0) { ilg.Emit(OpCodes.Pop); IntegralLiteralElement.EmitLoad(1, ilg); ImplicitConverter.EmitImplicitNumericConvert(typeof(Int32), MyLeftChild.ResultType, ilg); return; } if (right.Value == 1) { return; } // Start at 1 since left operand has already been emited once for (int i = 1; i <= right.Value - 1; i++) { ilg.Emit(OpCodes.Dup); } for (int i = 1; i <= right.Value - 1; i++) { this.EmitMultiply(ilg, emitOverflow, unsigned); } }
private void DoEmitLogical(FleeILGenerator ilg, IServiceProvider services) { // We have to do a 'fake' emit so we can get the positions of the labels ShortCircuitInfo info = new ShortCircuitInfo(); // Do the real emit this.EmitLogical(ilg, info, services); }
private static Label GetLabel(object key, FleeILGenerator ilg, ShortCircuitInfo info) { if (info.HasLabel(key)) { return(info.FindLabel(key)); } return(info.AddLabel(key, ilg.DefineLabel())); }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { EmitChild(_operand, _operand.ResultType, ilg, services); EmitChild(_from, _operand.ResultType, ilg, services); EmitChild(_to, _operand.ResultType, ilg, services); ilg.Emit(OpCodes.Call, _betweenMethodInfo.MakeGenericMethod(_operand.ResultType)); }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { _myCastExpression.Emit(ilg, services); Type sourceType = _myCastExpression.ResultType; Type destType = _myDestType; this.EmitCast(ilg, sourceType, destType, services); }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { base.Emit(ilg, services); _myElement.Emit(ilg, services); if (_myElement.ResultType.IsValueType == true) { EmitValueTypeLoadAddress(ilg, this.ResultType); } }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { Type resultType = this.ResultType; MyLeftChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, resultType, ilg); MyRightChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, resultType, ilg); ilg.Emit(OpCodes.Xor); }
protected void EmitOverloadedOperatorCall(MethodInfo method, FleeILGenerator ilg, IServiceProvider services) { ParameterInfo[] @params = method.GetParameters(); ParameterInfo pLeft = @params[0]; ParameterInfo pRight = @params[1]; EmitChildWithConvert(MyLeftChild, pLeft.ParameterType, ilg, services); EmitChildWithConvert(MyRightChild, pRight.ParameterType, ilg, services); ilg.Emit(OpCodes.Call, method); }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { if ((_myTargetCollectionType != null)) { this.EmitCollectionIn(ilg, services); } else { EmitCustomInMethod(ilg, services); } }
private static void EmitReferenceTypeMethodCall(MethodInfo mi, FleeILGenerator ilg) { if (mi.IsStatic == true) { ilg.Emit(OpCodes.Call, mi); } else { ilg.Emit(OpCodes.Callvirt, mi); } }
private void EmitValueTypeArrayLoad(FleeILGenerator ilg, Type elementType) { if (this.NextRequiresAddress == true) { ilg.Emit(OpCodes.Ldelema, elementType); } else { Utility.EmitArrayLoad(ilg, elementType); } }
protected static void EmitLoad(bool value, FleeILGenerator ilg) { if (value == true) { ilg.Emit(OpCodes.Ldc_I4_1); } else { ilg.Emit(OpCodes.Ldc_I4_0); } }
/// <summary> /// Emit the load of a constant field. We can't emit a ldsfld/ldfld of a constant so we have to get its value /// and then emit a ldc. /// </summary> /// <param name="fi"></param> /// <param name="ilg"></param> /// <param name="services"></param> private static void EmitLiteral(System.Reflection.FieldInfo fi, FleeILGenerator ilg, IServiceProvider services) { object value = fi.GetValue(null); Type t = value.GetType(); TypeCode code = Type.GetTypeCode(t); LiteralElement elem = default(LiteralElement); switch (code) { case TypeCode.Char: case TypeCode.Byte: case TypeCode.SByte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: elem = new Int32LiteralElement(System.Convert.ToInt32(value)); break; case TypeCode.UInt32: elem = new UInt32LiteralElement((UInt32)value); break; case TypeCode.Int64: elem = new Int64LiteralElement((Int64)value); break; case TypeCode.UInt64: elem = new UInt64LiteralElement((UInt64)value); break; case TypeCode.Double: elem = new DoubleLiteralElement((double)value); break; case TypeCode.Single: elem = new SingleLiteralElement((float)value); break; case TypeCode.Boolean: elem = new BooleanLiteralElement((bool)value); break; case TypeCode.String: elem = new StringLiteralElement((string)value); break; default: elem = null; Debug.Fail("Unsupported constant type"); break; } elem.Emit(ilg, services); }
private void EmitPower(FleeILGenerator ilg, bool emitOverflow, bool unsigned) { if (this.IsOptimizablePower == true) { this.EmitOptimizedPower(ilg, emitOverflow, unsigned); } else { ilg.Emit(OpCodes.Call, _ourPowerMethodInfo); } }
private static void EmitSuperShort(Int32 value, FleeILGenerator ilg) { OpCode ldcOpcode = default(OpCode); switch (value) { case 0: ldcOpcode = OpCodes.Ldc_I4_0; break; case 1: ldcOpcode = OpCodes.Ldc_I4_1; break; case 2: ldcOpcode = OpCodes.Ldc_I4_2; break; case 3: ldcOpcode = OpCodes.Ldc_I4_3; break; case 4: ldcOpcode = OpCodes.Ldc_I4_4; break; case 5: ldcOpcode = OpCodes.Ldc_I4_5; break; case 6: ldcOpcode = OpCodes.Ldc_I4_6; break; case 7: ldcOpcode = OpCodes.Ldc_I4_7; break; case 8: ldcOpcode = OpCodes.Ldc_I4_8; break; case -1: ldcOpcode = OpCodes.Ldc_I4_M1; break; default: Debug.Assert(false, "value out of range"); break; } ilg.Emit(ldcOpcode); }
private static void EmitBranch(AndOrElement op, FleeILGenerator ilg, Label target, ShortCircuitInfo info) { // Get the branch opcode if (op._myOperation == AndOrOperation.And) { ilg.EmitBranchFalse(target); } else { ilg.EmitBranchTrue(target); } }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { int index = ilg.GetTempLocalIndex(typeof(TimeSpan)); Utility.EmitLoadLocalAddress(ilg, index); LiteralElement.EmitLoad(_myValue.Ticks, ilg); ilg.Emit(OpCodes.Call, _timeSpanConstructor); Utility.EmitLoadLocal(ilg, index); }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { if ((MyTargetCollectionType != null)) { this.EmitCollectionIn(ilg, services); } else { // Do the real emit this.EmitListIn(ilg, services); } }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { if (object.ReferenceEquals(MyChild.ResultType, typeof(bool))) { this.EmitLogical(ilg, services); } else { MyChild.Emit(ilg, services); ilg.Emit(OpCodes.Not); } }
private void EmitConditional(FleeILGenerator ilg, IServiceProvider services, BranchManager bm) { Label falseLabel = bm.FindLabel("falseLabel"); Label endLabel = bm.FindLabel("endLabel"); // Emit the condition _myCondition.Emit(ilg, services); // On false go to the false operand if (ilg.IsTemp == true) { bm.AddBranch(ilg, falseLabel); ilg.Emit(OpCodes.Brfalse_S, falseLabel); } else if (bm.IsLongBranch(ilg, falseLabel) == false) { ilg.Emit(OpCodes.Brfalse_S, falseLabel); } else { ilg.Emit(OpCodes.Brfalse, falseLabel); } // Emit the true operand _myWhenTrue.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(_myWhenTrue.ResultType, _myResultType, ilg); // Jump to end if (ilg.IsTemp == true) { bm.AddBranch(ilg, endLabel); ilg.Emit(OpCodes.Br_S, endLabel); } else if (bm.IsLongBranch(ilg, endLabel) == false) { ilg.Emit(OpCodes.Br_S, endLabel); } else { ilg.Emit(OpCodes.Br, endLabel); } bm.MarkLabel(ilg, falseLabel); ilg.MarkLabel(falseLabel); // Emit the false operand _myWhenFalse.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(_myWhenFalse.ResultType, _myResultType, ilg); // Fall through to end bm.MarkLabel(ilg, endLabel); ilg.MarkLabel(endLabel); }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { base.Emit(ilg, services); if (this.IsArray == true) { this.EmitArrayLoad(ilg, services); } else { this.EmitIndexer(ilg, services); } }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { _myChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(_myChild.ResultType, _myResultType, ilg); ExpressionOptions options = (ExpressionOptions)services.GetService(typeof(ExpressionOptions)); if (options.IsGeneric == false) { ImplicitConverter.EmitImplicitConvert(_myResultType, typeof(object), ilg); } ilg.Emit(OpCodes.Ret); }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { int index = ilg.GetTempLocalIndex(typeof(DateTime)); Utility.EmitLoadLocalAddress(ilg, index); LiteralElement.EmitLoad(_myValue.Ticks, ilg); ConstructorInfo ci = typeof(DateTime).GetConstructor(new Type[] { typeof(long) }); ilg.Emit(OpCodes.Call, ci); Utility.EmitLoadLocal(ilg, index); }
private void EmitCast(FleeILGenerator ilg, Type sourceType, Type destType, IServiceProvider services) { MethodInfo explicitOperator = this.GetExplictOverloadedOperator(sourceType, destType); if (object.ReferenceEquals(sourceType, destType)) { // Identity cast; do nothing return; } else if ((explicitOperator != null)) { ilg.Emit(OpCodes.Call, explicitOperator); } else if (sourceType.IsEnum == true | destType.IsEnum == true) { this.EmitEnumCast(ilg, sourceType, destType, services); } else if (ImplicitConverter.EmitImplicitConvert(sourceType, destType, ilg) == true) { // Implicit numeric cast; do nothing return; } else if (IsCastableNumericType(sourceType) & IsCastableNumericType(destType)) { // Explicit numeric cast EmitExplicitNumericCast(ilg, sourceType, destType, services); } else if (sourceType.IsValueType == true) { Debug.Assert(destType.IsValueType == false, "expecting reference type"); ilg.Emit(OpCodes.Box, sourceType); } else { if (destType.IsValueType == true) { // Reference type to value type ilg.Emit(OpCodes.Unbox_Any, destType); } else { // Reference type to reference type if (destType.IsAssignableFrom(sourceType) == false) { // Only emit cast if it is an explicit cast ilg.Emit(OpCodes.Castclass, destType); } } } }