Beispiel #1
0
        /// <summary>
        /// Creates a papyrus call instruction.
        /// </summary>
        /// <param name="mainInstructionProcessor">The main instruction processor.</param>
        /// <param name="callOpCode">The call op code.</param>
        /// <param name="methodRef">The method reference.</param>
        /// <param name="callerLocation">The caller location.</param>
        /// <param name="destinationVariable">The destination variable.</param>
        /// <param name="parameters">The parameters.</param>
        /// <param name="structGets">The structure gets.</param>
        /// <param name="methodName">Name of the method.</param>
        /// <returns></returns>
        public PapyrusInstruction CreatePapyrusCallInstruction(
            IClrInstructionProcessor mainInstructionProcessor,
            PapyrusOpCodes callOpCode, MethodReference methodRef,
            string callerLocation, string destinationVariable, List <object> parameters,
            out List <PapyrusInstruction> structGets, string methodName = null)
        {
            structGets = new List <PapyrusInstruction>();

            var inst = new PapyrusInstruction {
                OpCode = callOpCode
            };

            var param = parameters.ToArray();

            for (var index = 0; index < param.Length; index++)
            {
                var p = param[index];
                PapyrusStructFieldReference structRef = null;
                var evalItem = p as EvaluationStackItem;

                if (evalItem != null)
                {
                    structRef = evalItem.Value as PapyrusStructFieldReference;
                }
                if (structRef == null)
                {
                    structRef = p as PapyrusStructFieldReference;
                }
                if (structRef != null)
                {
                    var structSource = structRef.StructSource as PapyrusFieldDefinition;
                    var structField  = structRef.StructVariable;

                    var fieldType = GetStructFieldType(papyrusAssemblyCollection, structSource, structField);

                    // 1. Create Temp Var
                    bool isStructAccess;
                    var  tempVar = mainInstructionProcessor.GetTargetVariable(currentInstruction, null,
                                                                              out isStructAccess,
                                                                              fieldType, true);

                    param[index] = mainInstructionProcessor.CreateVariableReferenceFromName(tempVar);

                    // 2. StructGet -> tempVar
                    // 3. Assign var <- tempVar
                    structGets.Add(mainInstructionProcessor.CreatePapyrusInstruction(
                                       PapyrusOpCodes.StructGet,
                                       mainInstructionProcessor.CreateVariableReferenceFromName(tempVar), structSource,
                                       structField));
                }
            }

            methodName = methodName ?? methodRef.Name;

            if (callOpCode == PapyrusOpCodes.Callstatic)
            {
                inst.Arguments.AddRange(mainInstructionProcessor.ParsePapyrusParameters(new object[]
                {
                    mainInstructionProcessor.CreateVariableReference(PapyrusPrimitiveType.Reference, callerLocation),
                    mainInstructionProcessor.CreateVariableReference(PapyrusPrimitiveType.Reference, methodName),
                    mainInstructionProcessor.CreateVariableReference(PapyrusPrimitiveType.Reference, destinationVariable)
                }));
            }
            else
            {
                inst.Arguments.AddRange(mainInstructionProcessor.ParsePapyrusParameters(new object[]
                {
                    mainInstructionProcessor.CreateVariableReference(PapyrusPrimitiveType.Reference, methodName),
                    mainInstructionProcessor.CreateVariableReference(PapyrusPrimitiveType.Reference, callerLocation),
                    mainInstructionProcessor.CreateVariableReference(PapyrusPrimitiveType.Reference, destinationVariable)
                }));
            }
            inst.OperandArguments.AddRange(EnsureParameterTypes(mainInstructionProcessor, methodRef.Parameters,
                                                                mainInstructionProcessor.ParsePapyrusParameters(param)));
            inst.Operand = methodRef;
            return(inst);
        }
