Ejemplo n.º 1
0
 public TypeTrace(AssemblyTrace parent, CST.TypeDef type)
 {
     Parent = parent;
     Type = type;
     IncludeType = false;
     Methods = new Set<CST.MethodSignature>();
 }
Ejemplo n.º 2
0
        // NOTE: May be called on invalid definitions
        public override bool TypeAlwaysUsed(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef)
        {
#if false
            if (env.AttributeHelper.TypeHasAttribute
                    (assemblyDef, typeDef, env.Global.CompilerGeneratedAttributeRef, false))
            {
                return(false);
            }
#endif

            if (env.AttributeHelper.TypeHasAttribute
                    (assemblyDef, typeDef, env.AttributeHelper.IgnoreAttributeRef, true, true))
            {
                return(false);
            }

            if (typeDef.IsModule)
            {
                return(true);
            }

            if (HasFullReflection(assemblyDef, typeDef))
            {
                return(true);
            }

            var isUsed = default(bool);
            env.AttributeHelper.GetValueFromType
                (assemblyDef,
                typeDef,
                env.AttributeHelper.UsedTypeAttributeRef,
                env.AttributeHelper.TheIsUsedProperty,
                true,
                false,
                ref isUsed);
            var isUsedType = default(bool);
            env.AttributeHelper.GetValueFromType
                (assemblyDef,
                typeDef,
                env.AttributeHelper.UsedAttributeRef,
                env.AttributeHelper.TheIsUsedProperty,
                true,
                false,
                ref isUsedType);
            if (isUsed || isUsedType)
            {
                return(true);
            }

            return(false);
        }
Ejemplo n.º 3
0
        private bool HasFullReflection(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef)
        {
            var level = default(ReflectionLevel);

            env.AttributeHelper.GetValueFromType
                (assemblyDef,
                typeDef,
                env.AttributeHelper.ReflectionAttributeRef,
                env.AttributeHelper.TheReflectionLevelProperty,
                true,
                true,
                ref level);
            return(level >= ReflectionLevel.Full);
        }
Ejemplo n.º 4
0
        public bool CouldBeInlinableBasedOnHeaderAlone(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef)
        {
            if (methodDef.IsVirtualOrAbstract || typeDef.Style is CST.InterfaceTypeStyle)
            {
                // No virtuals or interface methods
                return(false);
            }

            if (typeDef.Style is CST.MultiDimArrayTypeStyle)
            {
                // Implemented by runtime
                return(false);
            }

            if (typeDef.IsAttributeType(env.Global, assemblyDef))
            {
                // Don't inline attribute property methods since we invoke them directly when building attributes
                return(false);
            }

            var level = default(ReflectionLevel);

            env.AttributeHelper.GetValueFromType
                (assemblyDef,
                typeDef,
                env.AttributeHelper.ReflectionAttributeRef,
                env.AttributeHelper.TheReflectionLevelProperty,
                true,
                true,
                ref level);
            if (level >= ReflectionLevel.Full)
            {
                // No inlining in classes needing full reflection since need to support dynamic invokes
                return(false);
            }

            // NOTE: Method may be used in a delegate, in which case it's fine to inline but we'll still
            //       need to emit the definition

            if (assemblyDef.EntryPoint != null &&
                assemblyDef.EntryPoint.QualifiedMemberName.Equals
                    (methodDef.QualifiedMemberName(env.Global, assemblyDef, typeDef)))
            {
                // Entry points are called directly by startup code
                return(false);
            }

            return(true);
        }
Ejemplo n.º 5
0
        public void AddMethod(MessageContext ctxt, CST.TypeDef typeDef, CST.MethodDef methodDef)
        {
            var typeTrace = ResolveTypeTrace(typeDef);

            typeTrace.AddMethod(ctxt, methodDef);
        }
