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); }
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); } } }