protected override bool CheckEmpty(WriterMethodBuilderContext context, GroboIL.Label notEmptyLabel) { context.LoadObjByRef(); // stack: [&obj] context.Il.Call(Type.GetProperty("HasValue").GetGetMethod()); // stack: obj.HasValue context.Il.Brtrue(notEmptyLabel); // if(obj.HasValue) goto notEmpty; return(true); }
private static void EmitNullableBne(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse) { // a.GetValueOrDefault() == b.GetValueOrDefault() && a.HasValue == b.HasValue; var type = getMethod.ReturnType; var getValueOrDefault = type.GetMethod("GetValueOrDefault", new Type[0]); var hasValue = type.GetMethod("get_HasValue"); var a = il.DeclareLocal(type); var b = il.DeclareLocal(type); il.Ldarg(0); il.Call(getMethod); il.Stloc(a); il.Ldarg(1); il.Call(getMethod); il.Stloc(b); il.Ldloca(a); il.Call(getValueOrDefault); il.Ldloca(b); il.Call(getValueOrDefault); il.Bne_Un(returnFalse); il.Ldloca(a); il.Call(hasValue); il.Ldloca(b); il.Call(hasValue); il.Bne_Un(returnFalse); }
private static void EmitSwitch <T>(TrieNode node, EmittingContext context) { var il = context.Il; var curChar = context.CurChar; int n = CalcSize(node.children.Keys.ToArray()); var defaultLabel = il.DefineLabel("default"); var labels = new GroboIL.Label[n]; for (int i = 0; i < labels.Length; ++i) { labels[i] = defaultLabel; } foreach (var key in node.children.Keys) { labels[key % n] = il.DefineLabel("case_" + key); } il.Ldloc(curChar); // stack: [curChar] il.Ldc_I4(n); // stack: [curChar, n] il.Rem(false); // stack: [curChar % n] il.Switch(labels); // goto labels[curChar % n]; stack: [] il.Br(defaultLabel); // default; foreach (var pair in node.children) { il.MarkLabel(labels[pair.Key % n]); // case_{key}; stack: [] InlineTrie <T>(pair.Value, context); } il.MarkLabel(defaultLabel); il.Ldc_I4(0); // stack: [false] il.Ret(); }
protected void SaveOrCheck(GroboIL il, EvaluationStack stack, GroboIL.Label label) { ESType[] labelStack; if (!il.labelStacks.TryGetValue(label, out labelStack)) { il.labelStacks.Add(label, stack.Reverse().ToArray()); Propogate(il, il.ilCode.GetLabelLineNumber(label), stack); } else { ESType[] merged; var comparisonResult = CompareStacks(stack.Reverse().ToArray(), labelStack, out merged); switch (comparisonResult) { case StacksComparisonResult.Equal: return; case StacksComparisonResult.Inconsistent: ThrowError(il, string.Format("Inconsistent stack for the label '{0}'{1}Stack #1: {2}{1}Stack #2: {3}", label.Name, Environment.NewLine, stack, new EvaluationStack(labelStack))); break; case StacksComparisonResult.Equivalent: il.labelStacks[label] = merged; Propogate(il, il.ilCode.GetLabelLineNumber(label), new EvaluationStack(merged)); break; } } }
// todo обобщить private static void EmitExpressionAsVoid(Expression node, EmittingContext context) { var il = context.Il; GroboIL.Label skipLabel = context.CanReturn ? il.DefineLabel("skip") : null; Type resultType; bool skipLabelUsed = ExpressionEmittersCollection.Emit(node, context, skipLabel, ResultType.Void, false, out resultType); if (skipLabelUsed) { var endLabel = il.DefineLabel("end"); if (resultType != typeof(void)) { if (!resultType.IsStruct()) { il.Pop(); } else { using (var temp = context.DeclareLocal(resultType)) il.Stloc(temp); } } il.Br(endLabel); context.MarkLabelAndSurroundWithSP(skipLabel); il.Pop(); context.MarkLabelAndSurroundWithSP(endLabel); } }
protected override bool EmitInternal(NewArrayExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { var il = context.Il; if (node.Expressions.Count != 1) { context.EmitLoadArguments(node.Expressions.ToArray()); il.Newobj(node.Type.GetConstructor(node.Expressions.Select(exp => exp.Type).ToArray())); } else { GroboIL.Label lengthIsNullLabel = context.CanReturn ? il.DefineLabel("lengthIsNull") : null; Type lengthType; var labelUsed = ExpressionEmittersCollection.Emit(node.Expressions.Single(), context, lengthIsNullLabel, out lengthType); if (lengthType != typeof(int)) { throw new InvalidOperationException("Cannot create an array with length of type '" + lengthType + "'"); } if (labelUsed && context.CanReturn) { var lengthIsNotNullLabel = il.DefineLabel("lengthIsNotNull"); il.Br(lengthIsNotNullLabel); context.MarkLabelAndSurroundWithSP(lengthIsNullLabel); il.Pop(); il.Ldc_I4(0); context.MarkLabelAndSurroundWithSP(lengthIsNotNullLabel); } il.Newarr(node.Type.GetElementType()); } resultType = node.Type; return(false); }
public void EmitReturnDefaultValue(Type type, GroboIL.Label valueIsNullLabel, GroboIL.Label valueIsNotNullLabel) { Il.Br(valueIsNotNullLabel); MarkLabelAndSurroundWithSP(valueIsNullLabel); Il.Pop(); EmitLoadDefaultValue(type); MarkLabelAndSurroundWithSP(valueIsNotNullLabel); }
public static void ReadObjectNull(GroboIL il, GroboIL.Label finishMethod, GroboIL.Local buffer, GroboIL.Local offset, GroboIL.Local typeSize) { il.Ldloc(buffer); il.Ldloc(offset); il.Ldelem(typeof(byte)); WriteOffsetAppend(il, offset, 1); il.Brtrue(finishMethod); }
private static void EmitBne(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse) { // a.Property == b.Property il.Ldarg(0); il.Call(getMethod); il.Ldarg(1); il.Call(getMethod); il.Bne_Un(returnFalse); }
protected override bool EmitInternal(BinaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { if (node.Conversion != null) { throw new NotSupportedException("Coalesce with conversion is not supported"); } // note ich: баг решарпера // ReSharper disable HeuristicUnreachableCode var left = node.Left; var right = node.Right; GroboIL il = context.Il; GroboIL.Label valueIsNullLabel = il.DefineLabel("valueIsNull"); Type leftType; bool labelUsed = ExpressionEmittersCollection.Emit(left, context, valueIsNullLabel, out leftType); if (left.Type.IsValueType) { using (var temp = context.DeclareLocal(left.Type)) { il.Stloc(temp); il.Ldloca(temp); } } labelUsed |= context.EmitNullChecking(left.Type, valueIsNullLabel); if (left.Type.IsValueType) { if (!left.Type.IsNullable()) { throw new InvalidOperationException("Type '" + left.Type + "' cannot be null"); } if (node.Type != left.Type) { context.EmitValueAccess(left.Type); } else { il.Ldobj(left.Type); } } var valueIsNotNullLabel = il.DefineLabel("valueIsNotNull"); il.Br(valueIsNotNullLabel); if (labelUsed) { context.MarkLabelAndSurroundWithSP(valueIsNullLabel); il.Pop(); } Type rightType; var result = ExpressionEmittersCollection.Emit(right, context, returnDefaultValueLabel, out rightType); context.MarkLabelAndSurroundWithSP(valueIsNotNullLabel); resultType = node.Type; return(result); // ReSharper restore HeuristicUnreachableCode }
public int MarkLabel(GroboIL.Label label, ILInstructionComment comment) { if (labelLineNumbers.ContainsKey(label)) { throw new InvalidOperationException(string.Format("The label '{0}' has already been marked", label.Name)); } labelLineNumbers.Add(label, Count); instructions.Add(new ILInstruction(InstructionKind.Label, default(OpCode), new LabelILInstructionParameter(label), comment)); return(Count++); }
public static bool Emit(Expression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { IExpressionEmitter emitter; if (!expressionEmitters.TryGetValue(node.NodeType, out emitter)) { throw new NotSupportedException("Node type '" + node.NodeType + "' is not supported"); } return(emitter.Emit(node, context, returnDefaultValueLabel, whatReturn, extend, out resultType)); }
/// <summary> /// Checks whether <c>obj</c> is empty /// </summary> /// <param name="context">Current context</param> /// <param name="notEmptyLabel">Label where to go if <c>obj</c> is not empty</param> /// <returns>true if <c>obj</c> can be empty</returns> protected virtual bool CheckEmpty(SizeCounterMethodBuilderContext context, GroboIL.Label notEmptyLabel) { if (Type.IsValueType) { return(false); } context.LoadObj(); // stack: [obj] context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty; return(true); }
private static void EmitNullableEquals(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse) { // a.Equals(b) var type = getMethod.ReturnType; var local = il.DeclareLocal(type); il.Ldarg(0); il.Call(getMethod); il.Stloc(local); il.Ldloca(local); il.Ldarg(1); il.Call(getMethod); il.Box(type); il.Call(ObjectEquals, type); il.Brfalse(returnFalse); }
private void Visit(ForStatement stmt) { var loopStartLabel = Generator.DefineLabel("loopstart"); var indexLocal = Local(stmt.VarName); var toLocal = Generator.DeclareLocal(typeof(ulong), "end"); var previousEndLabel = CurrentLoopEndLabel; var endLabel = CurrentLoopEndLabel = Generator.DefineLabel("forend"); Visit(stmt.From); Generator.Dup(); Generator.Ldobj(typeof(BitsValue)); Generator.Stloc(indexLocal); Visit(stmt.To); BitsValueToNumber(); Generator.Stloc(toLocal); BitsValueToNumber(); Generator.MarkLabel(loopStartLabel); Visit(stmt.Body); // Increment index Generator.Ldc_I8(1); Generator.Conv <ulong>(); Generator.Add(); NumberToBitsValue(); Generator.Ldobj(typeof(BitsValue)); Generator.Stloc(indexLocal); // Check index == max, if true branch to end Generator.Ldloca(indexLocal); BitsValueToNumber(); Generator.Dup(); Generator.Ldloc(toLocal); Generator.Bne_Un(loopStartLabel); Generator.MarkLabel(endLabel); CurrentLoopEndLabel = previousEndLabel; Generator.Pop(); }
protected override bool CheckEmpty(WriterMethodBuilderContext context, GroboIL.Label notEmptyLabel) { context.LoadObj(); // stack: [obj] if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects)) { context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty; } else { var emptyLabel = context.Il.DefineLabel("empty"); context.Il.Brfalse(emptyLabel); // if(obj == null) goto empty; context.LoadObj(); // stack: [obj] context.Il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashtableCountFieldNames)); // stack: [obj.Count] context.Il.Brtrue(notEmptyLabel); // if(obj.Count != 0) goto notEmpty; context.Il.MarkLabel(emptyLabel); } return(true); }
protected override bool CheckEmpty(WriterMethodBuilderContext context, GroboIL.Label notEmptyLabel) { context.LoadObj(); // stack: [obj] if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects)) { context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty; } else { var emptyLabel = context.Il.DefineLabel("empty"); context.Il.Brfalse(emptyLabel); // if(obj == null) goto empty; context.LoadObj(); // stack: [obj] context.Il.Call(Type.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public).GetGetMethod()); // stack: [&result[index], obj.Count] context.Il.Brtrue(notEmptyLabel); // if(obj.Count != 0) goto notEmpty; context.Il.MarkLabel(emptyLabel); } return(true); }
protected override bool CheckEmpty(SizeCounterMethodBuilderContext context, GroboIL.Label notEmptyLabel) { context.LoadObj(); // stack: [obj] if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects)) { context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty; } else { var emptyLabel = context.Il.DefineLabel("empty"); context.Il.Brfalse(emptyLabel); // if(obj == null) goto empty; context.LoadObj(); // stack: [obj] context.Il.Ldfld(Type.GetField("_size", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [obj.Count] context.Il.Brtrue(notEmptyLabel); // if(obj.Count != 0) goto notEmpty; context.Il.MarkLabel(emptyLabel); } return(true); }
protected override bool CheckEmpty(WriterMethodBuilderContext context, GroboIL.Label notEmptyLabel) { context.LoadObj(); // stack: [obj] if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects)) { context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty; } else { var emptyLabel = context.Il.DefineLabel("empty"); context.Il.Brfalse(emptyLabel); // if(obj == null) goto empty; context.LoadObj(); // stack: [obj] context.Il.Ldlen(); // stack: [obj.Length] context.Il.Brtrue(notEmptyLabel); // if(obj.Length != 0) goto notEmpty; context.Il.MarkLabel(emptyLabel); } return(true); }
private void Visit(WhileStatement stmt) { var previousEndLabel = CurrentLoopEndLabel; var loopStartLabel = Generator.DefineLabel("whilestart"); var loopEndLabel = CurrentLoopEndLabel = Generator.DefineLabel("whileend"); Generator.MarkLabel(loopStartLabel); Visit(stmt.Condition); BitsValueToNumber(); Generator.Brfalse(loopEndLabel); Visit(stmt.Body); Generator.Br(loopStartLabel); Generator.MarkLabel(loopEndLabel); CurrentLoopEndLabel = previousEndLabel; }
public static void WriteObjectNull(GroboIL il, GroboIL.Label finishMethod, GroboIL.Local buffer, GroboIL.Local offset, GroboIL.Local typeSize) { var _null = il.DeclareLocal(typeof(bool)); il.Ldnull(); il.Ceq(); il.Stloc(_null); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(_null); il.Stelem(typeof(byte)); WriteOffsetAppend(il, offset, 1); il.Ldloc(_null); il.Brtrue(finishMethod); }
protected override bool CheckEmpty(WriterMethodBuilderContext context, GroboIL.Label notEmptyLabel) { var il = context.Il; context.LoadObjByRef(); // stack: [ref obj] il.Ldfld(arrayField); // stack: [obj._array] if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects)) { il.Brtrue(notEmptyLabel); // if(obj._array != null) goto notEmpty; } else { var emptyLabel = il.DefineLabel("empty"); il.Brfalse(emptyLabel); // if(obj._array == null) goto empty; context.LoadObjByRef(); // stack: [ref obj] il.Ldfld(countField); // stack: [obj._count] il.Brtrue(notEmptyLabel); // if(obj._count != 0) goto notEmpty; il.MarkLabel(emptyLabel); } return(true); }
private static void EmitLoadIndex(Expression index, EmittingContext context, Type arrayType) { GroboIL il = context.Il; GroboIL.Label indexIsNullLabel = context.CanReturn ? il.DefineLabel("indexIsNull") : null; Type indexType; bool labelUsed = ExpressionEmittersCollection.Emit(index, context, indexIsNullLabel, out indexType); // stack: [array, index] if (indexType != typeof(int)) { throw new InvalidOperationException("Unable to perform array index operator to type '" + arrayType + "'"); } if (labelUsed && context.CanReturn) { var indexIsNotNullLabel = il.DefineLabel("indexIsNotNull"); il.Br(indexIsNotNullLabel); context.MarkLabelAndSurroundWithSP(indexIsNullLabel); il.Pop(); il.Ldc_I4(0); context.MarkLabelAndSurroundWithSP(indexIsNotNullLabel); } }
public static void WriteNullableType <T>(GroboIL il, GroboIL.Label finishMethod, GroboIL.Local buffer, GroboIL.Local offset) where T : struct { var _null = il.DeclareLocal(typeof(bool)); il.Call(typeof(Nullable <T>).GetProperty("HasValue").GetGetMethod()); il.Ldc_I4(0); //il.Ldnull(); il.Ceq(); il.Stloc(_null); il.Ldloc(buffer); il.Ldloc(offset); il.Ldloc(_null); il.Stelem(typeof(byte)); WriteOffsetAppend(il, offset, 1); il.Ldloc(_null); il.Brtrue(finishMethod); }
public bool EmitNullChecking(Type type, GroboIL.Label objIsNullLabel) { if (!type.IsValueType) { Il.Dup(); // stack: [obj, obj] Il.Brfalse(objIsNullLabel); // if(obj == null) goto returnDefaultValue; stack: [obj] return(true); } if (type.IsNullable()) { using (var temp = DeclareLocal(type.MakeByRefType())) { Il.Stloc(temp); Il.Ldnull(); Il.Ldloc(temp); EmitHasValueAccess(type); Il.Brfalse(objIsNullLabel); Il.Pop(); Il.Ldloc(temp); } return(true); } return(false); }
protected override bool EmitInternal(TryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { var il = context.Il; il.BeginExceptionBlock(); returnDefaultValueLabel = context.CanReturn ? il.DefineLabel("returnDefaultValue") : null; bool returnDefaultValueLabelUsed = ExpressionEmittersCollection.Emit(node.Body, context, returnDefaultValueLabel, whatReturn, extend, out resultType); EmittingContext.LocalHolder retValue = null; var doneLabel = il.DefineLabel("done"); if (resultType == typeof(void)) { if (returnDefaultValueLabelUsed) { context.MarkLabelAndSurroundWithSP(returnDefaultValueLabel); } il.Leave(doneLabel); } else { retValue = context.DeclareLocal(resultType); il.Stloc(retValue); il.Leave(doneLabel); if (returnDefaultValueLabelUsed) { context.MarkLabelAndSurroundWithSP(returnDefaultValueLabel); if (resultType.IsValueType) { il.Ldloca(retValue); il.Initobj(resultType); } else { il.Ldnull(); il.Stloc(retValue); } il.Leave(doneLabel); } } foreach (var catchBlock in node.Handlers) { bool disposeVariable = false; var variable = catchBlock.Variable; if (catchBlock.Filter == null) { il.BeginCatchBlock(catchBlock.Test); if (variable == null) { il.Pop(); } else { // todo вызвать ф-цию из AssignExpressionEmitter var index = Array.IndexOf(context.Parameters, variable); if (index >= 0) { il.Starg(index); } else { GroboIL.Local local; if (!context.VariablesToLocals.TryGetValue(variable, out local)) { local = context.DeclareLocal(variable.Type); context.VariablesToLocals.Add(variable, local); context.Variables.Push(variable); disposeVariable = true; } il.Stloc(local); } } } else { il.BeginExceptFilterBlock(); il.Isinst(catchBlock.Test); il.Dup(); var rightTypeLabel = il.DefineLabel("rightType"); il.Brtrue(rightTypeLabel); il.Pop(); il.Ldc_I4(0); var endFilterLabel = il.DefineLabel("endFilter"); il.Br(endFilterLabel); context.MarkLabelAndSurroundWithSP(rightTypeLabel); if (variable == null) { il.Pop(); } else { // todo вызвать ф-цию из AssignExpressionEmitter var index = Array.IndexOf(context.Parameters, variable); if (index >= 0) { il.Starg(index); } else { GroboIL.Local local; if (!context.VariablesToLocals.TryGetValue(variable, out local)) { local = string.IsNullOrEmpty(variable.Name) ? context.Il.DeclareLocal(variable.Type) : context.Il.DeclareLocal(variable.Type, variable.Name, appendUniquePrefix: false); if (context.DebugInfoGenerator != null) { local.SetLocalSymInfo(local.Name); } context.VariablesToLocals.Add(variable, local); context.Variables.Push(variable); disposeVariable = true; } il.Stloc(local); } } GroboIL.Label returnFalseLabel = context.CanReturn ? il.DefineLabel("returnFalse") : null; Type filterResultType; bool returnFalseLabelUsed = ExpressionEmittersCollection.Emit(catchBlock.Filter, context, returnFalseLabel, out filterResultType); if (returnFalseLabelUsed) { il.Br(endFilterLabel); context.MarkLabelAndSurroundWithSP(returnFalseLabel); il.Pop(); il.Ldc_I4(0); } context.MarkLabelAndSurroundWithSP(endFilterLabel); il.BeginCatchBlock(null); il.Pop(); } context.EmitLoadArguments(catchBlock.Body); if (catchBlock.Body.Type != typeof(void)) { il.Stloc(retValue); } if (disposeVariable) { context.VariablesToLocals.Remove(variable); context.Variables.Pop(); } } if (node.Fault != null) { il.BeginFaultBlock(); EmitExpressionAsVoid(node.Fault, context); } if (node.Finally != null) { il.BeginFinallyBlock(); EmitExpressionAsVoid(node.Finally, context); } il.EndExceptionBlock(); context.MarkLabelAndSurroundWithSP(doneLabel); if (retValue != null) { il.Ldloc(retValue); retValue.Dispose(); } return(false); }
protected override bool EmitInternal(UnaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { Type operandType; var result = ExpressionEmittersCollection.Emit(node.Operand, context, returnDefaultValueLabel, ResultType.Value, extend, out operandType); GroboIL il = context.Il; if (node.NodeType == ExpressionType.IsTrue || node.NodeType == ExpressionType.IsFalse) { if (!operandType.IsNullable()) { if (node.Method != null) { il.Call(node.Method); } else if (operandType == typeof(bool)) { if (node.NodeType == ExpressionType.IsFalse) { il.Ldc_I4(1); il.Xor(); } } else { throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a type '" + operandType + "'"); } } else { using (var temp = context.DeclareLocal(operandType)) { il.Stloc(temp); il.Ldloca(temp); context.EmitHasValueAccess(operandType); var returnFalseLabel = il.DefineLabel("returnFalse"); il.Brfalse(returnFalseLabel); il.Ldloca(temp); context.EmitValueAccess(operandType); if (node.Method != null) { il.Call(node.Method); } else if (operandType == typeof(bool?)) { if (node.NodeType == ExpressionType.IsFalse) { il.Ldc_I4(1); il.Xor(); } } else { throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a type '" + operandType + "'"); } var doneLabel = il.DefineLabel("done"); il.Br(doneLabel); context.MarkLabelAndSurroundWithSP(returnFalseLabel); il.Ldc_I4(0); context.MarkLabelAndSurroundWithSP(doneLabel); } } } else { if (!operandType.IsNullable()) { if (node.Method != null) { il.Call(node.Method); } else { if (operandType.IsStruct()) { throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a struct '" + operandType + "'"); } switch (node.NodeType) { case ExpressionType.UnaryPlus: break; case ExpressionType.Negate: il.Neg(); break; case ExpressionType.NegateChecked: using (var temp = context.DeclareLocal(operandType)) { il.Stloc(temp); il.Ldc_I4(0); context.EmitConvert(typeof(int), operandType); il.Ldloc(temp); il.Sub_Ovf(operandType.Unsigned()); } break; case ExpressionType.Increment: il.Ldc_I4(1); context.EmitConvert(typeof(int), operandType); il.Add(); break; case ExpressionType.Decrement: il.Ldc_I4(1); context.EmitConvert(typeof(int), operandType); il.Sub(); break; case ExpressionType.OnesComplement: il.Not(); break; default: throw new InvalidOperationException("Node type '" + node.NodeType + "' invalid at this point"); } } } else { using (var temp = context.DeclareLocal(operandType)) { il.Stloc(temp); il.Ldloca(temp); context.EmitHasValueAccess(operandType); var returnNullLabel = il.DefineLabel("returnLabel"); il.Brfalse(returnNullLabel); Type argumentType = operandType.GetGenericArguments()[0]; if (node.Method != null) { il.Ldloca(temp); context.EmitValueAccess(operandType); il.Call(node.Method); } else { switch (node.NodeType) { case ExpressionType.UnaryPlus: il.Ldloca(temp); context.EmitValueAccess(operandType); break; case ExpressionType.Negate: il.Ldloca(temp); context.EmitValueAccess(operandType); il.Neg(); break; case ExpressionType.NegateChecked: il.Ldc_I4(0); context.EmitConvert(typeof(int), argumentType); il.Ldloca(temp); context.EmitValueAccess(operandType); il.Sub_Ovf(argumentType.Unsigned()); break; case ExpressionType.Increment: il.Ldloca(temp); context.EmitValueAccess(operandType); il.Ldc_I4(1); context.EmitConvert(typeof(int), argumentType); il.Add(); break; case ExpressionType.Decrement: il.Ldloca(temp); context.EmitValueAccess(operandType); il.Ldc_I4(1); context.EmitConvert(typeof(int), argumentType); il.Sub(); break; case ExpressionType.OnesComplement: il.Ldloca(temp); context.EmitValueAccess(operandType); il.Not(); break; default: throw new InvalidOperationException("Node type '" + node.NodeType + "' invalid at this point"); } } il.Newobj(operandType.GetConstructor(new[] { argumentType })); var doneLabel = il.DefineLabel("done"); il.Br(doneLabel); context.MarkLabelAndSurroundWithSP(returnNullLabel); context.EmitLoadDefaultValue(operandType); context.MarkLabelAndSurroundWithSP(doneLabel); } } } resultType = node.Type; return(result); }
public int GetLabelLineNumber(GroboIL.Label label) { int result; return(labelLineNumbers.TryGetValue(label, out result) ? result : -1); }
private static void EmitStatic(GroboIL il, MethodInfo getMethod, MethodInfo staticMethod, GroboIL.Label returnFalse) { // Equals(a.Property, b.Property) il.Ldarg(0); il.Call(getMethod); il.Ldarg(1); il.Call(getMethod); il.Call(staticMethod); il.Brfalse(returnFalse); }
protected override bool EmitInternal(LambdaExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType) { var parameterTypes = node.Parameters.Select(parameter => parameter.Type).ToArray(); Type[] constantTypes; var compiledLambda = CompileAndLoadConstants(node, context, out constantTypes); var il = context.Il; Type rawSubLambdaType; if (!Extensions.IsMono) { context.LoadCompiledLambdaPointer(compiledLambda); rawSubLambdaType = typeof(IntPtr); } else { rawSubLambdaType = Extensions.GetDelegateType(constantTypes.Concat(parameterTypes).ToArray(), node.ReturnType); context.LoadCompiledLambda(compiledLambda); il.Castclass(rawSubLambdaType); } resultType = Extensions.GetDelegateType(parameterTypes, node.ReturnType); var types = constantTypes.Concat(new[] { rawSubLambdaType }).ToArray(); var module = (ModuleBuilder)(context.TypeBuilder == null ? null : context.TypeBuilder.Module); var subLambdaInvoker = DynamicMethodInvokerBuilder.BuildDynamicMethodInvoker(module, constantTypes, node.ReturnType, parameterTypes); il.Newobj(subLambdaInvoker.GetConstructor(types)); il.Ldftn(subLambdaInvoker.GetMethod("Invoke")); il.Newobj(resultType.GetConstructor(new[] { typeof(object), typeof(IntPtr) })); return(false); }