Ejemplo n.º 6
0
        public TypeMapping(CompilerEnvironment env, CST.AssemblyDef assemblyDef, CST.TypeDef typeDef)
        {
            ctxt = CST.MessageContextBuilders.Type(env.Global, assemblyDef, typeDef);
            this.env = env;
            this.assemblyDef = assemblyDef;
            this.typeDef = typeDef;

            // Method slots appear as field names in type structures and directory names on disk.
            // Thus we use lower-case identifiers.
            methodSlots = new SlotAllocation<CST.QualifiedMemberName>
                (env.DebugMode, NameFlavor.LowercaseIdentifier, FriendlyMemberName);

            // Field slots appear in object annd type structuers, but always prefixed by 'S' or 'F'.
            // Thus we use arbitrary identifiers.
            fieldSlots = new SlotAllocation<CST.QualifiedMemberName>
                (env.DebugMode, NameFlavor.Identifier, FriendlyMemberName);

            // Similarly for event slots, but prefixed by 'E'.
            eventSlots = new SlotAllocation<CST.QualifiedMemberName>
                (env.DebugMode, NameFlavor.Identifier, FriendlyMemberName);

            // Similarly for property slots (needed only by reflection), but prefixed by 'R'
            propSlots = new SlotAllocation<CST.QualifiedMemberName>
                (env.DebugMode, NameFlavor.Identifier, FriendlyMemberName);

            AddNames(env, assemblyDef, typeDef, methodSlots, fieldSlots, eventSlots, propSlots);

            // Defer till ask for string slot
            stringSlots = null;
        }
Ejemplo n.º 7
0
        public void AddType(MessageContext ctxt, CST.TypeDef typeDef)
        {
            var typeTrace = ResolveTypeTrace(typeDef);

            typeTrace.AddType(ctxt);
        }
Ejemplo n.º 8
0
        public override CST.InvalidInfo ImplementableInstruction(MessageContext ctxt, CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef, CST.Instruction instruction)
        {
            switch (instruction.Flavor)
            {
            case CST.InstructionFlavor.Try:
            {
                var tryi = (CST.TryInstruction)instruction;
                if (tryi.Handlers.Any(h => h.Flavor == CST.HandlerFlavor.Filter))
                {
                    Log
                        (new CST.InvalidInstruction
                            (ctxt, instruction, "Exception filter blocks are not supported"));
                    return(new CST.InvalidInfo(CST.MessageContextBuilders.Instruction(Global, instruction)));
                }
                break;
            }

            default:
                break;
            }
            return(null);
        }
Ejemplo n.º 9
0
 public string ResolveStringToSlot(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, string str)
 {
     return(TypeMappingFor(assemblyDef, typeDef).ResolveStringToSlot(str));
 }
Ejemplo n.º 10
0
        public bool IsInlinable(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef)
        {
            var s = MethodBodySize(methodDef.QualifiedMemberName(env.Global, assemblyDef, typeDef));

            return(s >= 0 && s <= env.InlineThreshold);
        }
Ejemplo n.º 11
0
 public string ResolvePropertyDefToSlot(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.PropertyDef propDef)
 {
     return(TypeMappingFor(assemblyDef, typeDef).ResolvePropertyToSlot
                (propDef.QualifiedMemberName(env.Global, assemblyDef, typeDef)));
 }
Ejemplo n.º 12
0
        public void AddType(MessageContext ctxt, CST.AssemblyDef assemblyDef, CST.TypeDef typeDef)
        {
            var assemblyTrace = ResolveAssemblyTrace(assemblyDef);;

            assemblyTrace.AddType(ctxt, typeDef);
        }
Ejemplo n.º 13
0
 public IEnumerable <KeyValuePair <string, string> > AllStringSlots(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef)
 {
     return(TypeMappingFor(assemblyDef, typeDef).AllStringSlots());
 }
Ejemplo n.º 14
0
 public override bool IncludeAttributes(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef)
 {
     return(HasFullReflection(assemblyDef, typeDef));
 }
Ejemplo n.º 15
0
 // NOTE: May be called on invalid definitions
 public override bool IsAlternateEntryPoint(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef)
 {
     return(env.AttributeHelper.MethodHasAttribute
                (assemblyDef, typeDef, methodDef, env.AttributeHelper.EntryPointAttributeRef, false, false));
 }
Ejemplo n.º 16
0
 public string ResolveFieldDefToSlot(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.FieldDef fieldDef)
 {
     return(TypeMappingFor(assemblyDef, typeDef).ResolveFieldToSlot
                (fieldDef.QualifiedMemberName(env.Global, assemblyDef, typeDef)));
 }
Ejemplo n.º 17
0
 public string ResolveTypeDefToSlot(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef)
 {
     return(AssemblyMappingFor(assemblyDef).ResolveTypeDefinitionToSlot(typeDef.EffectiveName(env.Global)));
 }
