private AstNode EmitMultiDimensionalArrayInitializer() { List <int> dimensions = null; MethodInfo arraySetMethod = null; AstNodeDecorator nodeDecorator = null; var arrayCreation = Node.Parent as ArrayCreateExpression; var specifier = arrayCreation.AdditionalArraySpecifiers.First(); Type[] types = new Type[specifier.Dimensions + 1]; Type[] constructorTypes = new Type[specifier.Dimensions]; Enumerable.Range(0, specifier.Dimensions) .ForEach(i => types[i] = constructorTypes[i] = TypeSystem.Int); types[types.Length - 1] = _typeToEmit; arraySetMethod = Type.GetMethod("Set", types); dimensions = BuildDimsnsions(arrayCreation); dimensions.ForEach(d => ILGenerator.EmitPushInteger(d)); ILGenerator.Emit(OpCodes.Newobj, Type.GetConstructor(constructorTypes)); ILGenerator.EmitStoreLocal(_localBuilder); BuildIndexesRecursively(Node, new List <int>()).ForEach((tuple, i) => { ILGenerator.EmitLoadLocal(_localBuilder); tuple.Item2.ForEach(index => ILGenerator.EmitPushInteger(index)); nodeDecorator = tuple.Item1.AcceptVisitor(ILGenerator, Visitor); ILGenerator.EmitCastIfNeeded(nodeDecorator.Type, _typeToEmit); ILGenerator.Emit(OpCodes.Call, arraySetMethod); }); ILGenerator.EmitLoadLocal(_localBuilder, true); return(new AstNodeDecorator(Node, Type)); }
private void EmitElementRef(AstNode node, int index) { AstNodeDecorator nodeDecorator = null; ILGenerator.EmitLoadLocal(_localBuilder); ILGenerator.EmitPushInteger(index); nodeDecorator = node.AcceptVisitor(ILGenerator, Visitor); ILGenerator.EmitCastIfNeeded(nodeDecorator.Type, _typeToEmit); ILGenerator.Emit(OpCodes.Stelem_Ref); }
private void EmitPrimitiveElement(AstNode node, int index) { AstNodeDecorator astDecorator = null; ILGenerator.EmitLoadLocal(_localBuilder); ILGenerator.EmitPushInteger(index); ILGenerator.EmitLoadElementArrayIfNeeded(_typeToEmit); astDecorator = node.AcceptVisitor(ILGenerator, Visitor); ILGenerator.EmitStoreElementByType(astDecorator.Type); }
public override AstNode VisitInvocationExpression(InvocationExpression invocationExpression, ILGenerator data) { var localBuilder = Locals[Locals.Count - 1]; invocationExpression.Arguments.ForEach((arg, i) => { AstNodeDecorator decorator = null; ILGenerator.EmitLoadLocal(localBuilder); ILGenerator.EmitPushInteger(i); decorator = arg.AcceptVisitor(data, this); ILGenerator.EmitCastIfNeeded(decorator.Type, TypeSystem.Object); ILGenerator.Emit(OpCodes.Stelem_Ref); }); return(invocationExpression); }
public override AstNode Emit() { var falseLabel = ILGenerator.DefineLabel(); var trueLabel = ILGenerator.DefineLabel(); AstNodeDecorator falseExpressionDecorator = null; Node.Condition.AcceptVisitor(ILGenerator, Visitor); ILGenerator.Emit(OpCodes.Brtrue_S, trueLabel); falseExpressionDecorator = Node.FalseExpression.AcceptVisitor(ILGenerator, Visitor); ILGenerator.EmitCastIfNeeded(falseExpressionDecorator.Type, Type); ILGenerator.Emit(OpCodes.Br_S, falseLabel); ILGenerator.MarkLabel(trueLabel); Node.TrueExpression.AcceptVisitor(ILGenerator, Visitor); ILGenerator.MarkLabel(falseLabel); return(base.Emit()); }
private AstNode EmitNewObjectInitializer() { Type parameterType = null; bool requiresPop = false; MethodInfo methodInfo = null; AstNodeDecorator nodeDecorator = null; var callOpCode = _isPrimitive ? OpCodes.Call : OpCodes.Callvirt; var firstChild = Node.Elements.First(); var methodReference = Node.Elements.First().Annotation <MethodReference>(); if (methodReference == null) { Cil.Instruction instruction; InstructionsIndexer.TryGetCallInstruction(firstChild, out instruction); methodReference = instruction.Operand as MethodReference; } methodInfo = methodReference.GetActualMethod <MethodInfo>(); parameterType = methodInfo.GetParameters()[0].ParameterType; requiresPop = !methodInfo.ReturnType.Equals(TypeSystem.Void); Node.Elements.ForEach((node, i) => { ILGenerator.EmitLoadLocal(_localBuilder); nodeDecorator = node.AcceptVisitor(ILGenerator, Visitor); ILGenerator.EmitCastIfNeeded(nodeDecorator.Type, parameterType); ILGenerator.Emit(callOpCode, methodInfo); if (requiresPop) { ILGenerator.Emit(OpCodes.Pop); } }); ILGenerator.EmitLoadLocal(_localBuilder, true); return(new AstNodeDecorator(Node, Type)); }
public void EmitBinaryExpression() { AstNodeDecorator node = null; var checkedUnchecked = Node.Annotations.First(); var isChecked = checkedUnchecked == AddCheckedBlocks.CheckedAnnotation; var leftDecision = _promotionDecisions.LeftType; var rightDecision = _promotionDecisions.RightType; node = Node.Left.AcceptVisitor(ILGenerator, Visitor); if (!node.Type.Equals(leftDecision.To) && leftDecision.IsPromoted) { ILGenerator.EmitConversion(leftDecision.To, leftDecision.From); } if (Node.Operator != BinaryOperatorType.ConditionalAnd && Node.Operator != BinaryOperatorType.ConditionalOr && Node.Operator != BinaryOperatorType.NullCoalescing) { node = Node.Right.AcceptVisitor(ILGenerator, Visitor); if (!(Node.Right is NullReferenceExpression) && !node.Type.Equals(rightDecision.To) && rightDecision.IsPromoted) { ILGenerator.EmitConversion(rightDecision.To, rightDecision.From); } } switch (Node.Operator) { case BinaryOperatorType.BitwiseAnd: ILGenerator.Emit(OpCodes.And); break; case BinaryOperatorType.BitwiseOr: ILGenerator.Emit(OpCodes.Or); break; case BinaryOperatorType.ConditionalAnd: { var falseLabel = ILGenerator.DefineLabel(); var trueLabel = ILGenerator.DefineLabel(); ILGenerator.Emit(OpCodes.Brfalse_S, falseLabel); Node.Right.AcceptVisitor(Visitor, ILGenerator); ILGenerator.Emit(OpCodes.Br_S, trueLabel); ILGenerator.MarkLabel(falseLabel); ILGenerator.Emit(OpCodes.Ldc_I4_0); ILGenerator.MarkLabel(trueLabel); break; } case BinaryOperatorType.ConditionalOr: { var trueLabel = ILGenerator.DefineLabel(); var falseLabel = ILGenerator.DefineLabel(); ILGenerator.Emit(OpCodes.Brtrue_S, trueLabel); Node.Right.AcceptVisitor(Visitor, ILGenerator); ILGenerator.Emit(OpCodes.Br_S, falseLabel); ILGenerator.MarkLabel(trueLabel); ILGenerator.Emit(OpCodes.Ldc_I4_1); ILGenerator.MarkLabel(falseLabel); break; } case BinaryOperatorType.ExclusiveOr: ILGenerator.Emit(OpCodes.Xor); break; case BinaryOperatorType.Equality: ILGenerator.Emit(OpCodes.Ceq); break; case BinaryOperatorType.InEquality: ILGenerator.Emit(OpCodes.Ceq); ILGenerator.Emit(OpCodes.Ldc_I4_0); ILGenerator.Emit(OpCodes.Ceq); break; case BinaryOperatorType.LessThan: ILGenerator.EmitLessThen(_leftType); break; case BinaryOperatorType.LessThanOrEqual: ILGenerator.EmitLessThanOrEqual(_leftType, _rightType); break; case BinaryOperatorType.GreaterThan: ILGenerator.EmitGreaterThan(_leftType); break; case BinaryOperatorType.GreaterThanOrEqual: ILGenerator.EmitGreaterThanOrEqual(_leftType, _rightType); break; case BinaryOperatorType.Add: ILGenerator.EmitAddition(_leftType, _rightType, isChecked); if (IsPreCondition(Node.Right)) { ILGenerator.Emit(OpCodes.Dup); _storeArgumentShouldBeEmitted = true; } break; case BinaryOperatorType.Subtract: { if (isChecked && IsNegation(Node.Left)) { if (rightDecision.IsPromoted) { ILGenerator.EmitConversion(rightDecision.To, rightDecision.From); ILGenerator.Emit(OpCodes.Sub_Ovf); } } else { ILGenerator.EmitSubtraction(_leftType, _rightType, isChecked); if (IsPreCondition(Node.Right)) { ILGenerator.Emit(OpCodes.Dup); _storeArgumentShouldBeEmitted = true; } } break; } case BinaryOperatorType.Multiply: ILGenerator.EmitMultiplication(_leftType, _rightType, isChecked); break; case BinaryOperatorType.Divide: ILGenerator.EmitDivision(_leftType); break; case BinaryOperatorType.Modulus: ILGenerator.EmitModulu(_leftType); break; case BinaryOperatorType.ShiftLeft: case BinaryOperatorType.ShiftRight: { int result = _leftType.Equals(TypeSystem.Int) ? 0x1f : 0x3f; ILGenerator.Emit(OpCodes.Ldc_I4_S, result); ILGenerator.Emit(OpCodes.And); if (Node.Operator == BinaryOperatorType.ShiftRight) { ILGenerator.EmitRightShift(_leftType); } else { ILGenerator.Emit(OpCodes.Shl); } break; } case BinaryOperatorType.NullCoalescing: { var trueLabel = ILGenerator.DefineLabel(); ILGenerator.Emit(OpCodes.Dup); ILGenerator.Emit(OpCodes.Brtrue_S, trueLabel); ILGenerator.Emit(OpCodes.Pop); Node.Right.AcceptVisitor(Visitor, ILGenerator); ILGenerator.MarkLabel(trueLabel); break; } } if (_storeArgumentShouldBeEmitted) { var memberReference = Node.Left as MemberReferenceExpression; EmitStoreByArgumentIfNeeded(memberReference); } }