public MethodDef(CodeGen codegen, PEAPI.MethAttr meth_attr, PEAPI.CallConv call_conv, PEAPI.ImplAttr impl_attr, string name, BaseTypeRef ret_type, ArrayList param_list, Location start, GenericParameters gen_params, TypeDef type_def) { this.codegen = codegen; this.meth_attr = meth_attr; this.call_conv = call_conv; this.impl_attr = impl_attr; this.name = name; this.param_list = param_list; this.type_def = type_def; this.gen_params = gen_params; this.ret_param = new ParamDef(PEAPI.ParamAttr.Default, "", ret_type); this.start = (Location)start.Clone(); inst_list = new ArrayList(); label_table = new Hashtable(); labelref_table = new Hashtable(); label_list = new ArrayList(); local_list = new ArrayList(); named_local_tables = new ArrayList(); named_local_tables.Add(new Hashtable()); current_scope_depth = 0; entry_point = false; zero_init = false; init_locals = false; max_stack = -1; pinvoke_info = false; is_defined = false; is_resolved = false; ResolveGenParams(); CreateSignature(); codegen.BeginMethodDef(this); if (codegen.SymbolWriter != null) { source = codegen.SymbolWriter.BeginMethod(this, start); } }
public MethodDef (CodeGen codegen, PEAPI.MethAttr meth_attr, PEAPI.CallConv call_conv, PEAPI.ImplAttr impl_attr, string name, BaseTypeRef ret_type, ArrayList param_list, Location start, GenericParameters gen_params, TypeDef type_def) { this.codegen = codegen; this.meth_attr = meth_attr; this.call_conv = call_conv; this.impl_attr = impl_attr; this.name = name; this.param_list = param_list; this.type_def = type_def; this.gen_params = gen_params; this.ret_param = new ParamDef (PEAPI.ParamAttr.Default, "", ret_type); this.start = (Location) start.Clone (); inst_list = new ArrayList (); label_table = new Hashtable (); labelref_table = new Hashtable (); label_list = new ArrayList (); local_list = new ArrayList (); named_local_tables = new ArrayList (); named_local_tables.Add (new Hashtable ()); current_scope_depth = 0; entry_point = false; zero_init = false; init_locals = false; max_stack = -1; pinvoke_info = false; is_defined = false; is_resolved = false; ResolveGenParams (); CreateSignature (); codegen.BeginMethodDef (this); if (codegen.SymbolWriter != null) source = codegen.SymbolWriter.BeginMethod (this, start); }
private void FixAttributes () { if (name == ".ctor" || name == ".cctor") meth_attr |= PEAPI.MethAttr.SpecialName | PEAPI.MethAttr.RTSpecialName; // If methods aren't flagged as static they are instance if ((PEAPI.MethAttr.Static & meth_attr) == 0) call_conv |= PEAPI.CallConv.Instance; }
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); }
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); } }
static string CreateSignature(BaseTypeRef RetType, string name, IList param_list, int gen_param_count, PEAPI.MethAttr attrs) { StringBuilder builder = new StringBuilder(); if ((attrs & PEAPI.MethAttr.Static) == 0) { builder.Append("instance "); } builder.Append(RetType.FullName); builder.Append(" "); builder.Append(name); if (gen_param_count > 0) { builder.AppendFormat("`{0}", gen_param_count); } builder.Append('('); if (param_list != null) { bool first = true; foreach (ParamDef paramdef in param_list) { if (!first) { builder.Append(','); } builder.Append(paramdef.TypeName); first = false; } } builder.Append(')'); return(builder.ToString()); }