Example #1
0
        int InitLocalsArgs(CilMethod myMethod, List <CilType> localTypes)
        {
            var     parameters = myMethod.WithGenericParameters.Parameters;
            int     numArgs    = parameters.Count;
            CilType thisType;

            if (myMethod.HasThisArg)
            {
                if (myMethod.IsConstructor)
                {
                    thisType = CilType.From(JavaStackMap.UninitializedThis);
                }
                else
                {
                    thisType = myMethod.DeclType;
                    if (thisType.IsValueClass)
                    {
                        thisType = thisType.MakeByRef();
                    }
                }
                stackMap.SetLocal(0, thisType);
                numArgs++;
            }
            else
            {
                thisType = null;
            }

            argToLocalMap = new int[numArgs];
            int nextArg   = 0;
            int nextIndex = 0;

            if (thisType != null)
            {
                argToLocalMap[nextArg++] = nextIndex++;
                localTypes.Add(thisType);
                numArgs--;
            }

            for (int i = 0; i < numArgs; i++)
            {
                var argType = (CilType)parameters[i].Type;
                stackMap.SetLocal(nextIndex, argType);

                var genericType = argType.GetMethodGenericParameter();
                if (genericType != null)
                {
                    if (genericType.IsArray && genericType.IsGenericParameter)
                    {
                        // note that GenericArrayType is compared by reference
                        // in CodeArrays, to detect an array of a generic type T[]
                        argType = CodeArrays.GenericArrayType;
                    }
                    else
                    {
                        argType = genericType;
                    }
                }

                argToLocalMap[nextArg++] = nextIndex;
                nextIndex += argType.Category;

                localTypes.Add(argType);
                while (nextIndex > localTypes.Count)
                {
                    localTypes.Add(null);
                }
            }

            return(nextIndex);
        }
Example #2
0
        void Translate_Endfinally(int instOffset, bool setupFaultClause = false)
        {
            var thisClause = RollbackStackFrame(instOffset);

            if (thisClause == null || (!thisClause.finallyClause))
            {
                throw new InvalidProgramException();
            }

            int localIndex = -1;

            if (thisClause.hasNestedTry)
            {
                localIndex = thisClause.tryClause.localIndex;
                stackMap.SetLocal(localIndex, ThrowableType);
            }

            if (thisClause.faultClause && (!setupFaultClause))
            {
                // if this instruction appears in a 'fault' clause,
                // then it should be interpreted as 'endfault' rather
                // than 'endfilter', and just rethrow the exception
                if (thisClause.hasNestedTry)
                {
                    code.NewInstruction(0x19 /* aload */, null, localIndex);
                }
                code.NewInstruction(0xBF /* athrow */, null, null);
                return;
            }

            //
            // typical variant of a non-nested 'endfinally' instruction.
            // proceed to the specified leave offset, or rethrow the exception.
            //

            if (!thisClause.hasNestedTry)
            {
                localIndex = locals.GetTempIndex(ThrowableType);
                stackMap.SetLocal(localIndex, JavaStackMap.Top);

                stackMap.PushStack(ThrowableType);
                code.NewInstruction(0x3A /* astore */, null, localIndex);
                stackMap.PopStack(CilMain.Where);
            }

            // if a try/catch exits due to non-exceptional control flow, then
            // the exception object will be a 'fake' exception object created
            // in Translate_Leave, see there.  we have to identify this, and
            // branch accordingly.

            if (thisClause.leaveOffsets != null)
            {
                code.NewInstruction(0x19 /* aload */, null, localIndex);
                code.NewInstruction(0xB8 /* invokestatic */, LeaveTargetType,
                                    new JavaMethodRef("Get", JavaType.IntegerType, ThrowableType));

                int leaveIndex = -1;
                if (thisClause.leaveOffsets.Count != 1)
                {
                    leaveIndex = locals.GetTempIndex(JavaType.IntegerType);
                    code.NewInstruction(0x36 /* istore */, null, leaveIndex);
                }

                foreach (var leaveOffset in thisClause.leaveOffsets)
                {
                    if (leaveIndex != -1)
                    {
                        code.NewInstruction(0x15 /* iload */, null, leaveIndex);
                    }
                    stackMap.PushStack(JavaType.IntegerType);
                    code.NewInstruction(0x12 /* ldc */, null, (int)leaveOffset);
                    stackMap.PushStack(JavaType.IntegerType);
                    code.NewInstruction(0x9F /* if_icmpeq */, null, leaveOffset);
                    stackMap.PopStack(CilMain.Where);
                    stackMap.PopStack(CilMain.Where);
                    stackMap.SaveFrame(leaveOffset, true, CilMain.Where);
                }

                if (leaveIndex != -1)
                {
                    locals.FreeTempIndex(localIndex);
                }
            }

            // if the try/catch did exit due to an exception cause, then we
            // just need to rethrow the exception.

            code.NewInstruction(0x19 /* aload */, null, localIndex);
            if (setupFaultClause)
            {
                // if called from ExceptionClauseSetup to setup a 'fault' clause,
                // then we just want to put the exception back on the stack
                stackMap.PushStack(ThrowableType);
            }
            else
            {
                // if called to end a 'finally' clause, then we do want to throw
                code.NewInstruction(0xBF /* athrow */, null, null);
            }

            if (!thisClause.hasNestedTry)
            {
                // if this 'endfinally' instruction is the last in the clause,
                // then we can release the local index that holds the exception

                if (instOffset + 1 == thisClause.catchEnd)
                {
                    locals.FreeTempIndex(localIndex);
                }
            }
        }