Example #1
0
        // Virtual function related functionality
        public override MethodImplRecord[] FindMethodsImplWithMatchingDeclName(string declName)
        {
            MetadataReader metadataReader = _module.MetadataReader;
            var stringComparer = metadataReader.StringComparer;
            ArrayBuilder<MethodImplRecord> foundRecords = new ArrayBuilder<MethodImplRecord>();

            foreach (var methodImplHandle in _typeDefinition.GetMethodImplementations())
            {
                MethodImplementation methodImpl = metadataReader.GetMethodImplementation(methodImplHandle);

                EntityHandle methodDeclCheckHandle = methodImpl.MethodDeclaration;
                HandleKind methodDeclHandleKind = methodDeclCheckHandle.Kind;

                // We want to check that the method name matches before actually getting the MethodDesc. For MethodSpecifications
                // we need to dereference that handle to the underlying member reference to look at name matching.
                if (methodDeclHandleKind == HandleKind.MethodSpecification)
                {
                    methodDeclCheckHandle = metadataReader.GetMethodSpecification((MethodSpecificationHandle)methodDeclCheckHandle).Method;
                    methodDeclHandleKind = methodDeclCheckHandle.Kind;
                }

                bool foundRecord = false;

                switch (methodDeclHandleKind)
                {
                    case HandleKind.MethodDefinition:
                        if (stringComparer.Equals(metadataReader.GetMethodDefinition((MethodDefinitionHandle)methodDeclCheckHandle).Name, declName))
                        {
                            foundRecord = true;
                        }
                        break;

                    case HandleKind.MemberReference:
                        if (stringComparer.Equals(metadataReader.GetMemberReference((MemberReferenceHandle)methodDeclCheckHandle).Name, declName))
                        {
                            foundRecord = true;
                        }
                        break;

                    default:
                        Debug.Assert(false, "unexpected methodDeclHandleKind");
                        break;
                }

                if (foundRecord)
                {
                    MethodImplRecord newRecord = new MethodImplRecord();
                    newRecord.Decl = (MethodDesc)_module.GetObject(methodImpl.MethodDeclaration);
                    newRecord.Body = (MethodDesc)_module.GetObject(methodImpl.MethodBody);

                    foundRecords.Add(newRecord);
                }
            }

            if (foundRecords.Count != 0)
                return foundRecords.ToArray();

            return null;
        }
 internal static Expansion CreateExpansion(ArrayBuilder<Expansion> expansions)
 {
     switch (expansions.Count)
     {
         case 0:
             return null;
         case 1:
             return expansions[0];
         default:
             return new AggregateExpansion(expansions.ToArray());
     }
 }
        /// <summary>
        /// Metadata based computation of interfaces.
        /// </summary>
        private DefType[] ComputeRuntimeInterfacesForNonInstantiatedMetadataType(MetadataType type)
        {
            DefType[] explicitInterfaces = type.ExplicitlyImplementedInterfaces;
            DefType[] baseTypeInterfaces = (type.BaseType != null) ? (type.BaseType.RuntimeInterfaces) : Array.Empty<DefType>();

            // Optimized case for no interfaces newly defined.
            if (explicitInterfaces.Length == 0)
                return baseTypeInterfaces;

            ArrayBuilder<DefType> interfacesArray = new ArrayBuilder<DefType>();
            interfacesArray.Append(baseTypeInterfaces);

            foreach (DefType iface in explicitInterfaces)
            {
                BuildPostOrderInterfaceList(iface, ref interfacesArray);
            }

            return interfacesArray.ToArray();
        }
        public void AddRange()
        {
            var builder = new ArrayBuilder<int>();

            builder.AddRange(new int[0], 0, 0);
            AssertEx.Equal(new int[0], builder.ToArray());

            builder.AddRange(new[] { 1, 2, 3 }, 0, 3);
            AssertEx.Equal(new[] { 1, 2, 3 }, builder.ToArray());

            builder.AddRange(new[] { 1, 2, 3 }, 2, 0);
            AssertEx.Equal(new[] { 1, 2, 3 }, builder.ToArray());

            builder.AddRange(new[] { 1, 2, 3 }, 1, 1);
            AssertEx.Equal(new[] { 1, 2, 3, 2 }, builder.ToArray());

            builder.AddRange(new[] { 1, 2, 3 }, 1, 2);
            AssertEx.Equal(new[] { 1, 2, 3, 2, 2, 3 }, builder.ToArray());

            builder.AddRange(new[] { 1, 2, 3 }, 2, 1);
            AssertEx.Equal(new[] { 1, 2, 3, 2, 2, 3, 3 }, builder.ToArray());
        }
