Example #1
0
        private static MethodSpec GetVirtualMethod(TypeSpec impl_ts, MethodSpec decl_ms,
                                                   target.Target t, bool allow_non_virtual = false)
        {
            /* Iterate through methods looking for virtual ones */
            var first_mdef = impl_ts.m.GetIntEntry(MetadataStream.tid_TypeDef,
                                                   impl_ts.tdrow, 5);
            var last_mdef = impl_ts.m.GetLastMethodDef(impl_ts.tdrow);

            for (uint mdef_row = first_mdef; mdef_row < last_mdef; mdef_row++)
            {
                var flags = impl_ts.m.GetIntEntry(MetadataStream.tid_MethodDef,
                                                  (int)mdef_row, 2);

                if (allow_non_virtual || (flags & 0x40) == 0x40)
                {
                    MethodSpec impl_ms;
                    impl_ts.m.GetMethodDefRow(MetadataStream.tid_MethodDef,
                                              (int)mdef_row, out impl_ms, impl_ts.gtparams, null);
                    impl_ms.type = impl_ts;

                    if ((flags & 0x400) != 0x400)
                    {
                        // Not marked abstract
                        if (MetadataStream.CompareString(impl_ms.m,
                                                         impl_ms.m.GetIntEntry(MetadataStream.tid_MethodDef, (int)mdef_row, 3),
                                                         decl_ms.m,
                                                         decl_ms.m.GetIntEntry(MetadataStream.tid_MethodDef, (int)decl_ms.mdrow, 3)))
                        {
                            if (MetadataStream.CompareSignature(impl_ms.m, impl_ms.msig,
                                                                impl_ts.gtparams, null,
                                                                decl_ms.m, decl_ms.msig, impl_ts.gtparams, null))
                            {
                                // this is the correct one
                                return(impl_ms);
                            }
                            if (MetadataStream.CompareSignature(impl_ms.m, impl_ms.msig,
                                                                impl_ts.gtparams, null,
                                                                decl_ms.m, decl_ms.msig, decl_ms.gtparams, null))
                            {
                                // this is the correct one
                                return(impl_ms);
                            }
                        }
                    }
                }
            }

            // if not found, look to base classes
            var bc = impl_ts.GetExtends();

            if (bc != null)
            {
                return(GetVirtualMethod(bc, decl_ms, t, allow_non_virtual));
            }
            else
            {
                return(null);
            }
        }
Example #2
0
 private static int GetVTableIndex(MethodSpec ms, List <VTableItem> list)
 {
     for (int idx = 0; idx < list.Count; idx++)
     {
         var i = list[idx];
         if (MetadataStream.CompareString(ms.m, ms.m.GetIntEntry(MetadataStream.tid_MethodDef, ms.mdrow, 3),
                                          i.unimpl_meth.m, i.unimpl_meth.m.GetIntEntry(MetadataStream.tid_MethodDef, i.unimpl_meth.mdrow, 3)))
         {
             if (MetadataStream.CompareSignature(ms, i.unimpl_meth))
             {
                 return(idx);
             }
         }
     }
     return(-1);
 }
Example #3
0
        public static int GetVTableOffset(metadata.TypeSpec ts,
                                          metadata.MethodSpec ms, Target t)
        {
            var vtbl             = GetVirtualMethodDeclarations(ts);
            var search_meth_name = ms.m.GetIntEntry(MetadataStream.tid_MethodDef,
                                                    ms.mdrow, 3);

            // find the requested method, match on name, signature and declaring type
            for (int i = 0; i < vtbl.Count; i++)
            {
                var test  = vtbl[i];
                var mdecl = test.unimpl_meth;
                if (mdecl.type.Equals(ts))
                {
                    // Check on name
                    var mname = mdecl.m.GetIntEntry(MetadataStream.tid_MethodDef,
                                                    mdecl.mdrow, 3);
                    if (MetadataStream.CompareString(mdecl.m, mname,
                                                     ms.m, search_meth_name))
                    {
                        // Check on signature
                        if (MetadataStream.CompareSignature(mdecl.m, mdecl.msig,
                                                            mdecl.gtparams, mdecl.gmparams,
                                                            ms.m, ms.msig, ms.gtparams, ms.gmparams))
                        {
                            if (ts.IsInterface == false)
                            {
                                i += (6 + t.ExtraVTableFieldsPointerLength);
                            }
                            return(i);
                        }
                    }
                }
            }

            throw new Exception("Requested virtual method slot not found");
        }