Beispiel #2
0
        /// <summary>
        /// Parses the instruction.
        /// </summary>
        /// <param name="mainProcessor">The processor.</param>
        /// <param name="asmCollection">The papyrus assembly collection.</param>
        /// <param name="instruction">The instruction.</param>
        /// <param name="targetMethod">The target method.</param>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        /// <exception cref="MissingVariableException"></exception>
        public IEnumerable <PapyrusInstruction> Process(
            IClrInstructionProcessor mainProcessor,
            IReadOnlyCollection <PapyrusAssemblyDefinition> asmCollection,
            Instruction instruction,
            MethodDefinition targetMethod, TypeDefinition type)
        {
            bool isStructAccess;
            var  outputInstructions = new List <PapyrusInstruction>();

            if (InstructionHelper.NextInstructionIs(instruction, Code.Ldnull) &&
                InstructionHelper.NextInstructionIs(instruction.Next, Code.Cgt_Un))
            {
                var stack = mainProcessor.EvaluationStack;
                //var itemToCheck = stack.Pop().Value;
                var itemToCheck = instruction.Operand as FieldReference;

                if (itemToCheck != null)
                {
                    mainProcessor.EvaluationStack.Push(
                        new EvaluationStackItem
                    {
                        Value    = itemToCheck,
                        TypeName = ""
                    }
                        );
                    mainProcessor.EvaluationStack.Push(
                        new EvaluationStackItem
                    {
                        Value    = null,
                        TypeName = "none"
                    }
                        );

                    mainProcessor.SkipToOffset =
                        InstructionHelper.NextInstructionIsOffset(instruction.Next, Code.Cgt_Un) - 1;

                    //bool structAccess;
                    //var targetVar = mainInstructionProcessor.GetTargetVariable(tarInstruction, null, out structAccess, "Bool");

                    //if (mainInstructionProcessor.SkipNextInstruction)
                    //{
                    //    mainInstructionProcessor.SkipToOffset += 2;
                    //    mainInstructionProcessor.SkipNextInstruction = false;
                    //}

                    //outputInstructions.Add(mainInstructionProcessor.CreatePapyrusInstruction(PapyrusOpCodes.Is,
                    //    mainInstructionProcessor.CreateVariableReferenceFromName(targetVar), fieldDef,
                    //    mainInstructionProcessor.CreateVariableReferenceFromName(typeToCheckAgainst.Name)));
                    return(outputInstructions);
                }
            }

            if (InstructionHelper.IsLoadMethodRef(instruction.OpCode.Code))
            {
                // Often used for delegates or Action/func parameters, when loading a reference pointer to a method and pushing it to the stack.
                // To maintain the evaluation stack, this could add a dummy item, but for now im not going to do so.
            }

            if (InstructionHelper.IsLoadLength(instruction.OpCode.Code))
            {
                var popCount = Utility.GetStackPopCount(instruction.OpCode.StackBehaviourPop);
                if (mainProcessor.EvaluationStack.Count >= popCount)
                {
                    var val = mainProcessor.EvaluationStack.Pop();
                    if (val.TypeName.EndsWith("[]"))
                    {
                        if (val.Value is PapyrusPropertyDefinition)
                        {
                            // for now, so if this exception is thrown, i will have to remember I have to fix it.
                            throw new NotImplementedException();
                        }

                        if (val.Value is PapyrusVariableReference || val.Value is PapyrusFieldDefinition ||
                            val.Value is PapyrusParameterDefinition)
                        {
                            int variableIndex;

                            var storeInstruction =
                                mainProcessor.GetNextStoreLocalVariableInstruction(instruction,
                                                                                   out variableIndex);

                            if (storeInstruction != null ||
                                InstructionHelper.IsConverToNumber(instruction.Next.OpCode.Code))
                            {
                                if (InstructionHelper.IsConverToNumber(instruction.Next.OpCode.Code))
                                {
                                    mainProcessor.SkipNextInstruction = false;
                                    mainProcessor.SkipToOffset        = 0;

                                    var targetVariableName = mainProcessor.GetTargetVariable(instruction,
                                                                                             null, out isStructAccess, "Int", true);

                                    var allVars        = mainProcessor.PapyrusMethod.GetVariables();
                                    var targetVariable = allVars.FirstOrDefault(v => v.Name.Value == targetVariableName);

                                    if (targetVariable == null &&
                                        mainProcessor.PapyrusCompilerOptions == PapyrusCompilerOptions.Strict)
                                    {
                                        throw new MissingVariableException(targetVariableName);
                                    }
                                    if (targetVariable != null)
                                    {
                                        mainProcessor.EvaluationStack.Push(new EvaluationStackItem
                                        {
                                            TypeName = targetVariable.TypeName.Value,
                                            Value    = targetVariable
                                        });

                                        outputInstructions.Add(
                                            mainProcessor.CreatePapyrusInstruction(
                                                PapyrusOpCodes.ArrayLength,
                                                mainProcessor.CreateVariableReference(
                                                    PapyrusPrimitiveType.Reference, targetVariableName), val.Value));
                                    }
                                }
                                else
                                {
                                    var allVars = mainProcessor.PapyrusMethod.GetVariables();

                                    mainProcessor.EvaluationStack.Push(new EvaluationStackItem
                                    {
                                        TypeName = allVars[variableIndex].TypeName.Value,
                                        Value    = allVars[variableIndex]
                                    });

                                    outputInstructions.Add(
                                        mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.ArrayLength,
                                                                               allVars[variableIndex], val.Value));

                                    //return "ArrayLength " + allVars[variableIndex].Name + " " +
                                    //       (val.Value as VariableReference).Name;
                                }
                            }
                        }
                    }
                }
                // ArrayLength <outputVariableName> <arrayName>
            }


            if (InstructionHelper.IsLoadArgs(instruction.OpCode.Code))
            {
                var index = (int)mainProcessor.GetNumericValue(instruction);
                if (targetMethod.IsStatic && index == 0 && targetMethod.Parameters.Count == 0)
                {
                    mainProcessor.EvaluationStack.Push(new EvaluationStackItem
                    {
                        IsThis   = true,
                        Value    = type,
                        TypeName = type.FullName
                    });
                }
                else
                {
                    if (targetMethod.HasThis && index == 0)
                    {
                        return(outputInstructions);
                    }

                    if (!targetMethod.IsStatic && index > 0)
                    {
                        index--;
                    }
                    if (index < mainProcessor.PapyrusMethod.Parameters.Count)
                    {
                        mainProcessor.EvaluationStack.Push(new EvaluationStackItem
                        {
                            Value    = mainProcessor.PapyrusMethod.Parameters[index],
                            TypeName = mainProcessor.PapyrusMethod.Parameters[index].TypeName.Value
                        });
                    }
                }
            }
            if (InstructionHelper.IsLoadInteger(instruction.OpCode.Code))
            {
                var index = mainProcessor.GetNumericValue(instruction);
                mainProcessor.EvaluationStack.Push(new EvaluationStackItem {
                    Value = index, TypeName = "Int"
                });
            }

            if (InstructionHelper.IsLoadNull(instruction.OpCode.Code))
            {
                mainProcessor.EvaluationStack.Push(new EvaluationStackItem
                {
                    Value    = "None",
                    TypeName = "None"
                });
            }

            if (InstructionHelper.IsLoadLocalVariable(instruction.OpCode.Code))
            {
                var index        = (int)mainProcessor.GetNumericValue(instruction);
                var allVariables = mainProcessor.PapyrusMethod.GetVariables();
                if (index < allVariables.Count)
                {
                    mainProcessor.EvaluationStack.Push(new EvaluationStackItem
                    {
                        Value    = allVariables[index],
                        TypeName = allVariables[index].TypeName.Value
                    });
                }
            }

            if (InstructionHelper.IsLoadString(instruction.OpCode.Code))
            {
                var value = StringUtility.AsString(instruction.Operand);

                mainProcessor.EvaluationStack.Push(new EvaluationStackItem
                {
                    Value    = value,
                    TypeName = "String"
                });
            }

            if (InstructionHelper.IsLoadFieldObject(instruction.OpCode.Code))
            {
                if (instruction.Operand is FieldReference)
                {
                    var fieldRef = instruction.Operand as FieldReference;


                    PapyrusFieldDefinition targetField = null;

                    targetField = mainProcessor.PapyrusType.Fields.FirstOrDefault(
                        f => f.Name.Value == "::" + fieldRef.Name.Replace('<', '_').Replace('>', '_'));

                    if (targetField == null)
                    {
                        targetField = mainProcessor.GetDelegateField(fieldRef);
                    }


                    if (targetField != null)
                    {
                        mainProcessor.EvaluationStack.Push(new EvaluationStackItem
                        {
                            Value    = targetField,
                            TypeName = targetField.TypeName
                        });
                    }

                    if (InstructionHelper.PreviousInstructionWas(instruction, Code.Ldflda) &&
                        fieldRef.FullName.Contains("/"))
                    {
                        var targetStructVariable = mainProcessor.EvaluationStack.Pop().Value;

                        var structRef = new PapyrusStructFieldReference(mainProcessor.PapyrusAssembly, null)
                        {
                            StructSource   = targetStructVariable,
                            StructVariable = mainProcessor.CreateVariableReferenceFromName(fieldRef.Name)
                        };

                        mainProcessor.EvaluationStack.Push(new EvaluationStackItem
                        {
                            Value    = structRef,
                            TypeName = "$StructAccess$"
                        });

                        return(outputInstructions);

                        //    // The target field is not inside the declared type.
                        //    // Most likely, this is a get field from struct.
                        //    if (fieldRef.FieldType.FullName.Contains("/"))
                        //    {
                        //        var location = fieldRef.FieldType.FullName.Split("/").LastOrDefault();

                        //        var targetStruct = mainInstructionProcessor.PapyrusType.NestedTypes.FirstOrDefault(n => n.Name.Value == location);
                        //        if (targetStruct != null)
                        //        {

                        //            targetField = mainInstructionProcessor.PapyrusType.Fields.FirstOrDefault(
                        //                f => f.Name.Value == "::" + fieldRef.Name);
                        //            // var stack = mainInstructionProcessor.EvaluationStack;
                        //            // TODO: Add support for getting values from Structs
                        //            //
                        //            // CreatePapyrusInstruction(PapyrusOpCode.StructGet, ...)
                        //        }
                        //    }
                    }
                    //else
                    //{
                    //    targetField = mainInstructionProcessor.PapyrusType.Fields.FirstOrDefault(
                    //        f => f.Name.Value == "::" + fieldRef.Name.Replace('<', '_').Replace('>', '_'));
                    //}
                }
            }


            if (InstructionHelper.IsLoadElement(instruction.OpCode.Code))
            {
                // TODO: Load Element (Arrays, and what not)
                var popCount = Utility.GetStackPopCount(instruction.OpCode.StackBehaviourPop);
                if (mainProcessor.EvaluationStack.Count >= popCount)
                {
                    var itemIndex = mainProcessor.EvaluationStack.Pop();
                    var itemArray = mainProcessor.EvaluationStack.Pop();

                    object targetItemIndex = null;

                    var targetItemArray = itemArray.Value;

                    if (itemIndex.Value != null)
                    {
                        targetItemIndex = itemIndex.Value;
                    }

                    // 128 is the array size limit for Skyrim
                    if (mainProcessor.PapyrusAssembly.VersionTarget == PapyrusVersionTargets.Skyrim)
                    {
                        if ((targetItemIndex as int?) > 128)
                        {
                            targetItemIndex = 128;
                        }
                    }

                    // We want to use the Array Element together with a Method Call?
                    var isBoxing = InstructionHelper.IsBoxing(instruction.Next.OpCode.Code);
                    if (isBoxing || InstructionHelper.IsCallMethod(instruction.Next.OpCode.Code))
                    {
                        if (isBoxing)
                        {
                            var sourceArray = targetItemArray as PapyrusVariableReference;
                            if (sourceArray != null)
                            {
                                // Since we apply our logic necessary for this "boxing" right here
                                // we can skip the next instruction to avoid unexpected behaviour.
                                mainProcessor.SkipNextInstruction = true;

                                // Create a new Temp Variable
                                // Assign our value to this temp variable and push it to the stack
                                // so that the next instruction can take care of it.
                                var tempVariableType = sourceArray.TypeName.Value.Replace("[]", "");

                                var destinationTempVar = mainProcessor.GetTargetVariable(instruction, null,
                                                                                         out isStructAccess, tempVariableType, true);

                                var varRef =
                                    mainProcessor.PapyrusMethod.GetVariables()
                                    .FirstOrDefault(n => n.Name.Value == destinationTempVar);

                                mainProcessor.EvaluationStack.Push(new EvaluationStackItem
                                {
                                    Value = varRef ?? (object)destinationTempVar,
                                    // Should be the actual variable reference
                                    TypeName = tempVariableType
                                });

                                outputInstructions.Add(
                                    mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.ArrayGetElement,
                                                                           mainProcessor.CreateVariableReference(
                                                                               PapyrusPrimitiveType.Reference, destinationTempVar),
                                                                           targetItemArray,
                                                                           targetItemIndex));
                            }
                        }
                        else
                        {
                            // Get the method reference and then create a temp variable that
                            // we can use for assigning the value to.
                            var methodRef = instruction.Next.Operand as MethodReference;
                            if (methodRef != null && methodRef.HasParameters)
                            {
                                var sourceArray = targetItemArray as PapyrusVariableReference;
                                if (sourceArray != null)
                                {
                                    var tempVariableType   = sourceArray.TypeName.Value.Replace("[]", "");
                                    var destinationTempVar = mainProcessor.GetTargetVariable(instruction,
                                                                                             methodRef, out isStructAccess,
                                                                                             tempVariableType);

                                    // "ArrayGetElement " + destinationTempVar + " " + targetItemArray + " " + targetItemIndex;
                                    outputInstructions.Add(
                                        mainProcessor.CreatePapyrusInstruction(
                                            PapyrusOpCodes.ArrayGetElement,
                                            mainProcessor.CreateVariableReference(
                                                PapyrusPrimitiveType.Reference, destinationTempVar),
                                            targetItemArray,
                                            targetItemIndex));
                                }
                            }
                        }
                    }
                    else
                    {
                        // Otherwise we just want to store it somewhere.
                        int destinationVariableIndex;
                        // Get the target variable by finding the next store instruction and returning the variable index.
                        mainProcessor.GetNextStoreLocalVariableInstruction(instruction,
                                                                           out destinationVariableIndex);
                        var destinationVar =
                            mainProcessor.PapyrusMethod.GetVariables()[destinationVariableIndex];

                        // ArrayGetElement targetVariable targetItemArray targetItemIndex
                        outputInstructions.Add(
                            mainProcessor.CreatePapyrusInstruction(PapyrusOpCodes.ArrayGetElement,
                                                                   destinationVar,
                                                                   targetItemArray,
                                                                   targetItemIndex)
                            );
                    }
                }
            }
            return(outputInstructions);
        }
