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); } }
public void AddInstr (IInstr instr) { inst_list.Add (instr); }
public void AddInstr(IInstr instr) { inst_list.Add(instr); }