Example #4
0
        public static void ImplementVirtualMethods(TypeSpec ts, List <VTableItem> list)
        {
            // We implement those methods in the most derived class first and work back
            foreach (var i in list)
            {
                // skip if already done
                if (i.impl_meth != null)
                {
                    continue;
                }

                // if we've gone back far enough to the max_implementor class
                //  we can start looking for implementations from here
                if (i.max_implementor != null && i.max_implementor.Equals(ts))
                {
                    i.max_implementor = null;
                }

                // if we haven't, skip this method for this class (it will be
                //  implemented in a base class)
                if (i.max_implementor != null)
                {
                    continue;
                }

                // Now, search for a matching method in this particular class
                /* Iterate through methods looking for virtual ones */
                var first_mdef = ts.m.GetIntEntry(MetadataStream.tid_TypeDef,
                                                  ts.tdrow, 5);
                var last_mdef        = ts.m.GetLastMethodDef(ts.tdrow);
                var search_meth_name = i.unimpl_meth.m.GetIntEntry(MetadataStream.tid_MethodDef,
                                                                   i.unimpl_meth.mdrow, 3);

                for (uint mdef_row = first_mdef; mdef_row < last_mdef; mdef_row++)
                {
                    var flags = ts.m.GetIntEntry(MetadataStream.tid_MethodDef,
                                                 (int)mdef_row, 2);

                    if ((flags & 0x40) == 0x40)
                    {
                        // its a virtual method
                        MethodSpec impl_ms;
                        ts.m.GetMethodDefRow(MetadataStream.tid_MethodDef,
                                             (int)mdef_row, out impl_ms, ts.gtparams, null);
                        impl_ms.type = ts;

                        // compare on name
                        if (MetadataStream.CompareString(i.unimpl_meth.m, search_meth_name,
                                                         ts.m, ts.m.GetIntEntry(MetadataStream.tid_MethodDef, (int)mdef_row, 3)))
                        {
                            // and on signature
                            if (MetadataStream.CompareSignature(i.unimpl_meth, impl_ms))
                            {
                                // If its marked abstract, we dont implement it
                                if ((flags & 0x400) == 0x400)
                                {
                                    i.impl_meth = null;
                                }
                                else
                                {
                                    // we have found a valid implementing method
                                    i.impl_meth = impl_ms;
                                }
                            }
                        }
                    }
                }
            }

            // now implement on base classes
            var extends = ts.GetExtends();

            if (extends != null)
            {
                ImplementVirtualMethods(extends, list);
            }
        }
