Example #1
0
 // for prefetching
 internal FieldDefinition(FieldReference fref)
     : this()
 {
     Owner = fref.Owner as ClassDefinition;
     Type = fref.Type;
     Name = fref.Name;
 }
        private object ConvertFieldReference(FieldReference fieldRef, AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            // We could also handle access to fields in the generated class; but see the coverage comment above.
            // It would require to map fields in the MapFile as well, at least for those in the __generated
            // class. I don't think its worth it.
            if (fieldRef.Owner.Descriptor == _map.GeneratedType.DexSignature)
            {
                throw new CompilerCacheResolveException("unable to resolve fields in __generated: " + fieldRef);
            }

            // I don't believe we have to protect ourselfs from field name changes.
            // Except for obfuscation, there is no reason to rename fields. They are
            // independent of other classes not in their class hierachy (of which we know
            // that it can not have changed)

            var classRef = ConvertClassReference(fieldRef.Owner, compiler, targetPackage);
            var typeRef  = ConvertTypeReference(fieldRef.Type, compiler, targetPackage);

            return(new FieldReference(classRef, fieldRef.Name, typeRef));
        }
        private object ConvertFieldReference(FieldReference fieldRef, AssemblyCompiler compiler, DexTargetPackage targetPackage)
        {
            // We could also handle access to fields in the generated class; but see the coverage comment above.
            // It would require to map fields in the MapFile as well, at least for those in the __generated 
            // class. I don't think its worth it.
            if (fieldRef.Owner.Descriptor == _map.GeneratedType.DexSignature)
                throw new CompilerCacheResolveException("unable to resolve fields in __generated: " + fieldRef);

            // I don't believe we have to protect ourselfs from field name changes. 
            // Except for obfuscation, there is no reason to rename fields. They are 
            // independent of other classes not in their class hierachy (of which we know
            // that it can not have changed)

            var classRef = ConvertClassReference(fieldRef.Owner, compiler, targetPackage);
            var typeRef = ConvertTypeReference(fieldRef.Type, compiler, targetPackage);

            return new FieldReference(classRef, fieldRef.Name, typeRef);
        }