Example #5
0
        internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection<ParameterExpression> vars)
        {
            if (NearestHoistedLocals != null && vars.Count > 0)
            {
                // Find what array each variable is on & its index
                var indexes = new ArrayBuilder<long>(vars.Count);

                foreach (ParameterExpression variable in vars)
                {
                    // For each variable, find what array it's defined on
                    ulong parents = 0;
                    HoistedLocals locals = NearestHoistedLocals;
                    while (!locals.Indexes.ContainsKey(variable))
                    {
                        parents++;
                        locals = locals.Parent;
                        Debug.Assert(locals != null);
                    }

                    // combine the number of parents we walked, with the
                    // real index of variable to get the index to emit.
                    ulong index = (parents << 32) | (uint)locals.Indexes[variable];

                    indexes.UncheckedAdd((long)index);
                }

                EmitGet(NearestHoistedLocals.SelfVariable);
                lc.EmitConstantArray(indexes.ToArray());
                lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables_ObjectArray_Int64Array);
            }
            else
            {
                // No visible variables
                lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables);
            }
        }
Example #6
0
        protected override MethodImplRecord[] ComputeVirtualMethodImplsForType()
        {
            ArrayBuilder<MethodImplRecord> records = new ArrayBuilder<MethodImplRecord>();

            MetadataReader metadataReader = _module.MetadataReader;

            foreach (var methodImplHandle in _typeDefinition.GetMethodImplementations())
            {
                MethodImplementation methodImpl = metadataReader.GetMethodImplementation(methodImplHandle);

                EntityHandle methodDeclCheckHandle = methodImpl.MethodDeclaration;
                HandleKind methodDeclHandleKind = methodDeclCheckHandle.Kind;

                // We want to check that the type is not an interface matches before actually getting the MethodDesc. 
                // For MethodSpecifications we need to dereference that handle to the underlying member reference to 
                // look at the owning type.
                if (methodDeclHandleKind == HandleKind.MethodSpecification)
                {
                    methodDeclCheckHandle = metadataReader.GetMethodSpecification((MethodSpecificationHandle)methodDeclCheckHandle).Method;
                    methodDeclHandleKind = methodDeclCheckHandle.Kind;
                }

                MetadataType owningType = null;
                switch (methodDeclHandleKind)
                {
                    case HandleKind.MethodDefinition:
                        owningType = ((MethodDesc)_module.GetObject(methodDeclCheckHandle)).OwningType as MetadataType;
                        break;

                    case HandleKind.MemberReference:
                        EntityHandle owningTypeHandle = metadataReader.GetMemberReference((MemberReferenceHandle)methodDeclCheckHandle).Parent;
                        owningType = _module.GetObject(owningTypeHandle) as MetadataType;
                        break;

                    default:
                        Debug.Assert(false, "unexpected methodDeclHandleKind");
                        break;
                }

                if (!owningType.IsInterface)
                {
                    MethodImplRecord newRecord = new MethodImplRecord();
                    newRecord.Decl = (MethodDesc)_module.GetObject(methodImpl.MethodDeclaration);
                    newRecord.Body = (MethodDesc)_module.GetObject(methodImpl.MethodBody);
                    records.Add(newRecord);
                }
            }

            return records.ToArray();
        }
        DispatchMapEntry[] BuildDispatchMap(NodeFactory factory)
        {
            ArrayBuilder<DispatchMapEntry> dispatchMapEntries = new ArrayBuilder<DispatchMapEntry>();
            
            for (int i = 0; i < _type.RuntimeInterfaces.Length; i++)
            {
                var interfaceType = _type.RuntimeInterfaces[i];
                Debug.Assert(interfaceType.IsInterface);

                List<MethodDesc> virtualSlots;
                factory.VirtualSlots.TryGetValue(interfaceType, out virtualSlots);

                if (virtualSlots != null)
                {
                    for (int j = 0; j < virtualSlots.Count; j++)
                    {
                        MethodDesc declMethod = virtualSlots[j];
                        var implMethod = VirtualFunctionResolution.ResolveInterfaceMethodToVirtualMethodOnType(declMethod, _type.GetClosestMetadataType());

                        // Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface
                        // dispatch will walk the inheritance chain).
                        if (implMethod != null)
                        {
                            var entry = new DispatchMapEntry();
                            entry.InterfaceIndex = checked((short)i);
                            entry.InterfaceMethodSlot = checked((short)j);
                            entry.ImplementationMethodSlot = checked((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, implMethod));
                            dispatchMapEntries.Add(entry);
                        }
                    }
                }
            }

            return dispatchMapEntries.ToArray();
        }