Ejemplo n.º 18
0
        private static void AddNames(
            CompilerEnvironment env,
            CST.AssemblyDef assemblyDef,
            CST.TypeDef typeDef,
            SlotAllocation <CST.QualifiedMemberName> methodSlots,
            SlotAllocation <CST.QualifiedMemberName> fieldSlots,
            SlotAllocation <CST.QualifiedMemberName> eventSlots,
            SlotAllocation <CST.QualifiedMemberName> propSlots)
        {
            // Allocate slots for any base type so that this type's slots won't collide with them.
            // NOTE: Not strictly necessary for methods, since only virtual methods of supertype may find their
            //       way into derived type, but seems easiest to just allocate them all.
            // NOTE: Interface method slots need only be unique within their interface type since the type
            //       id is included in the final slot name.
            if (typeDef.Extends != null)
            {
                var extAssemblyDef = default(CST.AssemblyDef);
                var extTypeDef     = default(CST.TypeDef);
                if (typeDef.Extends.PrimTryResolve(env.Global, out extAssemblyDef, out extTypeDef))
                {
                    AddNames(env, extAssemblyDef, extTypeDef, methodSlots, fieldSlots, eventSlots, propSlots);
                }
            }

            // Members are already in canonical order
            foreach (var memberDef in typeDef.Members.Where(m => m.IsUsed && m.Invalid == null))
            {
                var name = memberDef.QualifiedMemberName(env.Global, assemblyDef, typeDef);
                switch (memberDef.Flavor)
                {
                case CST.MemberDefFlavor.Field:
                {
                    fieldSlots.Add(name);
                    break;
                }

                case CST.MemberDefFlavor.Event:
                {
                    eventSlots.Add(name);
                    break;
                }

                case CST.MemberDefFlavor.Method:
                {
                    methodSlots.Add(name);
                    break;
                }

                case CST.MemberDefFlavor.Property:
                {
                    propSlots.Add(name);
                    break;
                }

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            return;
        }
Ejemplo n.º 19
0
        public void AddMethod(MessageContext ctxt, CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef)
        {
            var assemblyTrace = ResolveAssemblyTrace(assemblyDef);

            assemblyTrace.AddMethod(ctxt, typeDef, methodDef);
        }
Ejemplo n.º 20
0
        public override bool PropogateExtraUsedFromMember(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MemberDef memberDef)
        {
            var newUsed = false;

            var methodDef = memberDef as CST.MethodDef;

            if (methodDef != null)
            {
                if (!methodDef.IsStatic && methodDef.IsConstructor &&
                    env.InteropManager.IsImported(assemblyDef, typeDef, methodDef) &&
                    !env.InteropManager.IsFactory(assemblyDef, typeDef, methodDef))
                {
                    // Imported instance constructor may invoke an 'importing' constructor
                    var polyMethEnv =
                        Global.Environment().AddAssembly(assemblyDef).AddType(typeDef).AddSelfTypeBoundArguments().
                        AddMethod(methodDef);
                    var methodRef = env.InteropManager.BestImportingConstructor(polyMethEnv);
                    if (methodRef != null)
                    {
                        if (ExtraUsedMethod(methodRef.QualifiedMemberName))
                        {
                            newUsed = true;
                        }
                    }
                }
            }

            return(newUsed);
        }
Ejemplo n.º 21
0
 public override bool IgnoreMethodDefBody(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef)
 {
     return(env.AttributeHelper.MethodHasAttribute(assemblyDef, typeDef, methodDef, env.AttributeHelper.InteropGeneratedAttributeRef, false, false));
 }
Ejemplo n.º 22
0
        public override void ImplementableMemberDef(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MemberDef memberDef)
        {
            var ctxt = CST.MessageContextBuilders.Member(env.Global, assemblyDef, typeDef, memberDef);
            var s    = typeDef.Style;

            var methodDef = memberDef as CST.MethodDef;

            if (methodDef == null)
            {
                return;
            }

            if (s is CST.DelegateTypeStyle || s is CST.MultiDimArrayTypeStyle)
            {
                // SPECIAL CASE: Magic delegate and multi-dimensional array methods are
                //               implemented by runtime
                return;
            }

            if (env.AttributeHelper.MethodHasAttribute
                    (assemblyDef, typeDef, methodDef, env.AttributeHelper.IgnoreAttributeRef, true, true))
            {
                Log(new CST.InvalidMemberDef(ctxt, "Method is marked as '[Ignore]'"));
                methodDef.Invalid = new CST.InvalidInfo("Ignored");
            }

            try
            {
                if (!(s is CST.InterfaceTypeStyle) && methodDef.MethodStyle != CST.MethodStyle.Abstract &&
                    !env.InteropManager.IsImported(assemblyDef, typeDef, methodDef))
                {
                    switch (methodDef.CodeFlavor)
                    {
                    case CST.MethodCodeFlavor.Managed:
                    {
                        var instructions = methodDef.Instructions(Global);
                        if (instructions == null || instructions.Body.Count == 0)
                        {
                            Log(new CST.InvalidMemberDef(ctxt, "Method has no body"));
                            methodDef.Invalid = new CST.InvalidInfo("Unimplementable");
                        }
                        break;
                    }

                    case CST.MethodCodeFlavor.ManagedExtern:
                        Log(new CST.InvalidMemberDef(ctxt, "Method is marked as extern but has no import"));
                        methodDef.Invalid = new CST.InvalidInfo("Unimplementable");
                        break;

                    case CST.MethodCodeFlavor.Native:
                        Log(new CST.InvalidMemberDef(ctxt, "Method invokes native code"));
                        methodDef.Invalid = new CST.InvalidInfo("Unimplementable");
                        break;

                    case CST.MethodCodeFlavor.Runtime:
                        Log(new CST.InvalidMemberDef(ctxt, "Method is part of the CLR runtime"));
                        methodDef.Invalid = new CST.InvalidInfo("Unimplementable");
                        break;

                    case CST.MethodCodeFlavor.ForwardRef:
                        Log(new CST.InvalidMemberDef(ctxt, "Method is a forward reference"));
                        methodDef.Invalid = new CST.InvalidInfo("Unimplementable");
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
                // else: no body to check
            }
            catch (DefinitionException)
            {
                Log(new CST.InvalidMemberDef(ctxt, "Method contains an interop error"));
                methodDef.Invalid = new CST.InvalidInfo("Unimplementable");
            }
        }
Ejemplo n.º 23
0
        // See also: InteropManager::IsInlinable
        private bool PrimIsInlinable(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef)
        {
            if (!CouldBeInlinableBasedOnHeaderAlone(assemblyDef, typeDef, methodDef))
            {
                return(false);
            }

            if (methodDef.IsRecursive)
            {
                // No recursive methods
                return(false);
            }

            if (methodDef.IsConstructor)
            {
                // No instance constructors (since we can't enline NewExpressions yet), and
                // no static constructors (since we can't inline calls emitted in assembly Initialize)
                return(false);
            }

            if (env.InteropManager.IsImported(assemblyDef, typeDef, methodDef) ||
                env.InteropManager.IsExported(assemblyDef, typeDef, methodDef))
            {
                // No imported methods (we inline separately), and
                // no exported methods (we need the definition around to be able to export it)
                return(false);
            }

            if (methodDef.MethodBody == null || methodDef.MethodBody.Instructions.Length == 0)
            {
                // No empty methods or imported methods
                return(false);
            }

            var numReturns   = 0;
            var instructions = methodDef.Instructions(env.Global);

            if (!instructions.IsInlinable(ref numReturns) || numReturns != 1)
            {
                // Non-inlinable instructions
                return(false);
            }

            var code = instructions.Body[instructions.Body.Count - 1].Code;

            if (code != CST.InstructionCode.Ret && code != CST.InstructionCode.RetVal)
            {
                // Last instruction is not return
                return(false);
            }

            // NOTE: Even though instructions have a single return, it is still possible the translated statatements
            //       won't have a unique result, so unfortunately we need to check that below

            var isInline       = default(bool);
            var overrideInline = env.AttributeHelper.GetValueFromMethod
                                     (assemblyDef,
                                     typeDef,
                                     methodDef,
                                     env.AttributeHelper.InlineAttributeRef,
                                     env.AttributeHelper.TheIsInlinedProperty,
                                     true,
                                     false,
                                     ref isInline);

            if (overrideInline && !isInline)
            {
                // User has supressed inlining
                return(false);
            }

            if (!overrideInline && instructions.Size > env.InlineThreshold)
            {
                // Method too large
                return(false);
            }

            var methEnv =
                env.Global.Environment().AddAssembly(assemblyDef).AddType(typeDef).AddSelfTypeBoundArguments().
                AddMethod(methodDef).AddSelfMethodBoundArguments();
            var cstmethod = CST.CSTMethod.Translate(methEnv, new JST.NameSupply(), null);
            var body      = new Seq <CST.Statement>();
            var retres    = cstmethod.Body.ToReturnResult(body);

            if (retres.Status != CST.ReturnStatus.One)
            {
                // More than one return
                return(false);
            }

            return(true);
        }
Ejemplo n.º 24
0
 public string ResolveEventDefToSlot(CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.EventDef eventDef)
 {
     return(TypeMappingFor(assemblyDef, typeDef).ResolveEventToSlot
                (eventDef.QualifiedMemberName(env.Global, assemblyDef, typeDef)));
 }