Example #4
0
 /// <summary>
 /// Is other equal to this?
 /// </summary>
 public bool Equals(FieldReference other)
 {
     return (other != null) && Owner.Equals(other.Owner) && Name.Equals(other.Name) && Type.Equals(other.Type);
 }
        /// <summary>
        /// Create the body of the invoke method.
        /// </summary>
        private static MethodBody CreateInvokeBody(ISourceLocation sequencePoint, AssemblyCompiler compiler, DexTargetPackage targetPackage, XMethodDefinition calledMethod, XMethodDefinition invokeMethod, Prototype invokePrototype, Prototype calledMethodPrototype, FieldDefinition instanceField, ClassReference delegateClass)
        {
            var body = new MethodBody(null);
            var rthis = body.AllocateRegister(RCategory.Argument, RType.Object);
            foreach (var p in invokePrototype.Parameters)
            {
                if (p.Type.IsWide())
                {
                    body.AllocateWideRegister(RCategory.Argument);
                }
                else
                {
                    var type = (p.Type is PrimitiveType) ? RType.Value : RType.Object;
                    body.AllocateRegister(RCategory.Argument, type);
                }
            }
            var incomingMethodArgs = body.Registers.ToArray();

            // Create code
            var ins = body.Instructions;
            Register instance = null;
            if (!calledMethod.IsStatic)
            {
                // load instance
                instance = body.AllocateRegister(RCategory.Temp, RType.Object);
                ins.Add(new Instruction(RCode.Iget_object, instance, rthis) { Operand = instanceField });
            }
            // Invoke
            var calledMethodRef = calledMethod.GetReference(targetPackage);
            var inputArgs = calledMethod.IsStatic ? incomingMethodArgs.Skip(1).ToArray() : incomingMethodArgs;
            
            // Cast arguments (if needed)
            var outputArgs = new List<Register>();
            if (!calledMethod.IsStatic)
            {
                outputArgs.Add(instance);
            }
            var parameterIndex = 0;
            for (var i = calledMethod.IsStatic ? 0 : 1; i < inputArgs.Length; )
            {
                var invokeType = invokePrototype.Parameters[parameterIndex].Type;
                var inputIsWide = invokeType.IsWide();
                var calledType = calledMethodPrototype.Parameters[parameterIndex].Type;
                if (!invokeType.Equals(calledType))
                {
                    // Add cast / unbox
                    var source = inputIsWide
                                     ? new RegisterSpec(inputArgs[i], inputArgs[i + 1], invokeType)
                                     : new RegisterSpec(inputArgs[i], null, invokeType);
                    var tmp = ins.Unbox(sequencePoint, source, calledMethod.Parameters[parameterIndex].ParameterType, compiler, targetPackage, body);
                    outputArgs.Add(tmp.Result.Register);
                    if (calledType.IsWide())
                    {
                        outputArgs.Add(tmp.Result.Register2);
                    }
                }
                else
                {
                    outputArgs.Add(inputArgs[i]);
                    if (calledType.IsWide())
                    {
                        outputArgs.Add(inputArgs[i + 1]);
                    }
                }
                i += inputIsWide ? 2 : 1;
                parameterIndex++;
            }

            // Actual call
            ins.Add(new Instruction(calledMethod.Invoke(calledMethod, null), calledMethodRef, outputArgs.ToArray()));

            // Collect return value
            var invokeReturnType = invokePrototype.ReturnType;
            var calledReturnType = calledMethodPrototype.ReturnType;
            var needsBoxing = !invokeReturnType.Equals(calledReturnType);
            Instruction returnInstruction;

            if (calledReturnType.IsWide())
            {
                var r = body.AllocateWideRegister(RCategory.Temp);
                ins.Add(new Instruction(RCode.Move_result_wide, r.Item1));
                if (needsBoxing)
                {
                    // Box
                    var source = new RegisterSpec(r.Item1, r.Item2, calledReturnType);
                    var tmp = ins.Box(sequencePoint, source, calledMethod.ReturnType, targetPackage, body);
                    returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register);
                }
                else
                {
                    // Return wide
                    returnInstruction = new Instruction(RCode.Return_wide, r.Item1);
                }
            }
            else if (calledMethod.ReturnType.IsVoid())
            {
                // Void return
                returnInstruction = new Instruction(RCode.Return_void);
            }
            else if (calledReturnType is PrimitiveType)
            {
                // Single register return
                var r = body.AllocateRegister(RCategory.Temp, RType.Value);
                ins.Add(new Instruction(RCode.Move_result, r));
                if (needsBoxing)
                {
                    // Box
                    var source = new RegisterSpec(r, null, invokeReturnType);
                    var tmp = ins.Box(sequencePoint, source, calledMethod.ReturnType, targetPackage, body);
                    returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register);
                }
                else
                {
                    // Return 
                    returnInstruction = new Instruction(RCode.Return, r);
                }
            }
            else
            {
                var r = body.AllocateRegister(RCategory.Temp, RType.Object);
                ins.Add(new Instruction(RCode.Move_result_object, r));
                if (needsBoxing)
                {
                    // Box
                    var source = new RegisterSpec(r, null, invokeReturnType);
                    var tmp = ins.Box(sequencePoint, source, invokeMethod.ReturnType, targetPackage, body);
                    returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register);
                }
                else
                {
                    // Return 
                    returnInstruction = new Instruction(RCode.Return_object, r);
                }
            }

            // Call next delegate (if any)
            var next = body.AllocateRegister(RCategory.Temp, RType.Object);
            var multicastDelegateType = new ClassReference(targetPackage.NameConverter.GetConvertedFullName("System.MulticastDelegate"));
            var nextReference = new FieldReference(multicastDelegateType, "next", multicastDelegateType);
            ins.Add(new Instruction(RCode.Iget_object, nextReference, new[] { next, rthis })); // load this.next
            var afterCallNext = new Instruction(RCode.Nop);
            ins.Add(new Instruction(RCode.If_eqz, afterCallNext, new[] { next })); // if next == null, continue
            ins.Add(new Instruction(RCode.Check_cast, delegateClass, new[] { next }));
            var nextInvokeMethod = new MethodReference(delegateClass, "Invoke", invokePrototype);
            var nextInvokeArgs = new[] { next }.Concat(incomingMethodArgs.Skip(1)).ToArray();
            ins.Add(new Instruction(RCode.Invoke_virtual, nextInvokeMethod, nextInvokeArgs));
            ins.Add(afterCallNext);

            // Add return instructions
            ins.Add(returnInstruction);

            return body;
        }
        /// <summary>
        /// Generate code for the given expression.
        /// </summary>
        private RLRange VisitExpression(AstExpression node, List<RLRange> args, AstNode parent)
        {

            switch (node.Code)
            {
                case AstCode.Nop:
                case AstCode.Endfinally:
                case AstCode.Endfilter:
                    return new RLRange(this.Add(node.SourceLocation, RCode.Nop), null);
                case AstCode.Ldexception:
                    throw new InvalidOperationException("ldexception should not occur");
                case AstCode.Dup:
                    return new RLRange(this.Add(node.SourceLocation, RCode.Nop), args[0].Result);

                    #region Constants

                case AstCode.Ldc_I4:
                case AstCode.Ldc_R4:
                    {
                        var type = node.GetResultType();
                        var converter = type.ConstValueConverter(true);
                        var value = converter(node.Operand);
                        var r = frame.AllocateTemp(type.IsFloat() ? PrimitiveType.Float : PrimitiveType.Int);
                        var first = this.Add(node.SourceLocation, RCode.Const, value, r);
                        return new RLRange(first, r);
                    }
                case AstCode.Ldc_I8:
                case AstCode.Ldc_R8:
                    {
                        var type = node.GetResultType();
                        var converter = type.ConstValueConverter(false);
                        var value = converter(node.Operand);
                        var r = frame.AllocateTemp(type.IsDouble() ? PrimitiveType.Double : PrimitiveType.Long);
                        return new RLRange(args, this.Add(node.SourceLocation, RCode.Const_wide, value, r), r);
                    }
                case AstCode.Ldnull:
                    {
                        //Debugger.Launch();
                        var r = frame.AllocateTemp(node.GetResultType().GetReference(targetPackage));
                        return new RLRange(args, this.Add(node.SourceLocation, RCode.Const, 0, r), r);
                    }
                case AstCode.Ldstr:
                    {
                        var str = (string) node.Operand;
                        var r = frame.AllocateTemp(node.GetResultType().GetReference(targetPackage));
                        return new RLRange(args, this.Add(node.SourceLocation, RCode.Const_string, str, r), r);
                    }
                case AstCode.DefaultValue:
                    {
                        var type = (XTypeReference) node.Operand;
                        if (type.IsPrimitive)
                        {
                            var r = frame.AllocateTemp(type.GetReference(targetPackage));
                            return new RLRange(args, this.Add(node.SourceLocation, node.Arguments[0].Const(), 0, r), r);
                        }
                        if (type.IsEnum())
                        {
                            var r = frame.AllocateTemp(type.GetReference(targetPackage));
                            var denumType = type.GetClassReference(targetPackage);
                            var defaultField = new FieldReference(denumType, NameConstants.Enum.DefaultFieldName, denumType);
                            return new RLRange(this.Add(node.SourceLocation, RCode.Sget_object, defaultField, r), r);
                        }
                        else
                        {
                            var r = frame.AllocateTemp(type.GetReference(targetPackage));
                            return new RLRange(args, this.Add(node.SourceLocation, RCode.Const, 0, r), r);
                        }
                    }
                case AstCode.TypeOf:
                    {
                        var type = (XTypeReference) node.Operand;
                        var dtype = type.IsVoid() ? PrimitiveType.Void : type.GetReference(targetPackage);
                        var typeReg = frame.AllocateTemp(FrameworkReferences.Class);
                        var first = this.Add(node.SourceLocation, RCode.Const_class, dtype, typeReg);
                        return new RLRange(first, typeReg);
                    }
                case AstCode.BoxedTypeOf:
                    {
                        var type = (XTypeReference) node.Operand;
                        var typeReg = frame.AllocateTemp(FrameworkReferences.Class);
                        var first = this.Add(node.SourceLocation, RCode.Const_class, type.GetBoxedType(), typeReg);
                        return new RLRange(first, typeReg);
                    }

                    #endregion

                    #region Arithmetic

                case AstCode.Neg:
                    {
                        var tmp = this.EnsureTemp(node.SourceLocation, args[0].Result, frame);
                        return new RLRange(args, this.Add(node.SourceLocation, node.Neg(), tmp.Result, tmp.Result),
                                           tmp.Result);
                    }
                case AstCode.Not:
                    {
                        var tmp = this.EnsureTemp(node.SourceLocation, args[0].Result, frame);
                        return new RLRange(args, this.Add(node.SourceLocation, node.Not(), tmp.Result, tmp.Result),
                                           tmp.Result);
                    }
                case AstCode.Add:
                    {
                        if (args[0].Result.Register.IsTemp)
                            return new RLRange(args,
                                               this.Add(node.SourceLocation, node.Add2Addr(), args[0].Result,
                                                        args[1].Result), args[0].Result);
                        var tmp = frame.AllocateTemp(args[0].Result.Type);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Add(), tmp, args[0].Result, args[1].Result),
                                           tmp);
                    }
                case AstCode.Add_Ovf:
                    {
                        var isLong = node.Arguments[0].IsInt64();
                        var addMethods =
                            compiler.GetDot42InternalType("Checked").Resolve().Methods.Where(x => x.Name == "Add");
                        var ilMethod = addMethods.First(x => isLong ? x.ReturnType.IsInt64() : x.ReturnType.IsInt32());
                        var method = ilMethod.GetReference(targetPackage);
                        var tmp = this.EnsureTemp(node.SourceLocation, args[0].Result, frame);
                        var registers = tmp.Result.Registers.Concat(args[1].Result.Registers);
                        this.Add(node.SourceLocation, RCode.Invoke_static, method, registers);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation,
                                                    isLong ? RCode.Move_result_wide : RCode.Move_result, tmp.Result),
                                           tmp.Result);
                    }
                case AstCode.CompoundAdd:
                    {
                        var localReg = frame.GetArgument((AstVariable) node.Operand);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Add2Addr(), localReg, args[0].Result),
                                           localReg);
                    }
                case AstCode.Sub:
                    {
                        if (args[0].Result.Register.IsTemp)
                            return new RLRange(args,
                                               this.Add(node.SourceLocation, node.Sub2Addr(), args[0].Result,
                                                        args[1].Result), args[0].Result);
                        var tmp = frame.AllocateTemp(args[0].Result.Type);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Sub(), tmp, args[0].Result, args[1].Result),
                                           tmp);
                    }
                case AstCode.Sub_Ovf:
                    {
                        var isLong = node.Arguments[0].IsInt64();
                        var addMethods =
                            compiler.GetDot42InternalType("Checked").Resolve().Methods.Where(x => x.Name == "Sub");
                        var ilMethod = addMethods.First(x => isLong ? x.ReturnType.IsInt64() : x.ReturnType.IsInt32());
                        var method = ilMethod.GetReference(targetPackage);
                        var tmp = this.EnsureTemp(node.SourceLocation, args[0].Result, frame);
                        var registers = tmp.Result.Registers.Concat(args[1].Result.Registers);
                        this.Add(node.SourceLocation, RCode.Invoke_static, method, registers);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation,
                                                    isLong ? RCode.Move_result_wide : RCode.Move_result, tmp.Result),
                                           tmp.Result);
                    }
                case AstCode.CompoundSub:
                    {
                        var localReg = frame.GetArgument((AstVariable) node.Operand);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Sub2Addr(), localReg, args[0].Result),
                                           localReg);
                    }
                case AstCode.Mul:
                    {
                        if (args[0].Result.Register.IsTemp)
                            return new RLRange(args,
                                               this.Add(node.SourceLocation, node.Mul2Addr(), args[0].Result,
                                                        args[1].Result), args[0].Result);
                        var tmp = frame.AllocateTemp(args[0].Result.Type);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Mul(), tmp, args[0].Result, args[1].Result),
                                           tmp);
                    }
                case AstCode.Mul_Ovf:
                    {
                        var isLong = node.Arguments[0].IsInt64();
                        var addMethods =
                            compiler.GetDot42InternalType("Checked").Resolve().Methods.Where(x => x.Name == "Mul");
                        var ilMethod = addMethods.First(x => isLong ? x.ReturnType.IsInt64() : x.ReturnType.IsInt32());
                        var method = ilMethod.GetReference(targetPackage);
                        var tmp = this.EnsureTemp(node.SourceLocation, args[0].Result, frame);
                        var registers = tmp.Result.Registers.Concat(args[1].Result.Registers);
                        this.Add(node.SourceLocation, RCode.Invoke_static, method, registers);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation,
                                                    isLong ? RCode.Move_result_wide : RCode.Move_result, tmp.Result),
                                           tmp.Result);
                    }
                case AstCode.CompoundMul:
                    {
                        var localReg = frame.GetArgument((AstVariable) node.Operand);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Mul2Addr(), localReg, args[0].Result),
                                           localReg);
                    }
                case AstCode.Div:
                case AstCode.Div_Un:
                    {
                        if (args[0].Result.Register.IsTemp)
                            return new RLRange(args,
                                               this.Add(node.SourceLocation, node.Div2Addr(), args[0].Result,
                                                        args[1].Result), args[0].Result);
                        var tmp = frame.AllocateTemp(args[0].Result.Type);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Div(), tmp, args[0].Result, args[1].Result),
                                           tmp);
                    }
                case AstCode.CompoundDiv:
                    {
                        var localReg = frame.GetArgument((AstVariable) node.Operand);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Div2Addr(), localReg, args[0].Result),
                                           localReg);
                    }
                case AstCode.Rem:
                case AstCode.Rem_Un:
                    {
                        if (args[0].Result.Register.IsTemp)
                            return new RLRange(args,
                                               this.Add(node.SourceLocation, node.Rem2Addr(), args[0].Result,
                                                        args[1].Result), args[0].Result);
                        var tmp = frame.AllocateTemp(args[0].Result.Type);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Rem(), tmp, args[0].Result, args[1].Result),
                                           tmp);
                    }
                case AstCode.CompoundRem:
                    {
                        var localReg = frame.GetArgument((AstVariable) node.Operand);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Rem2Addr(), localReg, args[0].Result),
                                           localReg);
                    }
                case AstCode.And:
                    {
                        if (args[0].Result.Register.IsTemp)
                            return new RLRange(args,
                                               this.Add(node.SourceLocation, node.And2Addr(), args[0].Result,
                                                        args[1].Result), args[0].Result);
                        var tmp = frame.AllocateTemp(args[0].Result.Type);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.And(), tmp, args[0].Result, args[1].Result),
                                           tmp);
                    }
                case AstCode.CompoundAnd:
                    {
                        var localReg = frame.GetArgument((AstVariable) node.Operand);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.And2Addr(), localReg, args[0].Result),
                                           localReg);
                    }
                case AstCode.Or:
                    {
                        if (args[0].Result.Register.IsTemp)
                            return new RLRange(args,
                                               this.Add(node.SourceLocation, node.Or2Addr(), args[0].Result,
                                                        args[1].Result), args[0].Result);
                        var tmp = frame.AllocateTemp(args[0].Result.Type);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Or(), tmp, args[0].Result, args[1].Result),
                                           tmp);
                    }
                case AstCode.CompoundOr:
                    {
                        var localReg = frame.GetArgument((AstVariable) node.Operand);
                        return new RLRange(args, this.Add(node.SourceLocation, node.Or2Addr(), localReg, args[0].Result),
                                           localReg);
                    }
                case AstCode.Xor:
                    {
                        if (args[0].Result.Register.IsTemp)
                            return new RLRange(args,
                                               this.Add(node.SourceLocation, node.Xor2Addr(), args[0].Result,
                                                        args[1].Result), args[0].Result);
                        var tmp = frame.AllocateTemp(args[0].Result.Type);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Xor(), tmp, args[0].Result, args[1].Result),
                                           tmp);
                    }
                case AstCode.CompoundXor:
                    {
                        var localReg = frame.GetArgument((AstVariable) node.Operand);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Xor2Addr(), localReg, args[0].Result),
                                           localReg);
                    }
                case AstCode.Shl:
                    {
                        var r = frame.AllocateTemp(args[0].Result.Type);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Shl(), r, args[0].Result, args[1].Result),
                                           r);
                    }
                case AstCode.CompoundShl:
                    {
                        var localReg = frame.GetArgument((AstVariable) node.Operand);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Shl2Addr(), localReg, args[0].Result),
                                           localReg);
                    }
                case AstCode.Shr:
                    {
                        var r = frame.AllocateTemp(args[0].Result.Type);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Shr(), r, args[0].Result, args[1].Result),
                                           r);
                    }
                case AstCode.CompoundShr:
                    {
                        var localReg = frame.GetArgument((AstVariable) node.Operand);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.Shr2Addr(), localReg, args[0].Result),
                                           localReg);
                    }
                case AstCode.Shr_Un:
                    {
                        var r = frame.AllocateTemp(args[0].Result.Type);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.UShr(), r, args[0].Result, args[1].Result),
                                           r);
                    }
                case AstCode.CompoundShr_Un:
                    {
                        var localReg = frame.GetArgument((AstVariable) node.Operand);
                        return new RLRange(args,
                                           this.Add(node.SourceLocation, node.UShr2Addr(), localReg, args[0].Result),
                                           localReg);
                    }
                case AstCode.Conditional: // arg[0] ? arg[1] : arg[2]
                    {
                        var valueType = (XTypeReference) node.Operand;
                        var result = frame.AllocateTemp(valueType.GetReference(targetPackage));
                        var move = node.Arguments[1].Move();
                        var move2 = node.Arguments[2].Move();
                        if (move2 == RCode.Move_object) move = move2;

                        // condition
                        var gotoArg2 = this.Add(node.SourceLocation, RCode.If_eqz, null, args[0].Result.Registers);

                        // Generate code for arg[1]
                        var arg1 = node.Arguments[1].Accept(this, node);
                        this.Add(node.SourceLocation, move, result, arg1.Result);
                        var gotoEnd = this.Add(node.SourceLocation, RCode.Goto, null);

                        // Generate code for arg[2]
                        var arg2Start = this.Add(node.SourceLocation, RCode.Nop);
                        var arg2 = node.Arguments[2].Accept(this, node);
                        this.Add(node.SourceLocation, move, result, arg2.Result);

                        var end = this.Add(node.SourceLocation, RCode.Nop);
                        // Set branch targets
                        gotoArg2.Operand = arg2Start;
                        gotoEnd.Operand = end;

                        return new RLRange(gotoArg2, end, result);
                    }

                    #endregion

                    #region Conversion

                    /*case AstCode.Conv_U4:
                case AstCode.Conv_Ovf_U4:
                    {
                        return new RLRange(this.Add(node.SourceLocation, RCode.Nop), args[0].Result);
                    }*/
                case AstCode.Conv_I1:
                case AstCode.Conv_Ovf_I1:
                case AstCode.Conv_Ovf_I1_Un:
                    return ConvX(node.SourceLocation, RCode.Int_to_byte, PrimitiveType.Byte,
                                 ConvToInt(node.SourceLocation, args[0]));
                case AstCode.Conv_U1:
                case AstCode.Conv_Ovf_U1:
                case AstCode.Conv_Ovf_U1_Un:
                    {
                        var result = ConvX(node.SourceLocation, RCode.Int_to_byte, PrimitiveType.Byte,
                                           ConvToInt(node.SourceLocation, args[0]));
                        var last = this.Add(node.SourceLocation, RCode.And_int_lit, 0xFF, result.Result, result.Result);
                        return new RLRange(result.First, last, result.Result);
                    }
                case AstCode.Conv_I2:
                case AstCode.Conv_Ovf_I2:
                case AstCode.Conv_Ovf_I2_Un:
                    return ConvX(node.SourceLocation, RCode.Int_to_short, PrimitiveType.Short,
                                 ConvToInt(node.SourceLocation, args[0]));
                case AstCode.Conv_U2:
                case AstCode.Conv_Ovf_U2:
                case AstCode.Conv_Ovf_U2_Un:
                    {
                        if (node.GetResultType().IsUInt16())
                        {
                            var result = ConvX(node.SourceLocation, RCode.Int_to_short, PrimitiveType.Short,
                                               ConvToInt(node.SourceLocation, args[0]));
                            var r2 = frame.AllocateTemp(PrimitiveType.Int);
                            this.Add(node.SourceLocation, RCode.Const, 0xFFFF, r2);
                            var last = this.Add(node.SourceLocation, RCode.And_int_2addr, result.Result, r2);
                            return new RLRange(result.First, last, result.Result);
                        }
                        else
                        {
                            return ConvX(node.SourceLocation, RCode.Int_to_char, PrimitiveType.Char,
                                         ConvToInt(node.SourceLocation, args[0]));
                        }
                    }
                case AstCode.Conv_I4:
                case AstCode.Conv_Ovf_I4:
                case AstCode.Conv_Ovf_I4_Un:
                case AstCode.Conv_I: // Convert to native int
                case AstCode.Conv_Ovf_I: // Convert to native with overflow check
                case AstCode.Conv_Ovf_I_Un: // Convert to native without overflow check
                case AstCode.Conv_U: // Convert to native uint
                case AstCode.Conv_Ovf_U: // Convert to native uint with overflow check
                case AstCode.Conv_Ovf_U_Un: // Convert to native uint without overflow check
                case AstCode.Conv_U4:
                case AstCode.Conv_Ovf_U4:
                case AstCode.Conv_Ovf_U4_Un:
                    return ConvX(node.SourceLocation, node.Arguments[0].ConvI4(), PrimitiveType.Int, args[0]);
                case AstCode.Conv_I8:
                case AstCode.Conv_Ovf_I8:
                case AstCode.Conv_Ovf_I8_Un:
                case AstCode.Conv_U8:
                case AstCode.Conv_Ovf_U8:
                case AstCode.Conv_Ovf_U8_Un:
                    return ConvX(node.SourceLocation, node.Arguments[0].ConvI8(), PrimitiveType.Long, args[0]);
                case AstCode.Conv_R4:
                    return ConvX(node.SourceLocation, node.Arguments[0].ConvR4(), PrimitiveType.Float, args[0]);
                case AstCode.Conv_R8:
                case AstCode.Conv_R_Un:
                    return ConvX(node.SourceLocation, node.Arguments[0].ConvR8(), PrimitiveType.Double, args[0]);
                case AstCode.Int_to_ubyte:
                    {
                        var tmp = this.EnsureTemp(node.SourceLocation, args[0].Result, frame);
                        var last = this.Add(node.SourceLocation, RCode.And_int_lit, 0xFF, tmp.Result, tmp.Result);
                        return new RLRange(args, tmp.First, last, tmp.Result);
                    }
                case AstCode.Int_to_ushort:
                    {
                        var tmp = this.EnsureTemp(node.SourceLocation, args[0].Result, frame);
                        var r2 = frame.AllocateTemp(PrimitiveType.Int);
                        this.Add(node.SourceLocation, RCode.Const, 0xFFFF, r2);
                        var last = this.Add(node.SourceLocation, RCode.And_int_2addr, tmp.Result, r2);
                        return new RLRange(args, tmp.First, last, tmp.Result);
                    }
                case AstCode.Box:
                    {
                        var type = (XTypeReference) node.Operand;
                        var tmp = this.EnsureTemp(node.SourceLocation, args[0].Result, frame);
                        return this.Box(node.SourceLocation, tmp.Result, type, targetPackage, frame);
                    }
                case AstCode.Unbox:
                case AstCode.Unbox_Any:
                    {
                        var type = (XTypeReference) node.Operand;
                        var tmp = this.EnsureTemp(node.SourceLocation, args[0].Result, frame);
                        return this.Unbox(node.SourceLocation, tmp.Result, type, compiler, targetPackage, frame);
                    }
                case AstCode.AddressOf:
                    {
                        return args[0];
                    }
                case AstCode.Enum_to_int:
                case AstCode.Enum_to_long:
                    {
                        var enumType = node.Arguments[0].GetResultType().Resolve();
                        var isWide = enumType.GetEnumUnderlyingType().IsWide();
                        var internalEnumType = compiler.GetDot42InternalType("Enum").GetClassReference(targetPackage);
                        var methodName = isWide ? "LongValue" : "IntValue";
                        var enumNumericType = isWide ? PrimitiveType.Long : PrimitiveType.Int;
                        var rvalue = frame.AllocateTemp(enumNumericType);
                        var convMethodDex = new MethodReference(internalEnumType, methodName,
                                                                new Prototype(enumNumericType));
                        var call = this.Add(node.SourceLocation, RCode.Invoke_virtual, convMethodDex, args[0].Result);
                        var last = this.Add(node.SourceLocation, isWide ? RCode.Move_result_wide : RCode.Move_result,
                                            rvalue);
                        return new RLRange(call, last, rvalue);
                    }

                case AstCode.Int_to_enum:
                case AstCode.Long_to_enum:
                    {
                        var enumType = node.GetResultType().Resolve();
                        var denumType = enumType.GetClassReference(targetPackage);
                        var isWide = enumType.GetEnumUnderlyingType().IsWide();
                        var literalIsWide = node.Arguments[0].GetResultType().IsWide();
                        var internalEnumType = compiler.GetDot42InternalType("Enum").GetClassReference(targetPackage);
                        var internalEnumInfoType = compiler.GetDot42InternalType("EnumInfo").GetClassReference(targetPackage);
                        var enumNumericType = isWide ? PrimitiveType.Long : PrimitiveType.Int;
                        var getValueMethod = new MethodReference(internalEnumInfoType, "GetValue",
                                                                 new Prototype(internalEnumType,
                                                                               new Parameter(enumNumericType, "value")));
                        var rinfo = frame.AllocateTemp(internalEnumInfoType);
                        var infoField = new FieldReference(denumType, NameConstants.Enum.InfoFieldName,
                                                           internalEnumInfoType);
                        var getInfo = this.Add(node.SourceLocation, RCode.Sget_object, infoField, rinfo);
                        var valueR = args[0].Result;
                        if (isWide != literalIsWide)
                        {
                            var convValueR = frame.AllocateTemp(isWide ? PrimitiveType.Long : PrimitiveType.Int);
                            var convCode = isWide ? RCode.Int_to_long : RCode.Long_to_int;
                            this.Add(node.SourceLocation, convCode, convValueR, valueR);
                            valueR = convValueR;
                        }
                        this.Add(node.SourceLocation, RCode.Invoke_virtual, getValueMethod,
                                 rinfo.Registers.Concat(valueR.Registers));
                        var renum = frame.AllocateTemp(denumType);
                        this.Add(node.SourceLocation, RCode.Move_result_object, renum);
                        var castClass = this.Add(node.SourceLocation, RCode.Check_cast, denumType, renum);
                        return new RLRange(getInfo, castClass, renum);
                    }

                    #endregion

                    #region Branching

                case AstCode.Cle:
                case AstCode.Cle_Un:
                case AstCode.Clt:
                case AstCode.Clt_Un:
                case AstCode.Ceq:
                case AstCode.Cne:
                case AstCode.Cgt:
                case AstCode.Cgt_Un:
                case AstCode.Cge:
                case AstCode.Cge_Un:
                    {
                        var r = frame.AllocateTemp(PrimitiveType.Int);
                        var start = this.Add(node.SourceLocation, RCode.Const, 0, r);
                        Instruction test;
                        var narg0 = node.Arguments[0];
                        var narg1 = node.Arguments[1];
                        if (narg0.IsWide() || narg1.IsWide())
                        {
                            var r2 = frame.AllocateTemp(PrimitiveType.Int);
                            var code = narg0.IsDouble() ? RCode.Cmpg_double : RCode.Cmp_long;
                            this.Add(node.SourceLocation, code, r2, args[0].Result, args[1].Result);
                            test = this.Add(node.SourceLocation, node.Code.Reverse().ToIfTestZ(), r2);
                        }
                        else if (narg0.IsFloat() || narg1.IsFloat())
                        {
                            var r2 = frame.AllocateTemp(PrimitiveType.Int);
                            this.Add(node.SourceLocation, RCode.Cmpg_float, r2, args[0].Result, args[1].Result);
                            test = this.Add(node.SourceLocation, node.Code.Reverse().ToIfTestZ(), r2);
                        }
                        else
                        {
                            test = this.Add(node.SourceLocation, node.Code.Reverse().ToIfTest(), args[0].Result,
                                            args[1].Result);
                        }
                        this.Add(node.SourceLocation, RCode.Const, 1, r);
                        var end = this.Add(node.SourceLocation, RCode.Nop, null);
                        test.Operand = end;
                        return new RLRange(args, start, end, r);
                    }
                case AstCode.CmpLFloat:
                case AstCode.CmpGFloat:
                case AstCode.CmpLong:
                    {
                        var r = frame.AllocateTemp(PrimitiveType.Int);
                        var code = node.CmpFloatOrLong();
                        var test = this.Add(node.SourceLocation, code, r, args[0].Result, args[1].Result);
                        return new RLRange(args, test, r);
                    }
                case AstCode.CIsNotNull:
                case AstCode.CIsNull:
                    {
                        var r = frame.AllocateTemp(PrimitiveType.Int);
                        var start = this.Add(node.SourceLocation, RCode.Const, 0, r);
                        var test = this.Add(node.SourceLocation, node.Code.Reverse().ToIfTestZ(), args[0].Result);
                        this.Add(node.SourceLocation, RCode.Const, 1, r);
                        var end = this.Add(node.SourceLocation, RCode.Nop, null);
                        test.Operand = end;
                        return new RLRange(args, start, end, r);
                    }
                case AstCode.Brtrue:
                case AstCode.Brfalse:
                case AstCode.BrIfEq:
                case AstCode.BrIfNe:
                case AstCode.BrIfGe:
                case AstCode.BrIfGt:
                case AstCode.BrIfLe:
                case AstCode.BrIfLt:
                    {
                        var label = (AstLabel) node.Operand;
                        var opcode = node.Code.ToIfTestZ();
                        var branch = this.Add(node.SourceLocation, opcode, args[0].Result);
                        labelManager.AddResolveAction(label, x => branch.Operand = x);
                        return new RLRange(branch, null);
                    }
                case AstCode.__Beq:
                case AstCode.__Bne_Un:
                case AstCode.__Ble:
                case AstCode.__Ble_Un:
                case AstCode.__Blt:
                case AstCode.__Blt_Un:
                case AstCode.__Bgt:
                case AstCode.__Bgt_Un:
                case AstCode.__Bge:
                case AstCode.__Bge_Un:
                    {
                        var label = (AstLabel) node.Operand;
                        var opcode = node.Code.ToIfTest();
                        var branch = this.Add(node.SourceLocation, opcode, args[0].Result, args[1].Result);
                        labelManager.AddResolveAction(label, x => branch.Operand = x);
                        return new RLRange(branch, null);
                    }
                case AstCode.Br:
                    {
                        var label = (AstLabel) node.Operand;
                        var branch = this.Add(node.SourceLocation, RCode.Goto, null);
                        labelManager.AddResolveAction(label, x => branch.Operand = x);
                        return new RLRange(branch, null);
                    }
                case AstCode.Leave:
                    {
                        var label = (AstLabel) node.Operand;
                        var branch = this.Add(node.SourceLocation, RCode.Leave, null);
                        labelManager.AddResolveAction(label, x => branch.Operand = x);
                        return new RLRange(branch, null);
                    }
                case AstCode.Switch:
                    {
                        var labels = (AstLabel[]) node.Operand;
                        var targets = new Instruction[labels.Length];
                        for (var i = 0; i < labels.Length; i++)
                        {
                            var index = i;
                            labelManager.AddResolveAction(labels[i], x => targets[index] = x);
                        }
                        var @switch = this.Add(node.SourceLocation, RCode.Packed_switch, targets, args[0].Result);
                        return new RLRange(@switch, null);
                    }
                case AstCode.LookupSwitch:
                    {
                        var labelKeyPairs = (AstLabelKeyPair[]) node.Operand;
                        var targetPairs = new Tuple<int, Instruction>[labelKeyPairs.Length];
                        for (var i = 0; i < labelKeyPairs.Length; i++)
                        {
                            var index = i;
                            var key = labelKeyPairs[i].Key;
                            var label = labelKeyPairs[i].Label;
                            labelManager.AddResolveAction(label, x => targetPairs[index] = Tuple.Create(key, x));
                        }
                        var @switch = this.Add(node.SourceLocation, RCode.Sparse_switch, targetPairs, args[0].Result);
                        return new RLRange(@switch, null);
                    }
                case AstCode.NullCoalescing:
                    {
                        var r = frame.AllocateTemp(node.InferredType.GetReference(targetPackage));
                        var first = this.Add(node.SourceLocation, RCode.Move_object, r, args[0].Result);
                        // r := leftExpr
                        var if_nez = this.Add(node.SourceLocation, RCode.If_nez, r); // if r not null, skip
                        this.Add(node.SourceLocation, RCode.Move_object, r, args[1].Result); // r := rightExpr
                        var end = this.Add(node.SourceLocation, RCode.Nop);
                        if_nez.Operand = end;
                        return new RLRange(first, end, r);
                    }

                    #endregion

                    #region Call

                case AstCode.Call:
                case AstCode.Callvirt:
                case AstCode.CallIntf:
                case AstCode.CallSpecial:
                    {
                        return VisitCallExpression(node, args, parent);
                    }
                case AstCode.Ret:
                    if (currentMethod.ReturnsVoid)
                        return new RLRange(args, this.Add(node.SourceLocation, RCode.Return_void), null);
                    return new RLRange(args, this.Add(node.SourceLocation, node.Return(currentMethod), args[0].Result),
                                       null);

                    #endregion

                    #region Array

                case AstCode.Newarr:
                    {
                        var type = (XTypeReference) node.Operand;
                        var dType = new ArrayType(type.GetReference(targetPackage));
                        var r = frame.AllocateTemp(dType);
                        var newArray = this.Add(node.SourceLocation, RCode.New_array, dType, r, args[0].Result);
                        return new RLRange(newArray, r);
                    }
                case AstCode.ArrayNewInstance:
                    {
                        // Resolve type to a Class<?>
                        var newInstance = FrameworkReferences.ArrayNewInstance;
                        var first = this.Add(node.SourceLocation, RCode.Invoke_static, newInstance, args[0].Result,
                                             args[1].Result);
                        var r = frame.AllocateTemp(newInstance.Prototype.ReturnType);
                        var last = this.Add(node.SourceLocation, RCode.Move_result_object, r);
                        return new RLRange(first, last, r);
                    }
                case AstCode.ArrayNewInstance2:
                    {
                        // Call java.lang.reflect.Array.newInstance(type, int[])
                        var newInstance = FrameworkReferences.ArrayNewInstance2;
                        var first = this.Add(node.SourceLocation, RCode.Invoke_static, newInstance, args[0].Result,
                                             args[1].Result);
                        var resultReg = frame.AllocateTemp(FrameworkReferences.Object);
                        var last = this.Add(node.SourceLocation, RCode.Move_result_object, resultReg);
                        return new RLRange(args, first, last, resultReg);
                    }
                case AstCode.InitEnumArray:
                    {
                        var type = (XTypeReference) node.Operand;
                        var typeDef = type.Resolve();
                        // Initialize array
                        var fillMethod = FrameworkReferences.ArraysFillObject;
                        var denumType = typeDef.GetClassReference(targetPackage);
                        var defaultField = new FieldReference(denumType, NameConstants.Enum.DefaultFieldName, denumType);
                        var rdefault = frame.AllocateTemp(denumType);
                        var first = this.Add(node.SourceLocation, RCode.Sget_object, defaultField, rdefault);
                        var arrayR = args[0].Result;
                        var last = this.Add(node.SourceLocation, RCode.Invoke_static, fillMethod, arrayR, rdefault);
                        return new RLRange(first, last, arrayR);
                    }
                case AstCode.InitStructArray:
                    {
                        var defaultCtor = (XMethodReference) node.Operand;
                        var dDefaultCtor = defaultCtor.GetReference(targetPackage);
                        var arrayR = args[0].Result;
                        var indexR = frame.AllocateTemp(PrimitiveType.Int);
                        var oneR = frame.AllocateTemp(PrimitiveType.Int);
                        var elementR = frame.AllocateTemp(dDefaultCtor.Owner);
                        var first = this.Add(node.SourceLocation, RCode.Array_length, indexR, arrayR);
                        this.Add(node.SourceLocation, RCode.Const, 1, oneR);
                        var ifZero = this.Add(node.SourceLocation, RCode.If_eqz, indexR);
                            // if (index == 0) goto end;  (Operand set later)
                        this.Add(node.SourceLocation, RCode.Sub_int_2addr, indexR, oneR); // index--;
                        this.Add(node.SourceLocation, RCode.New_instance, dDefaultCtor.Owner, elementR);
                            // element = new Struct;
                        this.Add(node.SourceLocation, RCode.Invoke_direct, dDefaultCtor, elementR);
                            // invoke element.ctor()
                        this.Add(node.SourceLocation, RCode.Aput_object, elementR, arrayR, indexR);
                            // Store element in array
                        this.Add(node.SourceLocation, RCode.Goto, ifZero); // End of loop
                        var end = this.Add(node.SourceLocation, RCode.Nop);
                        ifZero.Operand = end;
                        return new RLRange(first, end, arrayR);
                    }
                case AstCode.MultiNewarr:
                    {
                        var arrType = (XTypeReference) node.Operand;
                        var darrType = arrType.GetReference(targetPackage);
                        var compType = arrType;
                        // Unwind array type to component type
                        for (var i = 0; i < node.Arguments.Count; i++)
                        {
                            compType = compType.ElementType;
                        }
                        var dcompType = new ArrayType(compType.GetReference(targetPackage));
                        var dimArrayR = frame.AllocateTemp(new ArrayType(PrimitiveType.Int));
                        var lengthR = frame.AllocateTemp(PrimitiveType.Int);
                        var first = this.Add(node.SourceLocation, RCode.Nop);
                        // Allocate dimensions array
                        this.Add(node.SourceLocation, RCode.Const, node.Arguments.Count, lengthR);
                        this.Add(node.SourceLocation, RCode.New_array, PrimitiveType.Int, dimArrayR, lengthR);
                        var indexR = lengthR;
                        // Initialize dimensions array
                        for (var i = 0; i < node.Arguments.Count; i++)
                        {
                            this.Add(node.SourceLocation, RCode.Const, i, indexR);
                            this.Add(node.SourceLocation, RCode.Aput, args[i], dimArrayR, indexR);
                        }

                        // Load component type
                        var compTypeR = frame.AllocateTemp(new ClassReference("java/lang/Class"));
                        this.Add(node.SourceLocation, RCode.Const_class, dcompType, compTypeR);

                        // Call java/lang/reflect/Array/newInstance
                        var reflectArrayType = new ClassReference("java/lang/reflect/Array");
                        var prototype = PrototypeBuilder.ParseMethodSignature("(Ljava/lang/Class;[I)Ljava/lang/Object;");
                        var methodRef = new MethodReference(reflectArrayType, "newInstance", prototype);
                        var arrayR = frame.AllocateTemp(darrType);
                        this.Add(node.SourceLocation, RCode.Invoke_static, methodRef, compTypeR, dimArrayR);
                        var last = this.Add(node.SourceLocation, RCode.Move_result_object, arrayR);

                        return new RLRange(first, last, arrayR);
                    }
                case AstCode.ByRefArray:
                case AstCode.ByRefOutArray:
                    {
                        // Create array
                        var type = (XTypeReference) node.Operand;
                        var dType = new ArrayType(type.GetReference(targetPackage));
                        var arrayR = frame.AllocateTemp(dType);
                        var lengthR = frame.AllocateTemp(PrimitiveType.Int);
                        // length=1
                        var initLength = this.Add(node.SourceLocation, RCode.Const, 1, lengthR);
                        // newarray
                        this.Add(node.SourceLocation, RCode.New_array, dType, arrayR, lengthR);
                        if (node.Code == AstCode.ByRefArray)
                        {
                            var valueR = args[0].Result;
                            var arrayType = node.InferredType;

                            // Perform type conversion if needed
                            bool isConverted;
                            var converted = this.ConvertTypeBeforeStore(node.SourceLocation, type, arrayType.ElementType,
                                                                        valueR, targetPackage, frame, compiler,
                                                                        out isConverted);
                            if (isConverted) valueR = converted.Result;

                            // array[0]=value
                            var indexR = frame.AllocateTemp(PrimitiveType.Int);
                            this.Add(node.SourceLocation, RCode.Const, 0, indexR);
                            this.Add(node.SourceLocation, arrayType.APut(), valueR, arrayR, indexR);
                        }
                        var end = this.Add(node.SourceLocation, RCode.Nop);
                        return new RLRange(initLength, end, arrayR);
                    }
                case AstCode.Ldlen:
                    {
                        var r = frame.AllocateTemp(PrimitiveType.Int);
                        return new RLRange(this.Add(node.SourceLocation, RCode.Array_length, r, args[0].Result), r);
                    }
                case AstCode.Stelem_I:
                case AstCode.Stelem_I1:
                case AstCode.Stelem_I2:
                case AstCode.Stelem_I4:
                case AstCode.Stelem_I8:
                case AstCode.Stelem_R4:
                case AstCode.Stelem_R8:
                case AstCode.Stelem_Ref:
                case AstCode.Stelem_Any:
                    {
                        var first = this.Add(node.SourceLocation, RCode.Nop);
                        var arrayR = args[0].Result;
                        var indexR = args[1].Result;
                        var valueR = args[2].Result;
                        var valueType = node.Arguments[2].GetResultType();
                        var arrayType = node.Arguments[0].GetResultType();

                        // Perform type conversion if needed
                        bool isConverted;
                        var converted = this.ConvertTypeBeforeStore(node.SourceLocation, valueType,
                                                                    arrayType.ElementType, valueR, targetPackage,
                                                                    frame, compiler, out isConverted);
                        if (isConverted) valueR = converted.Result;

                        // Store in array
                        var aput = this.Add(node.SourceLocation, node.APut(), valueR, arrayR, indexR);
                        return new RLRange(first, aput, valueR);
                    }
                case AstCode.Ldelem_I:
                case AstCode.Ldelem_I1:
                case AstCode.Ldelem_I2:
                case AstCode.Ldelem_I4:
                case AstCode.Ldelem_I8:
                case AstCode.Ldelem_R4:
                case AstCode.Ldelem_R8:
                case AstCode.Ldelem_U1:
                case AstCode.Ldelem_U2:
                case AstCode.Ldelem_U4:
                case AstCode.Ldelem_Ref:
                case AstCode.Ldelem_Any:
                    {
                        var arrayR = args[0].Result;
                        var indexR = args[1].Result;
                        var arrayType = node.Arguments[0].GetResultType();
                        var elementType = arrayType.ElementType;

                        // Allocate registry for value
                        var valueR = frame.AllocateTemp(elementType.GetReference(targetPackage));

                        // Get from array
                        var first = this.Add(node.SourceLocation, node.AGet(), valueR, arrayR, indexR);
                        return new RLRange(first, valueR);
                    }

                    #endregion

                    #region Local variables / arguments

                case AstCode.Ldloc:
                    {
                        var variable = (AstVariable) node.Operand;
                        var valueR = frame.GetArgument(variable);
                        return new RLRange(args, valueR);
                    }
                case AstCode.Ldthis:
                    if (frame.ThisArgument == null)
                        throw new ArgumentException("No this in current method");
                    return new RLRange(args, frame.ThisArgument);
                case AstCode.Stloc:
                    {
                        var variable = (AstVariable) node.Operand;
                        var resultType = node.Arguments[0].GetResultType();
                        var valueR = args[0].Result;
                        var first = this.Add(node.SourceLocation, RCode.Nop);
                        // Convert value if needed
                        bool isConverted;
                        var converted = this.ConvertTypeBeforeStore(node.SourceLocation, resultType, variable.Type,
                                                                    valueR, targetPackage, frame, compiler,
                                                                    out isConverted);
                        if (isConverted) valueR = converted.Result;
                        // Store in variable
                        var variableR = frame.GetArgument(variable);
                        return new RLRange(args, first, this.Add(node.SourceLocation, node.Move(), variableR, valueR),
                                           variableR);
                    }

                    #endregion

                    #region Fields

                case AstCode.Ldfld:
                    {
                        var fieldRef = (XFieldReference) node.Operand;
                        var field = fieldRef.Resolve();
                        var dField = field.GetReference(targetPackage);
                        var fieldType = field.FieldType;
                        // Allocate register
                        var valueR = frame.AllocateTemp(fieldType.GetReference(targetPackage));
                        // Get from field
                        var iget = this.Add(node.SourceLocation, field.IGet(), dField, valueR, args[0].Result);
                        return new RLRange(iget, valueR);
                    }
                case AstCode.Stfld:
                    {
                        var fieldRef = (XFieldReference) node.Operand;
                        var field = fieldRef.Resolve();
                        var dField = field.GetReference(targetPackage);
                        var type = node.InferredType;
                        var first = this.Add(node.SourceLocation, RCode.Nop);
                        var valueR = args[1].Result;

                        // Perform type conversion if needed
                        bool isConverted;
                        var converted = this.ConvertTypeBeforeStore(node.SourceLocation, type, field.FieldType, valueR,
                                                                    targetPackage, frame, compiler,
                                                                    out isConverted);
                        if (isConverted) valueR = converted.Result;

                        // Store in field
                        var iput = this.Add(node.SourceLocation, field.IPut(), dField, valueR, args[0].Result);
                        return new RLRange(first, iput, valueR);
                    }
                case AstCode.Ldsfld:
                    {
                        var field = (XFieldReference) node.Operand;
                        XFieldDefinition fieldDef;
                        field.TryResolve(out fieldDef);
                        var fieldType = field.FieldType;
                        // Allocate register
                        var valueR = frame.AllocateTemp(fieldType.GetReference(targetPackage));

                        string resourceName;
                        if ((fieldDef != null) && fieldDef.TryGetResourceIdAttribute(out resourceName))
                        {
                            // Replace by resource id.
                            var id = FindResourceId(compiler.ResourceTable, resourceName);
                            return new RLRange(args, this.Add(node.SourceLocation, RCode.Const, id, valueR), valueR);
                        }
                        else
                        {
                            // Normal get from field
                            var dField = field.GetReference(targetPackage);
                            var iget = this.Add(node.SourceLocation, node.SGet(), dField, valueR);
                            return new RLRange(iget, valueR);
                        }
                    }
                case AstCode.Stsfld:
                    {
                        var field = (XFieldReference) node.Operand;
                        var dField = field.GetReference(targetPackage);
                        var type = node.InferredType;
                        var first = this.Add(node.SourceLocation, RCode.Nop);
                        var valueR = args[0].Result;

                        // Perform type conversion if needed
                        bool isConverted;
                        var converted = this.ConvertTypeBeforeStore(node.SourceLocation, type, field.FieldType, valueR,
                                                                    targetPackage, frame, compiler,
                                                                    out isConverted);
                        if (isConverted) valueR = converted.Result;

                        // Store in field
                        var sput = this.Add(node.SourceLocation, node.SPut(), dField, valueR);
                        return new RLRange(first, sput, valueR);
                    }

                    #endregion

                    #region Object model

                case AstCode.Newobj: // IL new
                    {
                        var ilCtorRef = (XMethodReference) node.Operand;
                        var ilType = ilCtorRef.DeclaringType;

                        // New normal object
                        var ilCtor = ilCtorRef.Resolve();
                        var dCtor = ilCtor.GetReference(targetPackage);
                        var dType = ilType.GetReference(targetPackage);

                        // Create instance
                        var r = frame.AllocateTemp(dType);
                        var first = this.Add(node.SourceLocation, RCode.New_instance, dType, r);

                        // Prepare arguments
                        int argsOffset;
                        List<RLRange> originalArgs;
                        ConvertParametersBeforeCall(node, args, ilCtor, out argsOffset, out originalArgs);

                        // Collect arguments
                        var arguments = args.SelectMany(x => x.Result.Registers).ToList();
                        // Insert this argument
                        arguments.Insert(0, r);

                        // Invoke ctor
                        this.Add(node.SourceLocation, RCode.Invoke_direct, dCtor, arguments);

                        // Post process arguments
                        ConvertParametersAfterCall(node, args, ilCtor, argsOffset, originalArgs);
                        var last = this.Add(node.SourceLocation, RCode.Nop);
                        return new RLRange(args, first, last, r);
                    }
                case AstCode.New: // Java new
                    {
                        var ilType = (XTypeReference) node.Operand;
                        // New normal object
                        var dType = ilType.GetReference(targetPackage);
                        // Create instance
                        var r = frame.AllocateTemp(dType);
                        var first = this.Add(node.SourceLocation, RCode.New_instance, dType, r);
                        return new RLRange(args, first, r);
                    }
                case AstCode.CallBaseCtor:
                    {
                        var dtype = currentDexMethod.Owner;
                        var dBaseType = dtype.SuperClass as ClassDefinition;
                        if (dBaseType == null)
                            throw new CompilerException(string.Format("Type {0} base no superclass as definition", dtype.Fullname));
                        var paramCount = node.Arguments.Count - 1;
                        var baseCtor = dBaseType.Methods.Single(x => x.IsConstructor && (x.Prototype.Parameters.Count == paramCount));
                        var call = this.Add(node.SourceLocation, RCode.Invoke_direct, baseCtor, args.SelectMany(x => x.Result.Registers));
                        return new RLRange(call, args[0].Result);
                    }
            case AstCode.Castclass:
                    {
                        throw new NotSupportedException("castclass is not supported");
                    }
                case AstCode.SimpleCastclass:
                    {
                        var type = (XTypeReference) node.Operand;
                        var dType = type.GetReference(targetPackage);
                        if (type.IsPrimitive)
                        {
                            // Convert type to boxed type
                            dType = BoxInfo.GetBoxedType(type);
                        }

                        // Normal cast
                        var tmp = this.EnsureTemp(node.SourceLocation, args[0].Result, frame);
                        var checkCast = this.Add(node.SourceLocation, RCode.Check_cast, dType, tmp.Result);
                        return new RLRange(tmp, checkCast, tmp.Result);
                    }
                case AstCode.Isinst: // "as" operator
                    {
                        throw new NotSupportedException("isinst is not supported");
                    }
                case AstCode.InstanceOf: // "is" operator
                    {
                        throw new NotSupportedException("instanceof is not supported");
                    }
                case AstCode.SimpleInstanceOf: // "is" operator
                    {
                        var type = (XTypeReference) node.Operand;
                        var dType = type.GetReference(targetPackage);
                        if (type.IsPrimitive)
                        {
                            // Convert type to boxed type
                            dType = BoxInfo.GetBoxedType(type);
                        }
                        // Normal "is"
                        var rResult = frame.AllocateTemp(PrimitiveType.Boolean);
                        var instanceOf = this.Add(node.SourceLocation, RCode.Instance_of, dType, rResult, args[0].Result);
                        return new RLRange(instanceOf, rResult);
                    }

                    #endregion