Example #8
0
        private void SetDebugInformation(MethodCodeNode methodCodeNodeNeedingCode, MethodIL methodIL)
        {
            try
            {
                MethodDebugInformation debugInfo = _compilation.GetDebugInfo(methodIL);

                // TODO: NoLineNumbers
                //if (!_compilation.Options.NoLineNumbers)
                {
                    IEnumerable<ILSequencePoint> ilSequencePoints = debugInfo.GetSequencePoints();
                    if (ilSequencePoints != null)
                    {
                        SetSequencePoints(ilSequencePoints);
                    }
                }

                IEnumerable<ILLocalVariable> localVariables = debugInfo.GetLocalVariables();
                if (localVariables != null)
                {
                    SetLocalVariables(localVariables);
                }

                IEnumerable<string> parameters = debugInfo.GetParameterNames();
                if (parameters != null)
                {
                    SetParameterNames(parameters);
                }

                ArrayBuilder<uint> variableToTypeIndex = new ArrayBuilder<uint>();

                var signature = MethodBeingCompiled.Signature;
                if (!signature.IsStatic)
                {
                    TypeDesc type = MethodBeingCompiled.OwningType;
                    variableToTypeIndex.Add(GetVariableTypeIndex(type));
                }

                for (int i = 0; i < signature.Length; ++i)
                {
                    TypeDesc type = signature[i];
                    variableToTypeIndex.Add(GetVariableTypeIndex(type));
                }
                var locals = methodIL.GetLocals();
                for (int i = 0; i < locals.Length; ++i)
                {
                    TypeDesc type = locals[i].Type;
                    variableToTypeIndex.Add(GetVariableTypeIndex(type));
                }
                _variableToTypeIndex = variableToTypeIndex.ToArray();
            }
            catch (Exception e)
            {
                // Debug info not successfully loaded.
                Log.WriteLine(e.Message + " (" + methodCodeNodeNeedingCode.ToString() + ")");
            }
        }
