示例#1
0
    private static void VisitLocalLoads(CodeInfo codeInfo, ClassFile.Method method, List <LocalVar> locals, Dictionary <long, LocalVar> localByStoreSite, Dictionary <int, string> storeSites, int instructionIndex, bool debug)
    {
        Debug.Assert(IsLoadLocal(method.Instructions[instructionIndex].NormalizedOpCode));
        LocalVar    local      = null;
        TypeWrapper type       = VerifierTypeWrapper.Null;
        int         localIndex = method.Instructions[instructionIndex].NormalizedArg1;
        bool        isArg      = false;

        foreach (int store in storeSites.Keys)
        {
            if (store == -1)
            {
                // it's a method argument, it has no initial store, but the type is simply the parameter type
                type  = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(0, localIndex));
                isArg = true;
            }
            else
            {
                if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__invokespecial)
                {
                    type = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(store + 1, localIndex));
                }
                else if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__static_error)
                {
                    // it's an __invokespecial that turned into a __static_error
                    // (since a __static_error doesn't continue, we don't need to set type)
                }
                else
                {
                    Debug.Assert(IsStoreLocal(method.Instructions[store].NormalizedOpCode));
                    type = InstructionState.FindCommonBaseType(type, codeInfo.GetStackTypeWrapper(store, 0));
                }
            }
            // we can't have an invalid type, because that would have failed verification earlier
            Debug.Assert(type != VerifierTypeWrapper.Invalid);

            LocalVar l;
            if (localByStoreSite.TryGetValue(MakeKey(store, localIndex), out l))
            {
                if (local == null)
                {
                    local = l;
                }
                else if (local != l)
                {
                    // If we've already defined a LocalVar and we find another one, then we merge them
                    // together.
                    // This happens for the following code fragment:
                    //
                    // int i = -1;
                    // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {}
                    // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {}
                    // System.out.println(i);
                    //
                    local = MergeLocals(locals, localByStoreSite, local, l);
                }
            }
        }
        if (local == null)
        {
            local       = new LocalVar();
            local.local = localIndex;
            if (VerifierTypeWrapper.IsThis(type))
            {
                local.type = ((VerifierTypeWrapper)type).UnderlyingType;
            }
            else
            {
                local.type = type;
            }
            local.isArg = isArg;
            if (debug)
            {
                FindLvtEntry(local, method, instructionIndex);
            }
            locals.Add(local);
        }
        else
        {
            local.isArg |= isArg;
            local.type   = InstructionState.FindCommonBaseType(local.type, type);
            Debug.Assert(local.type != VerifierTypeWrapper.Invalid);
        }
        foreach (int store in storeSites.Keys)
        {
            LocalVar v;
            if (!localByStoreSite.TryGetValue(MakeKey(store, localIndex), out v))
            {
                localByStoreSite[MakeKey(store, localIndex)] = local;
            }
            else if (v != local)
            {
                local = MergeLocals(locals, localByStoreSite, local, v);
            }
        }
    }