#region Generics
                case AstCode.LdGenericInstanceField:
                    {
                        var giField = GetGenericInstanceField();
                        var r = frame.AllocateTemp(FrameworkReferences.ClassArray);
                        var iget = this.Add(node.SourceLocation, RCode.Iget_object, giField, r, frame.ThisArgument);
                        return new RLRange(iget, r);
                    }
                case AstCode.StGenericInstanceField:
                    {
                        var giField = GetGenericInstanceField();
                        var r = args[0].Result;
                        var iput = this.Add(node.SourceLocation, RCode.Iput_object, giField, r, frame.ThisArgument);
                        return new RLRange(iput, r);
                    }
                case AstCode.LdGenericInstanceTypeArgument:
                    {
                        if (frame.GenericInstanceTypeArgument == null)
                        {
                            throw new CompilerException(string.Format("Method {0} has no generic instance type argument", currentMethod.FullName));
                        }
                        return new RLRange(frame.GenericInstanceTypeArgument);
                    }
                case AstCode.LdGenericInstanceMethodArgument:
                    {
                        if (frame.GenericInstanceMethodArgument == null)
                        {
                            throw new CompilerException(string.Format("Method {0} has no generic instance method argument", currentMethod.FullName));
                        }
                        return new RLRange(frame.GenericInstanceMethodArgument);
                    }
                case AstCode.UnboxFromGeneric:
                    {
                        // Get result
                        var elementType = (XTypeReference) node.Operand;
                        var r = args[0].Result;
                        var start = this.Add(node.SourceLocation, RCode.Nop);
                        var last = start;

                        // Convert result when needed
                        if (elementType.IsGenericParameter)
                        {
                            var returnType = node.GetResultType();
                            var tmp = this.Unbox(node.SourceLocation, r, returnType, compiler, targetPackage, frame);
                            last = tmp.Last;
                            r = tmp.Result;
                        }
                        else if (elementType.IsGenericParameterArray())
                        {
                            var returnType = node.GetResultType();
                            if (returnType.IsPrimitiveArray())
                            {
                                var tmp = this.UnboxGenericArrayResult(node.SourceLocation, r, returnType, targetPackage, frame, compiler);
                                last = tmp.Last;
                                r = tmp.Result;
                            }
                            else
                            {
                                var tmp = this.Unbox(node.SourceLocation, r, returnType, compiler, targetPackage, frame);
                                last = tmp.Last;
                                r = tmp.Result;
                            }
                        }
                        return new RLRange(start, last, r);
                    }
