예제 #1
0
 TypeSig SubstituteGenericParameter(TypeSig type)
 {
     if (genericArguments is null)
     {
         return(type);
     }
     return(genericArguments.Resolve(type));
 }
        private static MethodSig Resolve(MethodBaseSig method, TypeSig typeContext)
        {
            var args = new GenericArguments();

            if (typeContext.IsGenericInstanceType)
            {
                args.PushTypeArgs(((GenericInstSig)typeContext).GenericArguments);
            }

            var retSig = new MethodSig(method.CallingConvention);

            retSig.RetType = args.Resolve(method.RetType);
            foreach (var param in method.Params)
            {
                retSig.Params.Add(args.Resolve(param));
            }
            return(retSig);
        }
        private static TypeSig Resolve(TypeSig type, TypeSig typeContext)
        {
            var args = new GenericArguments();

            if (typeContext.IsGenericInstanceType)
            {
                args.PushTypeArgs(((GenericInstSig)typeContext).GenericArguments);
            }
            return(args.Resolve(type));
        }
예제 #4
0
        public static TypeSig ResolveType(this GenericArguments genericArgs, TypeSig typeSig)
        {
            switch (typeSig.ElementType)
            {
            case ElementType.Ptr:
                return(new PtrSig(genericArgs.ResolveType(typeSig.Next)));

            case ElementType.ByRef:
                return(new ByRefSig(genericArgs.ResolveType(typeSig.Next)));

            case ElementType.SZArray:
                return(new SZArraySig(genericArgs.ResolveType(typeSig.Next)));

            case ElementType.Array:
                var arraySig = (ArraySig)typeSig;
                return(new ArraySig(genericArgs.ResolveType(typeSig.Next), arraySig.Rank, arraySig.Sizes, arraySig.LowerBounds));

            case ElementType.Pinned:
                return(new PinnedSig(genericArgs.ResolveType(typeSig.Next)));

            case ElementType.Var:
            case ElementType.MVar:
                return(genericArgs.Resolve(typeSig));

            case ElementType.GenericInst:
                var genInst  = (GenericInstSig)typeSig;
                var typeArgs = new List <TypeSig>();
                foreach (var arg in genInst.GenericArguments)
                {
                    typeArgs.Add(genericArgs.ResolveType(arg));
                }
                return(new GenericInstSig(genInst.GenericType, typeArgs));

            case ElementType.CModReqd:
                return(new CModReqdSig(((CModReqdSig)typeSig).Modifier, genericArgs.ResolveType(typeSig.Next)));

            case ElementType.CModOpt:
                return(new CModOptSig(((CModOptSig)typeSig).Modifier, genericArgs.ResolveType(typeSig.Next)));

            case ElementType.ValueArray:
                return(new ValueArraySig(genericArgs.ResolveType(typeSig.Next), ((ValueArraySig)typeSig).Size));

            case ElementType.Module:
                return(new ModuleSig(((ModuleSig)typeSig).Index, genericArgs.ResolveType(typeSig.Next)));
            }
            if (typeSig.IsTypeDefOrRef)
            {
                var s = (TypeDefOrRefSig)typeSig;
                if (s.TypeDefOrRef is TypeSpec)
                {
                    throw new NotSupportedException(); // TODO: ?
                }
            }
            return(typeSig);
        }
        bool ReplaceGenericArg(ref TypeSig typeSig)
        {
            if (genericArguments == null)
            {
                return(false);
            }
            var newTypeSig = genericArguments.Resolve(typeSig);

            if (newTypeSig != typeSig)
            {
                typeSig = newTypeSig;
                return(true);
            }
            return(false);
        }
        private static IEnumerable <TypeSig> BaseTypes(TypeSig type)
        {
            TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();

            if (typeDef.BaseType == null)
            {
                yield break;
            }

            TypeSig baseType = type;

            do
            {
                var args = new GenericArguments();
                if (baseType.IsGenericInstanceType)
                {
                    args.PushTypeArgs(((GenericInstSig)baseType).GenericArguments);
                }
                baseType = args.Resolve(typeDef.BaseType.ToTypeSig());
                yield return(baseType);

                typeDef = typeDef.BaseType.ResolveTypeDef();
            } while (typeDef != null && typeDef.BaseType != null);
        }
        public bool Instantiate(MethodSpec methodSpec, out MethodDef def)
        {
            if (instantiations.TryGetValue(methodSpec, out def))
            {
                return(true);
            }

            var genericArguments = new GenericArguments();

            genericArguments.PushMethodArgs(methodSpec.GenericInstMethodSig.GenericArguments);
            var originDef = methodSpec.Method.ResolveMethodDefThrow();

            var newSig = ResolveMethod(originDef.MethodSig, genericArguments);

            newSig.Generic       = false;
            newSig.GenParamCount = 0;

            string newName = originDef.Name;

            foreach (var typeArg in methodSpec.GenericInstMethodSig.GenericArguments)
            {
                newName += ";" + typeArg.TypeName;
            }

            def = new MethodDefUser(newName, newSig, originDef.ImplAttributes, originDef.Attributes);
            var thisParam = originDef.HasThis ? originDef.Parameters[0].Type : null;

            def.DeclaringType2 = originDef.DeclaringType2;
            if (thisParam != null)
            {
                def.Parameters[0].Type = thisParam;
            }

            foreach (var declSec in originDef.DeclSecurities)
            {
                def.DeclSecurities.Add(declSec);
            }
            def.ImplMap = originDef.ImplMap;
            foreach (var ov in originDef.Overrides)
            {
                def.Overrides.Add(ov);
            }

            def.Body            = new CilBody();
            def.Body.InitLocals = originDef.Body.InitLocals;
            def.Body.MaxStack   = originDef.Body.MaxStack;
            foreach (var variable in originDef.Body.Variables)
            {
                var newVar = new Local(variable.Type);
                def.Body.Variables.Add(newVar);
            }

            var instrMap = new Dictionary <Instruction, Instruction>();

            foreach (var instr in originDef.Body.Instructions)
            {
                var newInstr = new Instruction(instr.OpCode, ResolveOperand(instr.Operand, genericArguments));
                def.Body.Instructions.Add(newInstr);
                instrMap[instr] = newInstr;
            }
            foreach (var instr in def.Body.Instructions)
            {
                if (instr.Operand is Instruction)
                {
                    instr.Operand = instrMap[(Instruction)instr.Operand];
                }
                else if (instr.Operand is Instruction[])
                {
                    var targets = (Instruction[])((Instruction[])instr.Operand).Clone();
                    for (int i = 0; i < targets.Length; i++)
                    {
                        targets[i] = instrMap[targets[i]];
                    }
                    instr.Operand = targets;
                }
            }
            def.Body.UpdateInstructionOffsets();

            foreach (var eh in originDef.Body.ExceptionHandlers)
            {
                var newEH = new ExceptionHandler(eh.HandlerType);
                newEH.TryStart     = instrMap[eh.TryStart];
                newEH.HandlerStart = instrMap[eh.HandlerStart];
                if (eh.TryEnd != null)
                {
                    newEH.TryEnd = instrMap[eh.TryEnd];
                }
                if (eh.HandlerEnd != null)
                {
                    newEH.HandlerEnd = instrMap[eh.HandlerEnd];
                }
                if (eh.CatchType != null)
                {
                    newEH.CatchType = genericArguments.Resolve(newEH.CatchType.ToTypeSig()).ToTypeDefOrRef();
                }
                else if (eh.FilterStart != null)
                {
                    newEH.FilterStart = instrMap[eh.FilterStart];
                }

                def.Body.ExceptionHandlers.Add(newEH);
            }

            instantiations[methodSpec] = def;
            return(false);
        }
        public static GenericArguments ParseGenericArguments(string type, string path, int absoluteCharOffset)
        {
            GenericArguments generics = new GenericArguments();

            var p = type.IndexOf('<');
            System.Text.StringBuilder s = new System.Text.StringBuilder();
            if (p > -1)
            {
                for (int i = p + 1; i < type.Length; i++)
                {

                    var c = type[i];

                    switch (c)
                    {

                        case '>':
                        case ',':
                            generics.Add(s.ToString().Trim());
                            s.Clear();
                            break;

                        default:
                            s.Append(c);
                            break;
                    }

                }
            }

            string txt = LoadText(path, absoluteCharOffset);
            System.Text.RegularExpressions.MatchCollection matchs = r.Matches(txt);

            foreach (System.Text.RegularExpressions.Match item in matchs)
            {
                string t = item.Value.Substring("where".Length).Trim();
                GenericArgument gen = generics.Resolve(t);
                if (gen != null)
                {
                    t = txt.Substring(item.Index + item.Length + 1).Trim();
                    var m2 = r.Match(t);
                    if (m2.Success)
                        t = t.Substring(0, m2.Index);
                    var constraints = t.Split(',');
                    foreach (string constraint in constraints)
                        gen.AddConstraint(constraint.Trim());
                }
            }

            return generics;
        }