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