#endregion

                case AstCode.Throw:
                    {
                        var @throw = this.Add(node.SourceLocation, RCode.Throw, args[0].Result);
                        return new RLRange(@throw, null);
                    }
                case AstCode.Rethrow:
                    {
                        if (currentExceptionRegister == null)
                            throw new CompilerException("retrow outside catch block");
                        var @throw = this.Add(node.SourceLocation, RCode.Throw, currentExceptionRegister);
                        return new RLRange(@throw, null);                        
                    }
                case AstCode.Delegate:
                    {
                        //Debugger.Launch();
                        var delegateInfo = (Tuple<XTypeDefinition, XMethodDefinition>)node.Operand;
                        var delegateType = compiler.GetDelegateType(delegateInfo.Item1);
                        var delegateInstanceType = delegateType.GetOrCreateInstance(node.SourceLocation, targetPackage, delegateInfo.Item2);

                        // Create instance
                        var r = frame.AllocateTemp(delegateInstanceType.InstanceDefinition);
                        var newobj = this.Add(node.SourceLocation, RCode.New_instance, delegateInstanceType.InstanceDefinition, r);
                        // Call ctor
                        if (delegateInstanceType.CalledMethodIsStatic)
                        {
                            // Call without instance argument
                            var invokeCtor = this.Add(node.SourceLocation, RCode.Invoke_direct, delegateInstanceType.InstanceCtor, r);
                            return new RLRange(newobj, invokeCtor, r);
                        }
                        else
                        {
                            // Call with instance argument
                            var invokeCtor = this.Add(node.SourceLocation, RCode.Invoke_direct, delegateInstanceType.InstanceCtor, r, args[0].Result);
                            return new RLRange(newobj, invokeCtor, r);
                        }
                    }
                case AstCode.InitArray:
                    {
                        var arrayData = (InitArrayData) node.Operand;
                        var size = arrayData.Length;
                        var type = arrayData.ArrayType;
                        var dType = type.GetReference(targetPackage);

                        // Allocate new array
                        var rArray = frame.AllocateTemp(dType);
                        var rSize = frame.AllocateTemp(PrimitiveType.Int);
                        var start = this.Add(node.SourceLocation, RCode.Const, size, rSize);
                        this.Add(node.SourceLocation, RCode.New_array, dType, rArray, rSize);

                        // Initialize array
                        if (arrayData.IsSupportedByFillArrayData())
                        {
                            // Use fill-array-data
                            this.Add(node.SourceLocation, RCode.Fill_array_data, arrayData.Values, rArray);
                        }
                        else
                        {
                            // Use const/aput sequence
                            var rValue = frame.AllocateTemp(arrayData.ArrayType.ElementType.GetReference(targetPackage));
                            var rIndex = frame.AllocateTemp(PrimitiveType.Int);
                            var isWide = arrayData.ArrayType.ElementType.IsWide();
                            var constCode = isWide ? RCode.Const_wide : RCode.Const;
                            var aputCode = arrayData.ArrayType.APut();
                            var convertCode = arrayData.ArrayType.AConstConvertBeforePut();
                            var valueConverter = arrayData.ArrayType.ElementType.ConstValueConverter(false);

                            // Initialize index
                            this.Add(node.SourceLocation, RCode.Const, 0, rIndex);

                            // aput for each
                            for (var i = 0; i < arrayData.Length; i++)
                            {
                                var value = valueConverter(arrayData.Values.GetValue(i));
                                this.Add(node.SourceLocation, constCode, value, rValue);
                                if (convertCode != RCode.Nop)
                                {
                                    this.Add(node.SourceLocation, convertCode, rValue, rValue);                                    
                                }
                                this.Add(node.SourceLocation, aputCode, rValue, rArray, rIndex);
                                if (i + 1 < arrayData.Length)
                                {
                                    // Increment index
                                    this.Add(node.SourceLocation, RCode.Add_int_lit, 1, rIndex, rIndex);
                                }
                            }
                        }


                        //throw new NotImplementedException();
                        return new RLRange(this.Add(node.SourceLocation, RCode.Nop), rArray);
                    }
                case AstCode.InitArrayFromArguments:
                    {
                        var size = args.Count;
                        var type = (XArrayType) node.Operand;
                        var dType = type.GetReference(targetPackage);

                        // Allocate new array
                        var rArray = frame.AllocateTemp(dType);
                        var rSize = frame.AllocateTemp(PrimitiveType.Int);
                        var start = this.Add(node.SourceLocation, RCode.Nop);
                        this.Add(node.SourceLocation, RCode.Const, size, rSize);
                        this.Add(node.SourceLocation, RCode.New_array, dType, rArray, rSize);

                        // Use const/aput sequence
                        var rIndex = frame.AllocateTemp(PrimitiveType.Int);
                        var aputCode = type.APut();

                        // Initialize index
                        this.Add(node.SourceLocation, RCode.Const, 0, rIndex);

                        // aput for each
                        for (var i = 0; i < size; i++)
                        {
                            this.Add(node.SourceLocation, aputCode, args[i].Result, rArray, rIndex);
                            if (i + 1 < size)
                            {
                                // Increment index
                                this.Add(node.SourceLocation, RCode.Add_int_lit, 1, rIndex, rIndex);
                            }
                        }
                        return new RLRange(start, this.Add(node.SourceLocation, RCode.Nop), rArray);
                    }
                case AstCode.LdClass:
                    {
                        var ilType = (XTypeReference)node.Operand;
                        var dType = ilType.GetReference(targetPackage);
                        // Load type
                        var r = frame.AllocateTemp(FrameworkReferences.Class);
                        var first = this.Add(node.SourceLocation, RCode.Const_class, dType, r);
                        return new RLRange(args, first, r);                        
                    }
                case AstCode.Ldtoken:
                    {
                        throw new NotSupportedException("ldtoken is not supported");
                    }
                default:
                    string opcodeName;
