示例#1
0
        public bool Equals(MemberInfo x, MemberInfo y)
        {
            if (x == null)
            {
                return(y == null);
            }

            if (y == null)
            {
                return(false);
            }

            if (x.GetType() == y.GetType())
            {
                if (x.MetadataToken == y.MetadataToken && x.Module == y.Module)
                {
                    if (x is MethodBase xMethod && y is MethodBase yMethod)
                    {
                        return(LabelName.GetFullName(xMethod) == LabelName.GetFullName(yMethod));
                    }
                    else if (x is Type xType && y is Type yType)
                    {
                        return(LabelName.GetFullName(xType) == LabelName.GetFullName(yType));
                    }
                    else
                    {
                        return(true);
                    }
                }
示例#2
0
        private static void __cyclesrdtsc(int *target)
        {
            /*
             * push eax
             * push ecx
             * push edx
             * lea esi, target
             * rdtsc
             * mov [esi+4], eax
             * mov [esi], edx
             * pop edx
             * pop ecx
             * pop eax
             * ret
             */
            __cyclesrdtscptr = target;

            string intname = LabelName.GetFullName(typeof(CPUImpl).GetTypeInfo().GetField(nameof(__cyclesrdtscptr)));

            XS.Push(XSRegisters.EAX);
            XS.Push(XSRegisters.ECX);
            XS.Push(XSRegisters.EDX);
            XS.Lea(XSRegisters.ESI, intname);
            XS.Rdtsc();
            XS.Set(XSRegisters.ESI, XSRegisters.EAX, destinationIsIndirect: true, destinationDisplacement: 4);
            XS.Set(XSRegisters.ESI, XSRegisters.EDX, destinationIsIndirect: true);
            XS.Push(XSRegisters.EDX);
            XS.Push(XSRegisters.ECX);
            XS.Push(XSRegisters.EAX);
            XS.Return();
        }
示例#3
0
        private static void __raterdmsr(int *target)
        {
            /*
             * ; esi register layout: (mperf_hi, mperf_lo, aperf_hi, aperf_lo)
             * ;
             * ; int* ptr = new int[4];
             * ;
             * lea esi,        ptr  ;equivalent with `mov esi, &ptr`
             * mov ecx,        e7h
             * rdmsr
             * mov [esi + 4],  eax
             * mov [esi],      edx
             * mov ecx,        e8h
             * rdmsr
             * mov [esi + 12], eax
             * mov [esi + 8],  edx
             * xor eax,        eax
             * ret
             */
            __raterdmsrptr = target;

            string intname = LabelName.GetFullName(typeof(CPUImpl).GetTypeInfo().GetField(nameof(__raterdmsrptr)));

            XS.Lea(XSRegisters.ESI, intname);
            XS.Set(XSRegisters.ECX, 0xe7);
            XS.Rdmsr();
            XS.Set(XSRegisters.EAX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 4);
            XS.Set(XSRegisters.EDX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 0);
            XS.Set(XSRegisters.ECX, 0xe8);
            XS.Rdmsr();
            XS.Set(XSRegisters.EAX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 12);
            XS.Set(XSRegisters.EDX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 8);
            XS.Xor(XSRegisters.EAX, XSRegisters.EAX); // XS.Set(XSRegisters.EAX, 0);
            XS.Return();
        }
示例#4
0
 public override void ExpandStatements(ExtendedWarrior warrior, IWarriorParser parser, ref int currentAddress,
                                       int coreSize, bool evaluate)
 {
     //set labels, except last which is EQU expression
     for (int l = 0; l < Labels.Count; l++)
     {
         LabelName label = Labels[l];
         if (l == Labels.Count - 1)
         {//equ
             parser.Variables[label.GetFullName(parser, currentAddress)] = expression;
         }
         else
         {//labels
             parser.Variables[label.GetFullName(parser, currentAddress)] = new Address(currentAddress);
         }
     }
     return;
 }
示例#5
0
        public void TestGetTypeFullName()
        {
            Action       a  = () => { };
            Action <int> a1 = (i) => test++;

            Assert.That(LabelName.GetFullName(a.GetType()) != LabelName.GetFullName(a1.GetType()));

            var c = new { i = 1, n = "Test" };
            var d = new { i = 1, n = "Test" };
            var e = new { n = "Test", i = 1 };

            Assert.That(LabelName.GetFullName(c.GetType()) != null);
            Assert.That(LabelName.GetFullName(c.GetType()) == LabelName.GetFullName(d.GetType()));
        }
示例#6
0
        public override void ExpandStatements(ExtendedWarrior warrior, IWarriorParser parser, ref int currentAddress,
                                              int coreSize, bool evaluate)
        {
            //set labels, except last which is FOR expression
            for (int l = 0; l < Labels.Count - 1; l++)
            {
                LabelName label = Labels[l];
                parser.Variables[label.GetFullName(parser, currentAddress)] = new Address(currentAddress);
            }

            string cnt   = Labels[Labels.Count - 1].Name;
            int    count = parser.Variables[LimitName].Evaluate(parser, currentAddress);

            for (int i = 1; i <= count; i++)
            {
                parser.Variables[cnt] = new Value(i);
                base.ExpandStatements(warrior, parser, ref currentAddress, coreSize, evaluate);
            }
        }
示例#7
0
        internal static void FetchCPUVendor(int *target)
        {
            /*
             * lea esi, target
             * xor eax, eax
             * cpuid
             * mov [esi], ebx
             * mov [esi + 4], edx
             * mov [esi + 8], ecx
             * ret
             */
            __vendortargetptr = target;

            string intname = LabelName.GetFullName(typeof(CPUImpl).GetTypeInfo().GetField(nameof(__vendortargetptr)));

            XS.Lea(XSRegisters.ESI, intname); // new Lea { DestinationReg = RegistersEnum.ESI, SourceRef = ElementReference.New(intname) };
            XS.Cpuid();
            XS.Set(XSRegisters.ESI, XSRegisters.EBX, destinationIsIndirect: true);
            XS.Set(XSRegisters.ESI, XSRegisters.EDX, destinationIsIndirect: true, destinationDisplacement: 4);
            XS.Set(XSRegisters.ESI, XSRegisters.ECX, destinationIsIndirect: true, destinationDisplacement: 8);
            XS.Return();
        }
示例#8
0
        private void LoadBootEntries()
        {
            mBootEntries   = new Dictionary <MethodBase, int?>();
            mForceIncludes = new List <MemberInfo>();

            var xCheckedAssemblies = new List <string>();

            foreach (string xRef in References)
            {
                LogMessage("Checking Reference: " + xRef);
                if (File.Exists(xRef))
                {
                    LogMessage("  Exists");
                    var xAssembly = AssemblyLoadContext.Default.LoadFromAssemblyCacheOrPath(xRef);
                    CheckAssembly(xAssembly);
                }
            }

            void CheckAssembly(Assembly aAssembly)
            {
                // Just for debugging
                //LogMessage("Checking Assembly: " + aAssembly.Location);

                xCheckedAssemblies.Add(aAssembly.GetName().ToString());

                foreach (var xType in aAssembly.GetTypes())
                {
                    var xForceIncludeAttribute = xType.GetCustomAttribute <ForceInclude>();

                    if (xForceIncludeAttribute != null)
                    {
                        ForceInclude(xType, xForceIncludeAttribute);
                    }

                    foreach (var xMethod in xType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
                    {
                        xForceIncludeAttribute = xMethod.GetCustomAttribute <ForceInclude>();

                        if (xForceIncludeAttribute != null)
                        {
                            ForceInclude(xMethod, xForceIncludeAttribute);
                        }

                        var xBootEntryAttribute = xMethod.GetCustomAttribute <BootEntry>();

                        if (xBootEntryAttribute != null)
                        {
                            var xEntryIndex = xBootEntryAttribute.EntryIndex;

                            LogMessage("Boot Entry found: Name: " + xMethod + ", Entry Index: "
                                       + (xEntryIndex.HasValue ? xEntryIndex.Value.ToString() : "null"));

                            if (xMethod.ReturnType != typeof(void))
                            {
                                throw new NotSupportedException("Boot Entry should return void! Method: " + LabelName.Get(xMethod));
                            }

                            if (xMethod.GetParameters().Length != 0)
                            {
                                throw new NotSupportedException("Boot Entry shouldn't have parameters! Method: " + LabelName.Get(xMethod));
                            }

                            mBootEntries.Add(xMethod, xEntryIndex);
                        }
                    }

                    if (xType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                        .Where(m => m.GetCustomAttribute <BootEntry>() != null).Any())
                    {
                        throw new NotSupportedException("Boot Entry should be static! Type: " + LabelName.GetFullName(xType));
                    }
                }

                foreach (var xReference in aAssembly.GetReferencedAssemblies())
                {
                    try
                    {
                        if (!xCheckedAssemblies.Contains(xReference.ToString()))
                        {
                            var xAssembly = AssemblyLoadContext.Default.LoadFromAssemblyName(xReference);

                            if (xAssembly != null)
                            {
                                CheckAssembly(xAssembly);
                            }
                        }
                    }
                    catch (FileNotFoundException)
                    {
                        if (xReference.Name.Contains("Cosmos"))
                        {
                            LogWarning("Cosmos Assembly not found!" + Environment.NewLine +
                                       "Assembly Name: " + xReference.FullName);
                        }
                    }
                }
            }

            if (mBootEntries.Count == 0)
            {
                throw new NotSupportedException("No boot entries found!");
            }

            if (mBootEntries.Where(e => e.Value == null).Count() == 0)
            {
                throw new NotImplementedException("No default boot entries found!");
            }

            mBootEntries = mBootEntries.OrderBy(e => e.Value)
                           .OrderByDescending(e => e.Value.HasValue)
                           .ToDictionary(e => e.Key, e => e.Value);

            if (mBootEntries.Count > 1)
            {
                var xLastEntryIndex = mBootEntries.Values.ElementAt(0);

                for (int i = 1; i < mBootEntries.Count; i++)
                {
                    var xEntryIndex = mBootEntries.Values.ElementAt(i);

                    if (xLastEntryIndex == xEntryIndex)
                    {
                        throw new NotSupportedException("Two boot entries with the same entry index were found! Methods: '" +
                                                        LabelName.GetFullName(mBootEntries.Keys.ElementAt(i - 1)) + "' and '" +
                                                        LabelName.GetFullName(mBootEntries.Keys.ElementAt(i)) + "'");
                    }

                    xLastEntryIndex = xEntryIndex;
                }
            }
        }
示例#9
0
 public static string GetTypeIDLabel(Type aType)
 {
     return("VMT__TYPE_ID_HOLDER__" + DataMember.FilterStringForIncorrectChars(LabelName.GetFullName(aType) + " ASM_IS__" + aType.GetTypeInfo().Assembly.GetName().Name));
 }
示例#10
0
        protected void ScanMethod(MethodBase aMethod, bool aIsPlug, string sourceItem)
        {
            CompilerHelpers.Debug($"ILScanner: ScanMethod");
            CompilerHelpers.Debug($"Method = '{aMethod}'");
            CompilerHelpers.Debug($"IsPlug = '{aIsPlug}'");
            CompilerHelpers.Debug($"Source = '{sourceItem}'");

            var xParams     = aMethod.GetParameters();
            var xParamTypes = new Type[xParams.Length];

            // Dont use foreach, enum generaly keeps order but
            // isn't guaranteed.
            //string xMethodFullName = LabelName.GetFullName(aMethod);

            for (int i = 0; i < xParams.Length; i++)
            {
                xParamTypes[i] = xParams[i].ParameterType;
                Queue(xParamTypes[i], aMethod, "Parameter");
            }
            var xIsDynamicMethod = aMethod.DeclaringType == null;

            // Queue Types directly related to method
            if (!aIsPlug)
            {
                // Don't queue declaring types of plugs
                if (!xIsDynamicMethod)
                {
                    // dont queue declaring types of dynamic methods either, those dont have a declaring type
                    Queue(aMethod.DeclaringType, aMethod, "Declaring Type");
                }
            }
            if (aMethod is MethodInfo)
            {
                Queue(((MethodInfo)aMethod).ReturnType, aMethod, "Return Type");
            }
            // Scan virtuals

            #region Virtuals scan

            if (!xIsDynamicMethod && aMethod.IsVirtual)
            {
                // For virtuals we need to climb up the type tree
                // and find the top base method. We then add that top
                // node to the mVirtuals list. We don't need to add the
                // types becuase adding DeclaringType will already cause
                // all ancestor types to be added.

                var        xVirtMethod = aMethod;
                var        xVirtType   = aMethod.DeclaringType;
                MethodBase xNewVirtMethod;
                while (true)
                {
                    xVirtType = xVirtType.BaseType;
                    if (xVirtType == null)
                    {
                        // We've reached object, can't go farther
                        xNewVirtMethod = null;
                    }
                    else
                    {
                        xNewVirtMethod = xVirtType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                                         .Where(method => method.Name == aMethod.Name &&
                                                method.GetParameters().Select(param => param.ParameterType)
                                                .SequenceEqual(xParamTypes))
                                         .SingleOrDefault();
                        if (xNewVirtMethod != null)
                        {
                            if (!xNewVirtMethod.IsVirtual)
                            {
                                // This can happen if a virtual "replaces" a non virtual
                                // above it that is not virtual.
                                xNewVirtMethod = null;
                            }
                        }
                    }
                    // We dont bother to add these to Queue, because we have to do a
                    // full downlevel scan if its a new base virtual anyways.
                    if (xNewVirtMethod == null)
                    {
                        // If its already in the list, we mark it null
                        // so we dont do a full downlevel scan.
                        if (mVirtuals.Contains(xVirtMethod))
                        {
                            xVirtMethod = null;
                        }
                        break;
                    }
                    xVirtMethod = xNewVirtMethod;
                }

                // New virtual base found, we need to downscan it
                // If it was already in mVirtuals, then ScanType will take
                // care of new additions.
                if (xVirtMethod != null)
                {
                    Queue(xVirtMethod, aMethod, "Virtual Base");
                    mVirtuals.Add(xVirtMethod);

                    // List changes as we go, cant be foreach
                    for (int i = 0; i < mItemsList.Count; i++)
                    {
                        if (mItemsList[i] is Type xType && xType != xVirtMethod.DeclaringType && !xType.IsInterface)
                        {
                            if (xType.IsSubclassOf(xVirtMethod.DeclaringType))
                            {
                                var xNewMethod = xType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                                                 .Where(method => method.Name == aMethod.Name &&
                                                        method.GetParameters().Select(param => param.ParameterType).SequenceEqual(xParamTypes))
                                                 .SingleOrDefault();
                                if (xNewMethod != null)
                                {
                                    // We need to check IsVirtual, a non virtual could
                                    // "replace" a virtual above it?
                                    if (xNewMethod.IsVirtual)
                                    {
                                        Queue(xNewMethod, aMethod, "Virtual Downscan");
                                    }
                                }
                            }
                            else if (xVirtMethod.DeclaringType.IsInterface &&
                                     xType.GetInterfaces().Contains(xVirtMethod.DeclaringType))
                            {
                                var xInterfaceMap = xType.GetInterfaceMap(xVirtMethod.DeclaringType);
                                var xMethodIndex  = Array.IndexOf(xInterfaceMap.InterfaceMethods, xVirtMethod);

                                if (xMethodIndex != -1)
                                {
                                    var xMethod = xInterfaceMap.TargetMethods[xMethodIndex];

                                    if (xMethod.DeclaringType == xType)
                                    {
                                        Queue(xInterfaceMap.TargetMethods[xMethodIndex], aMethod, "Virtual Downscan");
                                    }
                                }
                            }
                        }
                    }
                }
            }

            #endregion Virtuals scan

            MethodBase xPlug = null;
            // Plugs may use plugs, but plugs won't be plugged over themself
            var inl = aMethod.GetCustomAttribute <InlineAttribute>();
            if (!aIsPlug && !xIsDynamicMethod)
            {
                // Check to see if method is plugged, if it is we don't scan body

                xPlug = mPlugManager.ResolvePlug(aMethod, xParamTypes);
                if (xPlug != null)
                {
                    //ScanMethod(xPlug, true, "Plug method");
                    if (inl == null)
                    {
                        Queue(xPlug, aMethod, "Plug method");
                    }
                }
            }

            if (xPlug == null)
            {
                bool xNeedsPlug = false;
                if ((aMethod.Attributes & MethodAttributes.PinvokeImpl) != 0)
                {
                    // pinvoke methods dont have an embedded implementation
                    xNeedsPlug = true;
                }
                else
                {
                    var xImplFlags = aMethod.GetMethodImplementationFlags();
                    // todo: prob even more
                    if (xImplFlags.HasFlag(MethodImplAttributes.Native) || xImplFlags.HasFlag(MethodImplAttributes.InternalCall))
                    {
                        // native implementations cannot be compiled
                        xNeedsPlug = true;
                    }
                }
                if (xNeedsPlug)
                {
                    throw new Exception(Environment.NewLine
                                        + "Native code encountered, plug required." + Environment.NewLine
                                        + "  DO NOT REPORT THIS AS A BUG." + Environment.NewLine
                                        + "  Please see http://www.gocosmos.org/docs/plugs/missing/" + Environment.NewLine
                                        + "  Need plug for: " + LabelName.GetFullName(aMethod) + "." + Environment.NewLine
                                        + "  Called from :" + Environment.NewLine + sourceItem + Environment.NewLine);
                }

                //TODO: As we scan each method, we could update or put in a new list
                // that has the resolved plug so we don't have to reresolve it again
                // later for compilation.

                // Scan the method body for more type and method refs
                //TODO: Dont queue new items if they are plugged
                // or do we need to queue them with a resolved ref in a new list?

                if (inl != null)
                {
                    return; // cancel inline
                }

                List <ILOpCode> xOpCodes;
                xOpCodes = mReader.ProcessMethod(aMethod);
                if (xOpCodes != null)
                {
                    ProcessInstructions(xOpCodes);
                    foreach (var xOpCode in xOpCodes)
                    {
                        if (xOpCode is ILOpCodes.OpMethod)
                        {
                            Queue(((ILOpCodes.OpMethod)xOpCode).Value, aMethod, "Call", sourceItem);
                        }
                        else if (xOpCode is ILOpCodes.OpType)
                        {
                            Queue(((ILOpCodes.OpType)xOpCode).Value, aMethod, "OpCode Value");
                        }
                        else if (xOpCode is ILOpCodes.OpField xOpField)
                        {
                            //TODO: Need to do this? Will we get a ILOpCodes.OpType as well?
                            Queue(xOpField.Value.DeclaringType, aMethod, "OpCode Value");
                            if (xOpField.Value.IsStatic)
                            {
                                //TODO: Why do we add static fields, but not instance?
                                // AW: instance fields are "added" always, as part of a type, but for static fields, we need to emit a datamember
                                Queue(xOpField.Value, aMethod, "OpCode Value");
                            }
                        }
                        else if (xOpCode is ILOpCodes.OpToken xOpToken)
                        {
                            if (xOpToken.ValueIsType)
                            {
                                Queue(xOpToken.ValueType, aMethod, "OpCode Value");
                            }
                            if (xOpToken.ValueIsField)
                            {
                                Queue(xOpToken.ValueField.DeclaringType, aMethod, "OpCode Value");
                                if (xOpToken.ValueField.IsStatic)
                                {
                                    //TODO: Why do we add static fields, but not instance?
                                    // AW: instance fields are "added" always, as part of a type, but for static fields, we need to emit a datamember
                                    Queue(xOpToken.ValueField, aMethod, "OpCode Value");
                                }
                            }
                        }
                    }
                }
            }
        }
示例#11
0
 private static string BuildMethodKeyName(MethodBase m)
 {
     return(LabelName.GetFullName(m));
 }
示例#12
0
        private MethodBase ResolvePlug(Type aTargetType, List <Type> aImpls, MethodBase aMethod, Type[] aParamTypes)
        {
            //TODO: This method is "reversed" from old - remember that when porting
            MethodBase xResult = null;

            // Setup param types for search
            Type[] xParamTypes;
            if (aMethod.IsStatic)
            {
                xParamTypes = aParamTypes;
            }
            else
            {
                // If its an instance method, we have to add this to the ParamTypes to search
                xParamTypes = new Type[aParamTypes.Length + 1];
                if (aParamTypes.Length > 0)
                {
                    aParamTypes.CopyTo(xParamTypes, 1);
                }
                xParamTypes[0] = aTargetType;
            }

            PlugMethod xAttrib = null;

            foreach (var xImpl in aImpls)
            {
                // TODO: cleanup this loop, next statement shouldnt be neccessary
                if (xResult != null)
                {
                    break;
                }
                // Plugs methods must be static, and public
                // Search for non signature matches first since signature searches are slower
                xResult = xImpl.GetTypeInfo().GetMethods()
                          .Where(method => method.Name == aMethod.Name &&
                                 method.GetParameters().Select(param => param.ParameterType)
                                 .SequenceEqual(xParamTypes))
                          .SingleOrDefault();

                if (xResult == null && aMethod.Name == ".ctor")
                {
                    xResult = xImpl.GetTypeInfo().GetMethod("Ctor", xParamTypes, null);
                }
                if (xResult == null && aMethod.Name == ".cctor")
                {
                    xResult = xImpl.GetTypeInfo().GetMethod("CCtor", xParamTypes, null);
                }

                if (xResult == null)
                {
                    // Search by signature
                    foreach (var xSigMethod in xImpl.GetTypeInfo().GetMethods(BindingFlags.Static | BindingFlags.Public))
                    {
                        // TODO: Only allow one, but this code for now takes the last one
                        // if there is more than one
                        xAttrib = null;
                        foreach (PlugMethod x in xSigMethod.GetCustomAttributes(typeof(PlugMethod), false))
                        {
                            xAttrib = x;
                        }

                        if (xAttrib != null && (xAttrib.IsWildcard && !xAttrib.WildcardMatchParameters))
                        {
                            MethodBase xTargetMethod = null;
                            if (String.Compare(xSigMethod.Name, "Ctor", true) == 0 ||
                                String.Compare(xSigMethod.Name, "Cctor", true) == 0)
                            {
                                xTargetMethod = aTargetType.GetTypeInfo().GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).SingleOrDefault();
                            }
                            else
                            {
                                xTargetMethod = (from item in aTargetType.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)
                                                 where item.Name == xSigMethod.Name
                                                 select item).SingleOrDefault();
                            }
                            if (xTargetMethod == aMethod)
                            {
                                xResult = xSigMethod;
                            }
                        }
                        else
                        {
                            var xParams = xSigMethod.GetParameters();
                            //TODO: Static method plugs dont seem to be separated
                            // from instance ones, so the only way seems to be to try
                            // to match instance first, and if no match try static.
                            // I really don't like this and feel we need to find
                            // an explicit way to determine or mark the method
                            // implementations.
                            //
                            // Plug implementations take "this" as first argument
                            // so when matching we don't include it in the search
                            Type[] xTypesInst        = null;
                            var    xActualParamCount = xParams.Length;
                            foreach (var xParam in xParams)
                            {
                                if (xParam.GetCustomAttributes(typeof(FieldAccess), false).Any())
                                {
                                    xActualParamCount--;
                                }
                            }
                            Type[] xTypesStatic = new Type[xActualParamCount];
                            // If 0 params, has to be a static plug so we skip
                            // any copying and leave xTypesInst = null
                            // If 1 params, xTypesInst must be converted to Type[0]
                            if (xActualParamCount == 1)
                            {
                                xTypesInst = new Type[0];

                                var xReplaceType = xParams[0].GetCustomAttributes(typeof(FieldType), false).ToList();
                                if (xReplaceType.Any())
                                {
                                    xTypesStatic[0] = Type.GetType(((FieldType)xReplaceType[0]).Name, true);
                                }
                                else
                                {
                                    xTypesStatic[0] = xParams[0].ParameterType;
                                }
                            }
                            else if (xActualParamCount > 1)
                            {
                                xTypesInst = new Type[xActualParamCount - 1];
                                var xCurIdx = 0;
                                foreach (var xParam in xParams.Skip(1))
                                {
                                    if (xParam.GetCustomAttributes(typeof(FieldAccess), false).Any())
                                    {
                                        continue;
                                    }

                                    var xReplaceType = xParam.GetCustomAttributes(typeof(FieldType), false).ToList();
                                    if (xReplaceType.Any())
                                    {
                                        xTypesInst[xCurIdx] = Type.GetType(((FieldType)xReplaceType[0]).Name, true);
                                    }
                                    else
                                    {
                                        xTypesInst[xCurIdx] = xParam.ParameterType;
                                    }

                                    xCurIdx++;
                                }
                                xCurIdx = 0;
                                foreach (var xParam in xParams)
                                {
                                    if (xParam.GetCustomAttributes(typeof(FieldAccess), false).Any())
                                    {
                                        xCurIdx++;
                                        continue;
                                    }
                                    if (xCurIdx >= xTypesStatic.Length)
                                    {
                                        break;
                                    }
                                    xTypesStatic[xCurIdx] = xParam.ParameterType;
                                    xCurIdx++;
                                }
                            }
                            MethodBase xTargetMethod = null;
                            // TODO: In future make rule that all ctor plugs are called
                            // ctor by name, or use a new attrib
                            //TODO: Document all the plug stuff in a document on website
                            //TODO: To make inclusion of plugs easy, we can make a plugs master
                            // that references the other default plugs so user exes only
                            // need to reference that one.
                            // TODO: Skip FieldAccessAttribute if in impl
                            if (xTypesInst != null)
                            {
                                if (string.Compare(xSigMethod.Name, "ctor", StringComparison.OrdinalIgnoreCase) == 0)
                                {
                                    xTargetMethod = aTargetType.GetTypeInfo().GetConstructor(xTypesInst);
                                }
                                else
                                {
                                    xTargetMethod = aTargetType.GetTypeInfo().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                                    .Where(method => method.Name == xSigMethod.Name &&
                                                           method.GetParameters().Select(param => param.ParameterType)
                                                           .SequenceEqual(xTypesInst))
                                                    .SingleOrDefault();
                                }
                            }
                            // Not an instance method, try static
                            if (xTargetMethod == null)
                            {
                                if (string.Compare(xSigMethod.Name, "cctor", StringComparison.OrdinalIgnoreCase) == 0 || string.Compare(xSigMethod.Name, "ctor", StringComparison.OrdinalIgnoreCase) == 0)
                                {
                                    xTargetMethod = aTargetType.GetTypeInfo().GetConstructor(xTypesStatic);
                                }
                                else
                                {
                                    xTargetMethod = aTargetType.GetTypeInfo().GetMethods()
                                                    .Where(method => method.Name == xSigMethod.Name &&
                                                           method.GetParameters().Select(param => param.ParameterType)
                                                           .SequenceEqual(xTypesStatic))
                                                    .SingleOrDefault();
                                }
                            }
                            if (xTargetMethod == aMethod)
                            {
                                xResult = xSigMethod;
                                break;
                            }
                            if (xAttrib?.Signature != null)
                            {
                                var xName = DataMember.FilterStringForIncorrectChars(LabelName.GetFullName(aMethod));
                                if (string.Compare(xName, xAttrib.Signature, true) == 0)
                                {
                                    xResult = xSigMethod;
                                    break;
                                }
                            }
                            xAttrib = null;
                        }
                    }
                }
                else
                {
                    // check if signatur is equal
                    var xResPara     = xResult.GetParameters();
                    var xAMethodPara = aMethod.GetParameters();
                    if (aMethod.IsStatic)
                    {
                        if (xResPara.Length != xAMethodPara.Length)
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        if (xResPara.Length - 1 != xAMethodPara.Length)
                        {
                            return(null);
                        }
                    }
                    for (int i = 0; i < xAMethodPara.Length; i++)
                    {
                        int correctIndex = aMethod.IsStatic ? i : i + 1;
                        if (xResPara[correctIndex].ParameterType != xAMethodPara[i].ParameterType)
                        {
                            return(null);
                        }
                    }
                    if (xResult.Name == "Ctor" && aMethod.Name == ".ctor")
                    {
                    }
                    else if (xResult.Name == "CCtor" && aMethod.Name == ".cctor")
                    {
                    }
                    else if (xResult.Name != aMethod.Name)
                    {
                        return(null);
                    }
                }
            }
            if (xResult == null)
            {
                return(null);
            }

            // If we found a matching method, check for attributes
            // that might disable it.
            //TODO: For signature ones, we could cache the attrib. Thats
            // why we check for null here
            if (xAttrib == null)
            {
                // TODO: Only allow one, but this code for now takes the last one
                // if there is more than one
                foreach (PlugMethod x in xResult.GetCustomAttributes(typeof(PlugMethod), false))
                {
                    xAttrib = x;
                }
            }

            // See if we need to disable this plug
            if (xAttrib != null)
            {
                if (!xAttrib.Enabled)
                {
                    //xResult = null;
                    return(null);
                }

                //else if (xAttrib.Signature != null) {
                //  var xName = DataMember.FilterStringForIncorrectChars(MethodInfoLabelGenerator.GetFullName(xResult));
                //  if (string.Compare(xName, xAttrib.Signature, true) != 0) {
                //    xResult = null;
                //  }
                //}
            }

            //if (xAttrib != null && xAttrib.Signature != null)
            //{
            //    var xTargetMethods = aTargetType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
            //    //System_Void__Indy_IL2CPU_Assembler_Assembler__cctor__
            //    //If signature exists, the search is slow. Signatures
            //    //are infrequent though, so for now we just go slow method
            //    //and have not optimized or cached this info. When we
            //    //redo the plugs, we can fix this.
            //    bool xEnabled=true;
            //    foreach (var xTargetMethod in xTargetMethods)
            //    {
            //        string sName = DataMember.FilterStringForIncorrectChars(MethodInfoLabelGenerator.GetFullName(xTargetMethod));
            //        if (string.Compare(sName, xAttrib.Signature, true) == 0)
            //        {
            //            //uint xUID = QueueMethod(xPlugImpl.Plug, "Plug", xMethod, true);
            //            //mMethodPlugs.Add(xTargetMethod, new PlugInfo(xUID, xAttrib.Assembler));
            //            // Mark as disabled, because we already handled it
            //            xEnabled = false;
            //            break;
            //        }
            //    }
            //    // if still enabled, we didn't find our method
            //    if (xEnabled)
            //    {
            //        // todo: more precise error: imagine having a 100K line project, and this error happens...
            //        throw new Exception("Plug target method not found.");
            //    }
            //}
            return(xResult);
        }
示例#13
0
        private MethodBase ResolvePlug(Type aTargetType, List <Type> aImpls, MethodBase aMethod, Type[] aParamTypes)
        {
            //TODO: This method is "reversed" from old - remember that when porting
            MethodBase xResult = null;

            // Setup param types for search
            Type[] xParamTypes;
            if (aMethod.IsStatic)
            {
                xParamTypes = aParamTypes;
            }
            else
            {
                // If its an instance method, we have to add this to the ParamTypes to search
                xParamTypes = new Type[aParamTypes.Length + 1];
                if (aParamTypes.Length > 0)
                {
                    aParamTypes.CopyTo(xParamTypes, 1);
                }
                xParamTypes[0] = aTargetType;
            }

            PlugMethod xAttrib = null;

            foreach (var xImpl in aImpls)
            {
                // TODO: cleanup this loop, next statement shouldnt be neccessary
                if (xResult != null)
                {
                    break;
                }
                // Plugs methods must be static, and public
                // Search for non signature matches first since signature searches are slower
                xResult = xImpl.GetMethod(aMethod.Name, BindingFlags.Static | BindingFlags.Public,
                                          null, xParamTypes, null);

                if (xResult == null && aMethod.Name == ".ctor")
                {
                    xResult = xImpl.GetMethod("Ctor", BindingFlags.Static | BindingFlags.Public,
                                              null, xParamTypes, null);
                }
                if (xResult == null && aMethod.Name == ".cctor")
                {
                    xResult = xImpl.GetMethod("CCtor", BindingFlags.Static | BindingFlags.Public,
                                              null, xParamTypes, null);
                }

                if (xResult == null)
                {
                    // Search by signature
                    foreach (var xSigMethod in xImpl.GetMethods(BindingFlags.Static | BindingFlags.Public))
                    {
                        // TODO: Only allow one, but this code for now takes the last one
                        // if there is more than one
                        xAttrib = null;
                        foreach (PlugMethod x in xSigMethod.GetCustomAttributes(typeof(PlugMethod), false))
                        {
                            xAttrib = x;
                        }

                        if (xAttrib != null && (xAttrib.IsWildcard && !xAttrib.WildcardMatchParameters))
                        {
                            MethodBase xTargetMethod = null;
                            if (String.Equals(xSigMethod.Name, "Ctor", StringComparison.OrdinalIgnoreCase) ||
                                String.Equals(xSigMethod.Name, "Cctor", StringComparison.OrdinalIgnoreCase))
                            {
                                xTargetMethod = aTargetType.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).SingleOrDefault();
                            }
                            else
                            {
                                xTargetMethod = (from item in aTargetType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)
                                                 where item.Name == xSigMethod.Name
                                                 select item).SingleOrDefault();
                            }
                            if (xTargetMethod == aMethod)
                            {
                                xResult = xSigMethod;
                            }
                        }
                        else
                        {
                            var xParams = xSigMethod.GetParameters();
                            //TODO: Static method plugs dont seem to be separated
                            // from instance ones, so the only way seems to be to try
                            // to match instance first, and if no match try static.
                            // I really don't like this and feel we need to find
                            // an explicit way to determine or mark the method
                            // implementations.
                            //
                            // Plug implementations take "this" as first argument
                            // so when matching we don't include it in the search
                            Type[] xTypesInst        = null;
                            var    xActualParamCount = xParams.Length;
                            foreach (var xParam in xParams)
                            {
                                if (xParam.GetCustomAttributes(typeof(FieldAccess), false).Length != 0)
                                {
                                    xActualParamCount--;
                                }
                            }
                            var xTypesStatic = new Type[xActualParamCount];
                            // If 0 params, has to be a static plug so we skip
                            // any copying and leave xTypesInst = null
                            // If 1 params, xTypesInst must be converted to Type[0]
                            if (xActualParamCount == 1)
                            {
                                xTypesInst = Array.Empty <Type>();

                                var xReplaceType = xParams[0].GetCustomAttributes(typeof(FieldType), false).ToList();
                                if (xReplaceType.Count != 0)
                                {
                                    xTypesStatic[0] = _typeResolver.ResolveType(((FieldType)xReplaceType[0]).Name, true);
                                }
                                else
                                {
                                    xTypesStatic[0] = xParams[0].ParameterType;
                                }
                            }
                            else if (xActualParamCount > 1)
                            {
                                xTypesInst = new Type[xActualParamCount - 1];
                                var xCurIdx = 0;
                                foreach (var xParam in xParams.Skip(1))
                                {
                                    if (xParam.GetCustomAttributes(typeof(FieldAccess), false).Length != 0)
                                    {
                                        continue;
                                    }

                                    var xReplaceType = xParam.GetCustomAttributes(typeof(FieldType), false).ToList();
                                    if (xReplaceType.Count != 0)
                                    {
                                        xTypesInst[xCurIdx] = _typeResolver.ResolveType(((FieldType)xReplaceType[0]).Name, true);
                                    }
                                    else
                                    {
                                        xTypesInst[xCurIdx] = xParam.ParameterType;
                                    }

                                    xCurIdx++;
                                }
                                xCurIdx = 0;
                                foreach (var xParam in xParams)
                                {
                                    if (xParam.GetCustomAttributes(typeof(FieldAccess), false).Length != 0)
                                    {
                                        xCurIdx++;
                                        continue;
                                    }
                                    if (xCurIdx >= xTypesStatic.Length)
                                    {
                                        break;
                                    }
                                    xTypesStatic[xCurIdx] = xParam.ParameterType;
                                    xCurIdx++;
                                }
                            }
                            MethodBase xTargetMethod = null;
                            // TODO: In future make rule that all ctor plugs are called
                            // ctor by name, or use a new attrib
                            //TODO: Document all the plug stuff in a document on website
                            //TODO: To make inclusion of plugs easy, we can make a plugs master
                            // that references the other default plugs so user exes only
                            // need to reference that one.
                            // TODO: Skip FieldAccessAttribute if in impl
                            if (xTypesInst != null)
                            {
                                if (String.Equals(xSigMethod.Name, "ctor", StringComparison.OrdinalIgnoreCase))
                                {
                                    xTargetMethod = aTargetType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, xTypesInst, null);
                                }
                                else
                                {
                                    xTargetMethod = aTargetType.GetMethod(xSigMethod.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, xTypesInst, null);
                                }
                            }
                            // Not an instance method, try static
                            if (xTargetMethod == null)
                            {
                                if (String.Equals(xSigMethod.Name, "cctor", StringComparison.OrdinalIgnoreCase) ||
                                    String.Equals(xSigMethod.Name, "ctor", StringComparison.OrdinalIgnoreCase))
                                {
                                    xTargetMethod = aTargetType.GetConstructor(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, xTypesStatic, null);
                                }
                                else
                                {
                                    xTargetMethod = aTargetType.GetMethod(xSigMethod.Name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, xTypesStatic, null);
                                }
                            }
                            if (xTargetMethod == aMethod)
                            {
                                xResult = xSigMethod;
                                break;
                            }
                            if (xAttrib?.Signature != null)
                            {
                                var xName = DataMember.FilterStringForIncorrectChars(LabelName.GetFullName(aMethod));
                                if (String.Equals(xName.Replace("_", ""), xAttrib.Signature.Replace("_", ""), StringComparison.OrdinalIgnoreCase))
                                {
                                    xResult = xSigMethod;
                                    break;
                                }
                            }
                            xAttrib = null;
                        }
                    }
                }
                else
                {
                    // check if signatur is equal
                    var xResPara     = xResult.GetParameters();
                    var xAMethodPara = aMethod.GetParameters();
                    if (aMethod.IsStatic)
                    {
                        if (xResPara.Length != xAMethodPara.Length)
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        if (xResPara.Length - 1 != xAMethodPara.Length)
                        {
                            return(null);
                        }
                    }
                    for (int i = 0; i < xAMethodPara.Length; i++)
                    {
                        int correctIndex = aMethod.IsStatic ? i : i + 1;
                        if (xResPara[correctIndex].ParameterType != xAMethodPara[i].ParameterType && xResPara[correctIndex].ParameterType.Name != "Object") // to cheat if we cant access the actual type
                        {
                            // Allow explicit overwriting of types by signature in case we have to hide internal enum behind uint etc
                            if (xResult.GetCustomAttribute <PlugMethod>()?.Signature.Replace("_", "") == DataMember.FilterStringForIncorrectChars(LabelName.GetFullName(aMethod)).Replace("_", ""))
                            {
                            }
                            else
                            {
                                return(null);
                            }
                        }
                    }
                    if (xResult.Name == "Ctor" && aMethod.Name == ".ctor")
                    {
                    }
                    else if (xResult.Name == "CCtor" && aMethod.Name == ".cctor")
                    {
                    }
                    else if (xResult.Name != aMethod.Name)
                    {
                        return(null);
                    }
                }
            }
            if (xResult == null)
            {
                return(null);
            }

            // If we found a matching method, check for attributes
            // that might disable it.
            //TODO: For signature ones, we could cache the attrib. Thats
            // why we check for null here
            if (xAttrib == null)
            {
                // TODO: Only allow one, but this code for now takes the last one
                // if there is more than one
                foreach (PlugMethod x in xResult.GetCustomAttributes(typeof(PlugMethod), false))
                {
                    xAttrib = x;
                }
            }

            // See if we need to disable this plug
            if (xAttrib != null)
            {
                if (!xAttrib.Enabled)
                {
                    //xResult = null;
                    return(null);
                }

                //else if (xAttrib.Signature != null) {
                //  var xName = DataMember.FilterStringForIncorrectChars(MethodInfoLabelGenerator.GetFullName(xResult));
                //  if (string.Compare(xName, xAttrib.Signature, true) != 0) {
                //    xResult = null;
                //  }
                //}
            }

            if (xResult is MethodInfo aMethodInfo && aMethodInfo.IsGenericMethodDefinition)
            {
                var types = aMethod.GetGenericArguments();
                xResult = aMethodInfo.MakeGenericMethod(types);
            }

            return(xResult);
        }