Beispiel #3
0
        private IEnumerable <PapyrusInstruction> ProcessPropertyAccess(IClrInstructionProcessor mainInstructionProcessor, Instruction instruction, MethodReference methodRef,
                                                                       MethodDefinition methodDefinition,
                                                                       List <object> parameters)
        {
            bool isStructAccess;
            var  instructions = new List <PapyrusInstruction>();

            if (methodRef is MethodDefinition)
            {
                methodDefinition = methodRef as MethodDefinition;
            }

            // If the property access is from outside the same class (Property exists outside the calling class)
            if (methodDefinition == null && methodRef != null)
            {
                var type               = methodRef.DeclaringType;
                var methodType         = methodRef.Name.Remove(3);
                var targetPropertyName = methodRef.Name.Substring(4);

                if (methodType == "set")
                {
                    var param            = parameters;
                    var stack            = mainInstructionProcessor.EvaluationStack;
                    var locationVariable = stack.Pop().Value;
                    instructions.Add(mainInstructionProcessor.CreatePapyrusInstruction(PapyrusOpCodes.PropSet,
                                                                                       mainInstructionProcessor.CreateVariableReferenceFromName(targetPropertyName),
                                                                                       locationVariable,
                                                                                       param.First()
                                                                                       ));
                }
                else if (methodType == "get")
                {
                    var stack               = mainInstructionProcessor.EvaluationStack;
                    var locationVariable    = stack.Pop().Value;
                    var destinationVariable = mainInstructionProcessor.GetTargetVariable(instruction, methodRef,
                                                                                         out isStructAccess);

                    if (isStructAccess)
                    {
                        var structRef =
                            mainInstructionProcessor.EvaluationStack.Pop().Value as PapyrusStructFieldReference;
                        if (structRef != null)
                        {
                            // (Get Property Value and Assign Temp then do StructSet using Temp)
                            instructions.Add(mainInstructionProcessor.CreatePapyrusInstruction(PapyrusOpCodes.PropGet,
                                                                                               mainInstructionProcessor.CreateVariableReferenceFromName(targetPropertyName),
                                                                                               locationVariable,
                                                                                               mainInstructionProcessor.CreateVariableReferenceFromName(destinationVariable)
                                                                                               ));

                            // StructSet
                            instructions.Add(mainInstructionProcessor.CreatePapyrusInstruction(PapyrusOpCodes.StructSet,
                                                                                               structRef.StructSource, structRef.StructVariable,
                                                                                               mainInstructionProcessor.CreateVariableReferenceFromName(destinationVariable)));

                            // Skip next instruction as it should be stfld and we already store the field here.
                            mainInstructionProcessor.SkipNextInstruction = true;
                        }
                    }
                    else
                    {
                        instructions.Add(mainInstructionProcessor.CreatePapyrusInstruction(PapyrusOpCodes.PropGet,
                                                                                           mainInstructionProcessor.CreateVariableReferenceFromName(targetPropertyName),
                                                                                           locationVariable,
                                                                                           mainInstructionProcessor.CreateVariableReferenceFromName(destinationVariable)
                                                                                           ));
                    }
                }
                else
                {
                    throw new InvalidPropertyAccessException();
                }
                return(instructions);
            }

            // Property Access within same class (Property exists within the same class)
            if (methodDefinition != null)
            {
                var targetPropertyName = methodRef.Name.Substring(4);

                var matchingProperty = mainInstructionProcessor.PapyrusType.Properties.FirstOrDefault(
                    p => (p.SetMethod != null && p.SetMethod.Name.Value.ToLower().Equals(methodRef.Name.ToLower())) ||
                    (p.GetMethod != null && p.GetMethod.Name.Value.ToLower().Equals(methodRef.Name.ToLower())) ||
                    p.Name.Value.ToLower() == targetPropertyName.ToLower());
                if (matchingProperty != null)
                {
                    if (methodDefinition.IsSetter)
                    {
                        var param      = parameters;
                        var firstParam = param.First();
                        PapyrusStructFieldReference structRef = null;
                        var eva1 = firstParam as PapyrusStructFieldReference;
                        var eval = firstParam as EvaluationStackItem;
                        if (eval != null)
                        {
                            structRef = eval.Value as PapyrusStructFieldReference;
                        }
                        if (eva1 != null)
                        {
                            structRef = eva1;
                        }

                        if (structRef != null)
                        {
                            // Create Temp Var

                            // StructGet -> TempVar
                            // PropSet TempVar

                            var structSource = structRef.StructSource as PapyrusFieldDefinition;
                            var structField  = structRef.StructVariable;

                            var fieldType = GetStructFieldType(papyrusAssemblyCollection, structSource, structField);

                            // 1. Create Temp Var
                            var tempVar = mainInstructionProcessor.GetTargetVariable(instruction, null,
                                                                                     out isStructAccess,
                                                                                     fieldType, true);

                            // 2. StructGet -> tempVar
                            // 3. Assign var <- tempVar
                            instructions.Add(mainInstructionProcessor.CreatePapyrusInstruction(
                                                 PapyrusOpCodes.StructGet,
                                                 mainInstructionProcessor.CreateVariableReferenceFromName(tempVar), structSource,
                                                 structField));

                            instructions.Add(mainInstructionProcessor.CreatePapyrusInstruction(PapyrusOpCodes.PropSet,
                                                                                               mainInstructionProcessor.CreateVariableReferenceFromName(matchingProperty.Name.Value),
                                                                                               mainInstructionProcessor.CreateVariableReferenceFromName("self"),
                                                                                               mainInstructionProcessor.CreateVariableReferenceFromName(tempVar)
                                                                                               ));
                        }
                        else
                        {
                            instructions.Add(mainInstructionProcessor.CreatePapyrusInstruction(PapyrusOpCodes.PropSet,
                                                                                               mainInstructionProcessor.CreateVariableReferenceFromName(matchingProperty.Name.Value),
                                                                                               mainInstructionProcessor.CreateVariableReferenceFromName("self"),
                                                                                               firstParam
                                                                                               ));
                        }
                    }
                    else if (methodDefinition.IsGetter)
                    {
                        var destinationVariable = mainInstructionProcessor.GetTargetVariable(instruction, methodRef,
                                                                                             out isStructAccess);
                        var locationVariable = mainInstructionProcessor.CreateVariableReferenceFromName("self");
                        var targetProperty   =
                            mainInstructionProcessor.CreateVariableReferenceFromName(matchingProperty.Name.Value);
                        if (isStructAccess)
                        {
                            var structRef =
                                mainInstructionProcessor.EvaluationStack.Pop().Value as PapyrusStructFieldReference;
                            if (structRef != null)
                            {
                                // (Get Property Value and Assign Temp then do StructSet using Temp)
                                instructions.Add(
                                    mainInstructionProcessor.CreatePapyrusInstruction(PapyrusOpCodes.PropGet,
                                                                                      targetProperty,
                                                                                      locationVariable,
                                                                                      mainInstructionProcessor.CreateVariableReferenceFromName(destinationVariable)
                                                                                      ));

                                // StructSet
                                instructions.Add(
                                    mainInstructionProcessor.CreatePapyrusInstruction(PapyrusOpCodes.StructSet,
                                                                                      structRef.StructSource, structRef.StructVariable,
                                                                                      mainInstructionProcessor.CreateVariableReferenceFromName(destinationVariable)));

                                // Skip next instruction as it should be stfld and we already store the field here.
                                mainInstructionProcessor.SkipNextInstruction = true;
                            }
                        }
                        else
                        {
                            var dest = mainInstructionProcessor.CreateVariableReferenceFromName(destinationVariable);
                            instructions.Add(mainInstructionProcessor.CreatePapyrusInstruction(PapyrusOpCodes.PropGet,
                                                                                               targetProperty,
                                                                                               locationVariable,
                                                                                               dest
                                                                                               ));

                            if (InstructionHelper.NextInstructionIs(instruction, InstructionHelper.IsConditional))
                            {
                                mainInstructionProcessor.EvaluationStack.Push(new EvaluationStackItem
                                {
                                    Value    = dest,
                                    TypeName = Utility.GetPapyrusReturnType(methodRef.ReturnType)
                                });
                            }
                        }
                    }
                }
            }
            return(instructions);
        }