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); }
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); } }