Example #9
0
        public string[] BuildFileInfoMap(IEnumerable<DependencyNode> nodes)
        {
            // TODO: DebugInfo on Unix https://github.com/dotnet/corert/issues/608
            if (_targetPlatform.OperatingSystem != TargetOS.Windows)
                return null;

            ArrayBuilder<string> debugFileInfos = new ArrayBuilder<string>();
            foreach (DependencyNode node in nodes)
            {
                if (node is INodeWithDebugInfo)
                {
                    DebugLocInfo[] debugLocInfos = ((INodeWithDebugInfo)node).DebugLocInfos;
                    if (debugLocInfos != null)
                    {
                        foreach (DebugLocInfo debugLocInfo in debugLocInfos)
                        {
                            string fileName = debugLocInfo.FileName;
                            if (!_debugFileToId.ContainsKey(fileName))
                            {
                                _debugFileToId.Add(fileName, debugFileInfos.Count);
                                debugFileInfos.Add(fileName);
                            }
                        }
                    }
                }
            }

            return debugFileInfos.Count > 0 ? debugFileInfos.ToArray() : null;
        }
        /// <summary>
        /// Parses the string '<paramref name="name"/>' and returns the type corresponding to the parsed type name.
        /// The type name string should be in the 'SerString' format as defined by the ECMA-335 standard.
        /// </summary>
        public static TypeDesc GetTypeByCustomAttributeTypeName(this ModuleDesc module, string name)
        {
            TypeDesc loadedType;

            StringBuilder genericTypeDefName = new StringBuilder(name.Length);

            var ch = name.Begin();
            var nameEnd = name.End();

            for (; ch < nameEnd; ++ch)
            {
                // Always pass escaped characters through.
                if (ch.Current == '\\')
                {
                    genericTypeDefName.Append(ch.Current);
                    ++ch;
                    if (ch < nameEnd)
                    {
                        genericTypeDefName.Append(ch.Current);
                    }
                    continue;
                }

                // The type def name ends if

                // The start of a generic argument list
                if (ch.Current == '[')
                    break;

                // Indication that the type is a pointer
                if (ch.Current == '*')
                    break;

                // Indication that the type is a reference
                if (ch.Current == '&')
                    break;

                // A comma that indicates that the rest of the name is an assembly reference
                if (ch.Current == ',')
                    break;

                genericTypeDefName.Append(ch.Current);
            }

            ModuleDesc homeModule = module;
            AssemblyName homeAssembly = FindAssemblyIfNamePresent(name);
            if (homeAssembly != null)
            {
                homeModule = module.Context.ResolveAssembly(homeAssembly);
            }
            MetadataType typeDef = ResolveCustomAttributeTypeNameToTypeDesc(genericTypeDefName.ToString(), homeModule);

            ArrayBuilder<TypeDesc> genericArgs = new ArrayBuilder<TypeDesc>();

            // Followed by generic instantiation parameters (but check for the array case)
            if (ch < nameEnd && ch.Current == '[' && (ch + 1) < nameEnd && (ch + 1).Current != ']' && (ch + 1).Current != ',')
            {
                ch++; // truncate the '['
                var genericInstantiationEnd = ch + ReadTypeArgument(ch, nameEnd, true);  // find the end of the instantiation list
                while (ch < genericInstantiationEnd)
                {
                    if (ch.Current == ',')
                        ch++;

                    int argLen = ReadTypeArgument(ch, name.End(), false);
                    string typeArgName;
                    if (ch.Current == '[')
                    {
                        // This type argument name is stringified,
                        // we need to remove the [] from around it
                        ch++;
                        typeArgName = StringIterator.Substring(ch, ch + (argLen - 2));
                        ch += argLen - 1;
                    }
                    else
                    {
                        typeArgName = StringIterator.Substring(ch, ch + argLen);
                        ch += argLen;
                    }

                    TypeDesc argType = module.GetTypeByCustomAttributeTypeName(typeArgName);
                    genericArgs.Add(argType);
                }

                Debug.Assert(ch == genericInstantiationEnd);
                ch++;

                loadedType = typeDef.MakeInstantiatedType(genericArgs.ToArray());
            }
            else
            {
                // Non-generic type
                loadedType = typeDef;
            }

            // At this point the characters following may be any number of * characters to indicate pointer depth
            while (ch < nameEnd)
            {
                if (ch.Current == '*')
                {
                    loadedType = loadedType.MakePointerType();
                }
                else
                {
                    break;
                }
                ch++;
            }

            // Followed by any number of "[]" or "[,*]" pairs to indicate arrays
            int commasSeen = 0;
            bool bracketSeen = false;
            while (ch < nameEnd)
            {
                if (ch.Current == '[')
                {
                    ch++;
                    commasSeen = 0;
                    bracketSeen = true;
                }
                else if (ch.Current == ']')
                {
                    if (!bracketSeen)
                        break;

                    ch++;
                    if (commasSeen == 0)
                    {
                        loadedType = loadedType.MakeArrayType();
                    }
                    else
                    {
                        loadedType = loadedType.MakeArrayType(commasSeen + 1);
                    }

                    bracketSeen = false;
                }
                else if (ch.Current == ',')
                {
                    if (!bracketSeen)
                        break;
                    ch++;
                    commasSeen++;
                }
                else
                {
                    break;
                }
            }

            // Followed by at most one & character to indicate a byref.
            if (ch < nameEnd)
            {
                if (ch.Current == '&')
                {
                    loadedType = loadedType.MakeByRefType();
                    ch++;
                }
            }

            return loadedType;
        }