#if DEBUG
                    //Debugger.Launch();
                    opcodeName = node.Code.ToString();
#else
                    opcodeName = ((int)node.Code).ToString();
#endif
                    var source = FormatSource(node);
                    var msg = string.Format("Unexpected opcode {0} in {1}.", opcodeName, source);
                    throw new ArgumentException(msg);
            }
        }
        private MethodBody CreateCloneBody(MethodDefinition ctor, ClassDefinition @class)
        {
            MethodBody body = new MethodBody(null);
            var ins = body.Instructions;

            Register rthis       = body.AllocateRegister(RCategory.Argument, RType.Object);
            Register rInvList    = body.AllocateRegister(RCategory.Argument, RType.Object);
            Register rInvListLen = body.AllocateRegister(RCategory.Argument, RType.Value);

            Register result     = body.AllocateRegister(RCategory.Temp, RType.Object);

            List<Register> ctorArgs = new List<Register> { result };

            if (instanceField != null)
            {
                var rInstance = body.AllocateRegister(RCategory.Temp, RType.Object);
                ins.Add(new Instruction(RCode.Iget_object, instanceField, new[] {rInstance, rthis}));
                ctorArgs.Add(rInstance);
            }

            foreach (var field in GenericTypeFields)
            {
                var r = body.AllocateRegister(RCategory.Temp, RType.Object);
                ins.Add(new Instruction(RCode.Iget_object, field, new[] { r, rthis }));
                ctorArgs.Add(r);
            }

            ins.Add(new Instruction(RCode.New_instance, @class, new[] {result}));
            ins.Add(new Instruction(RCode.Invoke_direct, ctor, ctorArgs.ToArray()));

            var invListLengthReference = new FieldReference(multicastDelegateClass, "InvocationListLength", PrimitiveType.Int);
            var multicastDelegateArray = new ArrayType(multicastDelegateClass);
            var invListReference = new FieldReference(multicastDelegateClass, "InvocationList", multicastDelegateArray);

            ins.Add(new Instruction(RCode.Iput_object, invListReference, new []{ rInvList, result}));
            ins.Add(new Instruction(RCode.Iput, invListLengthReference, new[] { rInvListLen, result }));
            
            ins.Add(new Instruction(RCode.Return_object, null, new []{result}));
            return body;
        }
        /// <summary>
        /// Create the body of the invoke method.
        /// </summary>
        /// <param name="calledMethodPrototype"></param>
        private MethodBody CreateInvokeBody(Prototype calledMethodPrototype)
        {
            var body = new MethodBody(null);
            var rthis = body.AllocateRegister(RCategory.Argument, RType.Object);
            foreach (var p in invokePrototype.Parameters)
            {
                if (p.Type.IsWide())
                {
                    body.AllocateWideRegister(RCategory.Argument);
                }
                else
                {
                    var type = (p.Type is PrimitiveType) ? RType.Value : RType.Object;
                    body.AllocateRegister(RCategory.Argument, type);
                }
            }
            var incomingMethodArgs = body.Registers.ToArray();

            // Create code
            var ins = body.Instructions;
            Register instanceReg = null;
            if (!calledMethod.IsStatic)
            {
                // load instance
                instanceReg = body.AllocateRegister(RCategory.Temp, RType.Object);
                ins.Add(new Instruction(RCode.Iget_object, instanceReg, rthis) { Operand = instanceField });
            }

            List<Register> genericTypeParameterRegs = new List<Register>(); 
            foreach(var field in GenericTypeFields)
            {
                var r = body.AllocateRegister(RCategory.Temp, RType.Object);
                ins.Add(new Instruction(RCode.Iget_object, r, rthis) { Operand = field });
                genericTypeParameterRegs.Add(r);
            }

            // Invoke
            var calledMethodRef = calledMethod.GetReference(targetPackage);
            var inputArgs = calledMethod.IsStatic ? incomingMethodArgs.Skip(1).ToArray() : incomingMethodArgs;
            
            // Cast arguments (if needed)
            var outputArgs = new List<Register>();
            if (!calledMethod.IsStatic)
            {
                outputArgs.Add(instanceReg);
            }
            var parameterIndex = 0;
            for (var i = calledMethod.IsStatic ? 0 : 1; i < inputArgs.Length; )
            {
                var invokeType = invokePrototype.Parameters[parameterIndex].Type;
                var inputIsWide = invokeType.IsWide();
                var calledType = calledMethodPrototype.Parameters[parameterIndex].Type;
                if (!invokeType.Equals(calledType))
                {
                    // Add cast / unbox
                    var source = inputIsWide
                                     ? new RegisterSpec(inputArgs[i], inputArgs[i + 1], invokeType)
                                     : new RegisterSpec(inputArgs[i], null, invokeType);
                    var tmp = ins.Unbox(sequencePoint, source, calledMethod.Parameters[parameterIndex].ParameterType, compiler, targetPackage, body);
                    outputArgs.Add(tmp.Result.Register);
                    if (calledType.IsWide())
                    {
                        outputArgs.Add(tmp.Result.Register2);
                    }
                }
                else
                {
                    outputArgs.Add(inputArgs[i]);
                    if (calledType.IsWide())
                    {
                        outputArgs.Add(inputArgs[i + 1]);
                    }
                }
                i += inputIsWide ? 2 : 1;
                parameterIndex++;
            }

            outputArgs.AddRange(genericTypeParameterRegs);

            // Actual call
            ins.Add(new Instruction(calledMethod.Invoke(calledMethod, null), calledMethodRef, outputArgs.ToArray()));

            // Collect return value
            var invokeReturnType = invokePrototype.ReturnType;
            var calledReturnType = calledMethodPrototype.ReturnType;
            var needsBoxing = !invokeReturnType.Equals(calledReturnType);
            Instruction returnInstruction;
            Instruction nextMoveResultInstruction = null;

            if (calledReturnType.IsWide())
            {
                var r = body.AllocateWideRegister(RCategory.Temp);
                ins.Add(new Instruction(RCode.Move_result_wide, r.Item1));
                if (needsBoxing)
                {
                    // Box
                    var source = new RegisterSpec(r.Item1, r.Item2, calledReturnType);
                    var tmp = ins.Box(sequencePoint, source, calledMethod.ReturnType, targetPackage, body);
                    returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register);
                    nextMoveResultInstruction = new Instruction(RCode.Move_result_object, tmp.Result.Register);
                }
                else
                {
                    // Return wide
                    returnInstruction = new Instruction(RCode.Return_wide, r.Item1);
                    nextMoveResultInstruction = new Instruction(RCode.Move_result_wide, r.Item1);
                }
            }
            else if (calledMethod.ReturnType.IsVoid())
            {
                // Void return
                returnInstruction = new Instruction(RCode.Return_void);
            }
            else if (calledReturnType is PrimitiveType)
            {
                // Single register return
                var r = body.AllocateRegister(RCategory.Temp, RType.Value);
                ins.Add(new Instruction(RCode.Move_result, r));
                if (needsBoxing)
                {
                    // Box
                    var source = new RegisterSpec(r, null, invokeReturnType);
                    var tmp = ins.Box(sequencePoint, source, calledMethod.ReturnType, targetPackage, body);
                    returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register);
                    nextMoveResultInstruction = new Instruction(RCode.Move_result_object, tmp.Result.Register);
                }
                else
                {
                    // Return 
                    returnInstruction = new Instruction(RCode.Return, r);
                    nextMoveResultInstruction = new Instruction(RCode.Move_result, r);
                }
            }
            else
            {
                var r = body.AllocateRegister(RCategory.Temp, RType.Object);
                ins.Add(new Instruction(RCode.Move_result_object, r));
                if (needsBoxing)
                {
                    // Box
                    var source = new RegisterSpec(r, null, invokeReturnType);
                    var tmp = ins.Box(sequencePoint, source, invokeMethod.ReturnType, targetPackage, body);
                    returnInstruction = new Instruction(RCode.Return_object, tmp.Result.Register);
                    nextMoveResultInstruction = new Instruction(RCode.Move_result_object, tmp.Result.Register);
                }
                else
                {
                    // Return 
                    returnInstruction = new Instruction(RCode.Return_object, r);
                    nextMoveResultInstruction = new Instruction(RCode.Move_result_object, r);
                }
            }

            // Call delegate list
            var multicastDelegateType = new ClassReference(targetPackage.NameConverter.GetConvertedFullName("System.MulticastDelegate"));
            var invListLengthReference = new FieldReference(multicastDelegateType, "InvocationListLength", PrimitiveType.Int);
            var multicastDelegateArray = new ArrayType(multicastDelegateType);
            var invListReference = new FieldReference(multicastDelegateType, "InvocationList", multicastDelegateArray);

            var index = body.AllocateRegister(RCategory.Temp, RType.Value);
            var count = body.AllocateRegister(RCategory.Temp, RType.Value);
            var next = body.AllocateRegister(RCategory.Temp, RType.Object);
            var invList = body.AllocateRegister(RCategory.Temp, RType.Object);

            var done = new Instruction(RCode.Nop);

            var nextInvokeMethod = new MethodReference(delegateClass, "Invoke", invokePrototype);
            var nextInvokeArgs = new[] { next }.Concat(incomingMethodArgs.Skip(1)).ToArray();

            ins.Add(new Instruction(RCode.Iget, invListLengthReference, new[] {count, rthis}));
            ins.Add(new Instruction(RCode.If_eqz, done, new[] { count }));
            ins.Add(new Instruction(RCode.Const, 0, new[] { index }));
            ins.Add(new Instruction(RCode.Iget_object, invListReference, new[] {invList, rthis}));

            var getNext = new Instruction(RCode.Aget_object, null, new[] { next, invList, index });
            ins.Add(getNext);
            ins.Add(new Instruction(RCode.Check_cast, delegateClass, new [] { next }));
            ins.Add(new Instruction(RCode.Invoke_virtual, nextInvokeMethod, nextInvokeArgs));
            
            if (nextMoveResultInstruction != null)
                ins.Add(nextMoveResultInstruction);

            ins.Add(new Instruction(RCode.Add_int_lit8, 1, new[] { index, index }));
            ins.Add(new Instruction(RCode.If_lt, getNext, new[] { index, count }));

            ins.Add(done);

            // Add return instructions
            ins.Add(returnInstruction);

            return body;
        }
Example #9
0
 // for prefetching
 internal FieldDefinition(FieldReference fref) : this()
 {
     Owner = fref.Owner as ClassDefinition;
     Type  = fref.Type;
     Name  = fref.Name;
 }
Example #10
0
 /// <summary>
 /// Is other equal to this?
 /// </summary>
 public bool Equals(FieldReference other)
 {
     return((other != null) && Owner.Equals(other.Owner) && Name.Equals(other.Name) && Type.Equals(other.Type));
 }