Exemplo n.º 1
0
        public void Define(CodeGen code_gen)
        {
            if (is_defined)
            {
                return;
            }

            if (is_intransit)
            {
                // Circular definition
                Report.Error("Circular definition of class: " + FullName);
            }

            if (outer != null)
            {
                PEAPI.TypeAttr vis = attr & PEAPI.TypeAttr.VisibilityMask;

                if (vis == PEAPI.TypeAttr.Private || vis == PEAPI.TypeAttr.Public)
                {
                    /* Nested class, but attr not set accordingly. */
                    Report.Warning(location, String.Format("Nested class '{0}' has non-nested visibility, set to such.", NestedFullName));
                    attr  = attr ^ vis;
                    attr |= (vis == PEAPI.TypeAttr.Public ? PEAPI.TypeAttr.NestedPublic : PEAPI.TypeAttr.NestedPrivate);
                }
            }

            if (parent != null)
            {
                is_intransit = true;
                parent.Resolve(code_gen);

                is_intransit = false;
                if (parent.PeapiClass == null)
                {
                    Report.Error("this type can not be a base type: "
                                 + parent);
                }

                if (IsValueType(parent.PeapiClass.nameSpace, parent.PeapiClass.name))
                {
                    is_value_class = true;
                }
                else if (IsEnumType(parent.PeapiClass.nameSpace, parent.PeapiClass.name))
                {
                    is_enum_class  = true;
                    is_value_class = false;
                }

                if (!IsValueType(name_space, name) && !IsEnumType(name_space, name) &&
                    is_value_class && (attr & PEAPI.TypeAttr.Sealed) == 0)
                {
                    attr |= PEAPI.TypeAttr.Sealed;
                }

                if (outer != null)
                {
                    if (!outer.IsDefined)
                    {
                        outer.Define(code_gen);
                    }
                    classdef = outer.PeapiType.AddNestedClass(attr,
                                                              name_space, name, parent.PeapiClass);
                }
                else
                {
                    if (is_value_class || is_enum_class)
                    {
                        // Should probably confirm that the parent is System.ValueType
                        classdef = code_gen.PEFile.AddValueClass(attr,
                                                                 name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
                    }
                    else
                    {
                        classdef = code_gen.PEFile.AddClass(attr,
                                                            name_space, name, parent.PeapiClass);
                    }
                }
            }
            else
            {
                if (outer != null)
                {
                    if (!outer.IsDefined)
                    {
                        outer.Define(code_gen);
                    }
                    classdef = outer.PeapiType.AddNestedClass(attr,
                                                              name_space, name);
                }
                else
                {
                    if (is_value_class || is_enum_class)
                    {
                        classdef = code_gen.PEFile.AddValueClass(attr,
                                                                 name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
                    }
                    else
                    {
                        classdef = code_gen.PEFile.AddClass(attr,
                                                            name_space, name);
                    }
                }
                if (FullName == "System.Object")
                {
                    classdef.SpecialNoSuper();
                }
            }

            is_defined = true;

            if (size != -1 || pack != -1)
            {
                classdef.AddLayoutInfo((pack == -1) ? 1 : pack, (size == -1) ? 0 : size);
            }

            if (impl_list != null)
            {
                foreach (BaseClassRef impl in impl_list)
                {
                    impl.Resolve(code_gen);
                    classdef.AddImplementedInterface(impl.PeapiClass);
                }
            }

            if (gen_params != null)
            {
                gen_params.Resolve(code_gen, classdef);
            }

            is_intransit = false;

            code_gen.AddToDefineContentsList(this);
        }
Exemplo n.º 2
0
        protected void WriteCode(CodeGen code_gen, PEAPI.MethodDef methoddef)
        {
            /// Add the custrom attributes to this method
            if (customattr_list != null)
            {
                foreach (CustomAttr customattr in customattr_list)
                {
                    customattr.AddTo(code_gen, methoddef);
                    if (customattr.IsSuppressUnmanaged(code_gen))
                    {
                        methoddef.AddMethAttribute(PEAPI.MethAttr.HasSecurity);
                    }
                }
            }

            /// Add declarative security to this method
            if (decl_sec != null)
            {
                decl_sec.AddTo(code_gen, methoddef);
                methoddef.AddMethAttribute(PEAPI.MethAttr.HasSecurity);
            }

            // Generic type parameters
            if (gen_params != null)
            {
                gen_params.Resolve(code_gen, methoddef);
            }

            if (type_def == null)
            {
                //Global method
                meth_attr &= ~PEAPI.MethAttr.Abstract;
                meth_attr |= PEAPI.MethAttr.Static;
            }
            else
            {
                if ((inst_list.Count > 0) && type_def.IsInterface && !IsStatic)
                {
                    Report.Error(start, "Method cannot have body if it is non-static declared in an interface");
                }

                if (IsAbstract)
                {
                    if (!type_def.IsAbstract)
                    {
                        Report.Error(start, String.Format("Abstract method '{0}' in non-abstract class '{1}'",
                                                          Name, type_def.FullName));
                    }
                    if (inst_list.Count > 0)
                    {
                        Report.Error(start, "Method cannot have body if it is abstract.");
                    }
                    return;
                }
            }

            if (entry_point)
            {
                methoddef.DeclareEntryPoint();
            }

            if (local_list.Count > 0)
            {
                int           ec          = Report.ErrorCount;
                PEAPI.Local[] local_array = new PEAPI.Local[local_list.Count];

                foreach (Local local in local_list)
                {
                    local_array[local.Slot] = local.GetPeapiLocal(code_gen);
                }

                if (Report.ErrorCount > ec)
                {
                    return;
                }

                if (zero_init)
                {
                    init_locals = true;
                }

                methoddef.AddLocals(local_array, init_locals);
            }

            /// Nothing seems to work if maxstack is not set,
            /// i need to find out if this NEEDs to be set
            /// and what its default value should be
            if (max_stack < 0)
            {
                max_stack = 8;
            }
            methoddef.SetMaxStack(max_stack);

            if (pinvoke_info)
            {
                methoddef.AddPInvokeInfo(pinvoke_mod.ModuleRef,
                                         (pinvoke_name != null ? pinvoke_name : name), pinvoke_attr);
            }

            if ((impl_attr & PEAPI.ImplAttr.Runtime) == PEAPI.ImplAttr.Runtime)
            {
                if (inst_list.Count > 0)
                {
                    Report.Error(start, String.Format("Method cannot have body if it is non-IL runtime-supplied, '{0}'",
                                                      FullName));
                }
            }
            else
            {
                if (((impl_attr & PEAPI.ImplAttr.Native) != 0) ||
                    ((impl_attr & PEAPI.ImplAttr.Unmanaged) != 0))
                {
                    Report.Error(start, String.Format("Cannot compile native/unmanaged method, '{0}'",
                                                      FullName));
                }
            }

            if (inst_list.Count > 0)
            {
                /* Has body */
                if ((impl_attr & PEAPI.ImplAttr.InternalCall) != 0)
                {
                    Report.Error(start, String.Format("Method cannot have body if it is an internal call, '{0}'",
                                                      FullName));
                }

                if (pinvoke_info)
                {
                    Report.Error(start, String.Format("Method cannot have body if it is pinvoke, '{0}'",
                                                      FullName));
                }
            }
            else
            {
                if (pinvoke_info ||
                    ((impl_attr & PEAPI.ImplAttr.Runtime) != 0) ||
                    ((impl_attr & PEAPI.ImplAttr.InternalCall) != 0))
                {
                    /* No body required */
                    return;
                }

                Report.Warning(start, "Method has no body, 'ret' emitted.");
                AddInstr(new SimpInstr(PEAPI.Op.ret, start));
            }

            PEAPI.CILInstructions cil = methoddef.CreateCodeBuffer();
            /// Create all the labels
            /// TODO: Most labels don't actually need to be created so we could
            /// probably only create the ones that need to be
            LabelInfo[] label_info = new LabelInfo[label_table.Count + label_list.Count];
            label_table.Values.CopyTo(label_info, 0);
            label_list.CopyTo(label_info, label_table.Count);
            int       previous_pos   = -1;
            LabelInfo previous_label = null;

            Array.Sort(label_info);

            foreach (LabelInfo label in label_info)
            {
                if (label.UseOffset)
                {
                    label.Define(new PEAPI.CILLabel(label.Offset, true));
                    continue;
                }
                if (label.Pos == previous_pos)
                {
                    label.Label = previous_label.Label;
                }
                else
                {
                    label.Define(cil.NewLabel());
                }

                previous_label = label;
                previous_pos   = label.Pos;
            }

            // Set all the label refs
            foreach (LabelInfo label in labelref_table.Values)
            {
                LabelInfo def = (LabelInfo)label_table[label.Name];
                if (def == null)
                {
                    Report.Error("Undefined Label:  " + label);
                    return;
                }
                label.Label = def.Label;
            }

            int label_pos      = 0;
            int next_label_pos = (label_info.Length > 0 ? label_info[0].Pos : -1);

            for (int i = 0; i < inst_list.Count; i++)
            {
                IInstr instr = (IInstr)inst_list[i];
                if (next_label_pos == i)
                {
                    cil.CodeLabel(label_info[label_pos].Label);
                    if (label_pos < label_info.Length)
                    {
                        while (next_label_pos == i && ++label_pos < label_info.Length)
                        {
                            if (label_info[label_pos].UseOffset)
                            {
                                cil.CodeLabel(label_info[label_pos].Label);
                            }
                            next_label_pos = label_info[label_pos].Pos;
                        }
                    }
                    if (label_pos >= label_info.Length)
                    {
                        next_label_pos = -1;
                    }
                }
                if (source != null)
                {
                    source.MarkLocation(instr.Location.line, cil.Offset);
                }
                instr.Emit(code_gen, this, cil);
            }

            if (source != null)
            {
                source.MarkLocation(source.EndLine, cil.Offset);
            }
        }