Example #11
0
        public string[] BuildFileInfoMap(IEnumerable<DependencyNode> nodes)
        {
            ArrayBuilder<string> debugFileInfos = new ArrayBuilder<string>();
            foreach (DependencyNode node in nodes)
            {
                if (node is INodeWithDebugInfo)
                {
                    DebugLocInfo[] debugLocInfos = ((INodeWithDebugInfo)node).DebugLocInfos;
                    if (debugLocInfos != null)
                    {
                        foreach (DebugLocInfo debugLocInfo in debugLocInfos)
                        {
                            string fileName = debugLocInfo.FileName;
                            if (!_debugFileToId.ContainsKey(fileName))
                            {
                                _debugFileToId.Add(fileName, debugFileInfos.Count);
                                debugFileInfos.Add(fileName);
                            }
                        }
                    }
                }
            }

            return debugFileInfos.Count > 0 ? debugFileInfos.ToArray() : null;
        }
        private static RuntimeAssemblyName CreateRuntimeAssemblyNameFromMetadata(
            MetadataReader reader,
            ConstantStringValueHandle name,
            ushort majorVersion,
            ushort minorVersion,
            ushort buildNumber,
            ushort revisionNumber,
            ConstantStringValueHandle culture,
            IEnumerable<byte> publicKeyOrToken,
            AssemblyFlags assemblyFlags)
        {
            AssemblyNameFlags assemblyNameFlags = AssemblyNameFlags.None;
            if (0 != (assemblyFlags & AssemblyFlags.PublicKey))
                assemblyNameFlags |= AssemblyNameFlags.PublicKey;
            if (0 != (assemblyFlags & AssemblyFlags.Retargetable))
                assemblyNameFlags |= AssemblyNameFlags.Retargetable;
            int contentType = ((int)assemblyFlags) & 0x00000E00;
            assemblyNameFlags |= (AssemblyNameFlags)contentType;

            ArrayBuilder<byte> keyOrTokenArrayBuilder = new ArrayBuilder<byte>();
            foreach (byte b in publicKeyOrToken)
                keyOrTokenArrayBuilder.Add(b);

            return new RuntimeAssemblyName(
                name.GetString(reader),
                new Version(majorVersion, minorVersion, buildNumber, revisionNumber),
                culture.GetStringOrNull(reader),
                assemblyNameFlags,
                keyOrTokenArrayBuilder.ToArray()
                );
        }
 /// <summary>
 /// Creates a special block that is marked as not allowing jumps in.
 /// This should not be used for rewriting BlockExpression itself, or
 /// anything else that supports jumping.
 /// </summary>
 private static Expression MakeBlock(ArrayBuilder<Expression> expressions)
 {
     return new SpilledExpressionBlock(expressions.ToArray());
 }