Example #5
0
        public static int GetFieldOffset(metadata.TypeSpec ts,
                                         string fname, target.Target t, out bool is_tls, bool is_static = false,
                                         List <TypeSpec> field_types = null, List <string> field_names = null,
                                         List <int> field_offsets    = null)
        {
            int align = 1;

            is_tls = false;
            if (ts.SimpleType == 0) // class
            {
                align = GetTypeAlignment(ts, t, is_static);
            }
            if (ts.SimpleType == 0xe && !is_static) // string
            {
                align = t.GetPointerSize();
            }

            if (ts.Equals(ts.m.SystemString) && !is_static)
            {
                /* System.String has a special layout in dotnet clr because the fields
                 * length and firstchar are reversed */

                if (field_names != null)
                {
                    field_names.Add("__vtbl");
                    field_names.Add("__mutex_lock");
                    field_names.Add("m_stringLength");
                    field_names.Add("m_firstChar");
                }
                if (field_types != null)
                {
                    field_types.Add(ts.m.SystemIntPtr);
                    field_types.Add(ts.m.SystemInt64);
                    field_types.Add(ts.m.SystemInt32);
                    field_types.Add(ts.m.SystemChar);
                }
                if (field_offsets != null)
                {
                    field_offsets.Add(0);
                    field_offsets.Add(GetArrayFieldOffset(ArrayField.MutexLock, t));
                    field_offsets.Add(GetTypeSize(ts.m.SystemObject, t));
                    field_offsets.Add(GetTypeSize(ts.m.SystemObject, t) + t.GetPointerSize());
                }

                if (fname == null)
                {
                    // size = sizeof(Object) + sizeof(int length), aligned to pointer size
                    return(GetTypeSize(ts.m.SystemObject, t) + t.GetPointerSize());
                }
                else
                {
                    if (fname == "length" || fname == "m_stringLength")
                    {
                        return(GetTypeSize(ts.m.SystemObject, t));
                    }
                    else if (fname == "start_char" || fname == "m_firstChar")
                    {
                        return(GetTypeSize(ts.m.SystemObject, t) + t.GetPointerSize());
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }
                }
            }

            /* Iterate through methods looking for requested
             *    one */
            var first_fdef = ts.m.GetIntEntry(MetadataStream.tid_TypeDef,
                                              ts.tdrow, 4);
            var last_fdef = ts.m.GetLastFieldDef(ts.tdrow);

            int cur_offset    = 0;
            int cur_tl_offset = 0;

            if (is_static == false && !ts.IsValueType)
            {
                if (ts.GetExtends() == null)
                {
                    // Add a vtable entry
                    if (field_offsets != null)
                    {
                        field_offsets.Add(cur_offset);
                    }
                    cur_offset += t.GetCTSize(ir.Opcode.ct_object);
                    cur_offset  = util.util.align(cur_offset, align);

                    if (field_types != null)
                    {
                        field_types.Add(ts.m.SystemIntPtr);
                    }
                    if (field_names != null)
                    {
                        field_names.Add("__vtbl");
                    }

                    // Add a mutex lock entry
                    if (field_offsets != null)
                    {
                        field_offsets.Add(cur_offset);
                    }
                    cur_offset += t.GetCTSize(ir.Opcode.ct_int64);
                    cur_offset  = util.util.align(cur_offset, align);

                    if (field_types != null)
                    {
                        field_types.Add(ts.m.SystemInt64);
                    }
                    if (field_names != null)
                    {
                        field_names.Add("__mutex_lock");
                    }
                }
                else
                {
                    cur_offset = GetFieldOffset(ts.GetExtends(), (string)null, t,
                                                out is_tls,
                                                is_static, field_types, field_names, field_offsets);
                    cur_offset = util.util.align(cur_offset, align);
                }
            }
            else if (is_static)
            {
                // Add an is_initalized field
                cur_offset += t.GetCTSize(ir.Opcode.ct_intptr);
                cur_offset  = util.util.align(cur_offset, align);
            }

            for (uint fdef_row = first_fdef; fdef_row < last_fdef; fdef_row++)
            {
                // Ensure field is static if requested
                var flags = ts.m.GetIntEntry(MetadataStream.tid_Field,
                                             (int)fdef_row, 0);
                if (((flags & 0x10) == 0x10 && is_static == true) ||
                    ((flags & 0x10) == 0 && is_static == false))
                {
                    // Check on name if we are looking for a particular field
                    bool f_is_tls = ts.m.thread_local_fields[fdef_row];
                    if (fname != null)
                    {
                        var ffname = ts.m.GetIntEntry(MetadataStream.tid_Field,
                                                      (int)fdef_row, 1);
                        if (MetadataStream.CompareString(ts.m, ffname, fname))
                        {
                            if (f_is_tls)
                            {
                                is_tls = true;
                                return(cur_tl_offset);
                            }
                            else
                            {
                                is_tls = false;
                                return(cur_offset);
                            }
                        }
                    }

                    // Increment by type size
                    var fsig = (int)ts.m.GetIntEntry(MetadataStream.tid_Field,
                                                     (int)fdef_row, 2);

                    var ft      = ts.m.GetFieldType(ref fsig, ts.gtparams, null);
                    var ft_size = t.GetSize(ft);

                    if (field_types != null)
                    {
                        field_types.Add(ft);
                    }
                    if (field_names != null)
                    {
                        var cur_fname = ts.m.GetStringEntry(MetadataStream.tid_Field,
                                                            (int)fdef_row, 1);
                        field_names.Add(cur_fname);
                    }
                    if (field_offsets != null)
                    {
                        if (f_is_tls)
                        {
                            field_offsets.Add(cur_tl_offset);
                        }
                        else
                        {
                            field_offsets.Add(cur_offset);
                        }
                    }

                    if (f_is_tls)
                    {
                        cur_tl_offset += ft_size;
                        cur_tl_offset  = util.util.align(cur_tl_offset, align);
                    }
                    else
                    {
                        cur_offset += ft_size;
                        cur_offset  = util.util.align(cur_offset, align);
                    }
                }
            }

            // Shouldn't get here if looking for a specific field
            if (fname != null)
            {
                throw new MissingFieldException();
            }

            // Else return size of complete type
            return(cur_offset);
        }
Example #6
0
        public static int GetFieldOffset(metadata.TypeSpec ts,
                                         metadata.MethodSpec fs, target.Target t, out bool is_tls, bool is_static = false)
        {
            int align = 1;

            is_tls = false;
            if (ts.SimpleType == 0 || ts.SimpleType == 0xe)      // class or string
            {
                align = GetTypeAlignment(ts, t, is_static);
            }

            /* Iterate through methods looking for requested
             *  one */
            var first_fdef = ts.m.GetIntEntry(MetadataStream.tid_TypeDef,
                                              ts.tdrow, 4);
            var last_fdef = ts.m.GetLastFieldDef(ts.tdrow);

            uint search_field_name = 0;

            if (fs != null)
            {
                search_field_name = fs.m.GetIntEntry(MetadataStream.tid_Field,
                                                     fs.mdrow, 1);
            }

            int cur_offset    = 0;
            int cur_tl_offset = 0;

            if (is_static == false && !ts.IsValueType)
            {
                if (ts.GetExtends() == null)
                {
                    // Add a vtable entry
                    cur_offset += t.GetCTSize(ir.Opcode.ct_object);
                    cur_offset  = util.util.align(cur_offset, align);

                    // Add a mutex lock entry
                    cur_offset += t.GetCTSize(ir.Opcode.ct_int64);
                    cur_offset  = util.util.align(cur_offset, align);
                }
                else
                {
                    cur_offset = GetFieldOffset(ts.GetExtends(), (string)null, t, out is_tls);
                    cur_offset = util.util.align(cur_offset, align);
                }
            }
            else if (is_static)
            {
                // Add an is_initalized field
                cur_offset += t.GetCTSize(ir.Opcode.ct_intptr);
                cur_offset  = util.util.align(cur_offset, align);
            }

            for (uint fdef_row = first_fdef; fdef_row < last_fdef; fdef_row++)
            {
                // Ensure field is static if requested
                var flags = ts.m.GetIntEntry(MetadataStream.tid_Field,
                                             (int)fdef_row, 0);
                if (((flags & 0x10) == 0x10 && is_static == true) ||
                    ((flags & 0x10) == 0 && is_static == false))
                {
                    // Check on name if we are looking for a particular field
                    bool f_is_tls = ts.m.thread_local_fields[fdef_row];
                    if (search_field_name != 0)
                    {
                        var fname = ts.m.GetIntEntry(MetadataStream.tid_Field,
                                                     (int)fdef_row, 1);
                        if (MetadataStream.CompareString(ts.m, fname,
                                                         fs.m, search_field_name))
                        {
                            if (f_is_tls)
                            {
                                is_tls = true;
                                return(cur_tl_offset);
                            }
                            else
                            {
                                is_tls = false;
                                return(cur_offset);
                            }
                        }
                    }

                    // Increment by type size
                    var fsig = (int)ts.m.GetIntEntry(MetadataStream.tid_Field,
                                                     (int)fdef_row, 2);

                    var ft      = ts.m.GetFieldType(ref fsig, ts.gtparams, null);
                    var ft_size = t.GetSize(ft);

                    if (f_is_tls)
                    {
                        cur_tl_offset += ft_size;
                        cur_tl_offset  = util.util.align(cur_tl_offset, align);
                    }
                    else
                    {
                        cur_offset += ft_size;
                        cur_offset  = util.util.align(cur_offset, align);
                    }
                }
            }

            // Shouldn't get here if looking for a specific field
            if (search_field_name != 0)
            {
                throw new MissingFieldException();
            }

            // Else return size of complete type
            return(cur_offset);
        }