[utils] Fix inet_pton fallback.
[mono.git] / mcs / ilasm / codegen / CodeGen.cs
1 //\r
2 // Mono.ILASM.CodeGen.cs\r
3 //\r
4 // Author(s):\r
5 //  Sergey Chaban (serge@wildwestsoftware.com)\r
6 //  Jackson Harper (Jackson@LatitudeGeo.com)\r
7 //\r
8 // (C) Sergey Chaban\r
9 // (C) 2003 Jackson Harper, All rights reserved\r
10 //\r
11 \r
12 using PEAPI;\r
13 using System;\r
14 using System.IO;\r
15 using System.Collections;\r
16 using System.Reflection;\r
17 using System.Reflection.Emit;\r
18 using System.Text;\r
19 using System.Security;\r
20 \r
21 using SSPermissionSet = System.Security.PermissionSet;\r
22 using MIPermissionSet = Mono.ILASM.PermissionSet;\r
23 \r
24 using MIAssembly = Mono.ILASM.Assembly;\r
25 \r
26 namespace Mono.ILASM {\r
27 \r
28         public class CodeGen {\r
29 \r
30                 private PEFile pefile;\r
31                 private ExternAssembly current_assemblyref;\r
32 //                private ExternModule current_moduleref;\r
33                 private string current_namespace;\r
34                 private TypeDef current_typedef;\r
35                 private MethodDef current_methoddef;\r
36                 private ArrayList typedef_stack;\r
37                 private int typedef_stack_top;\r
38                 private SymbolWriter symwriter;\r
39                 private ICustomAttrTarget current_customattrtarget;\r
40                 private IDeclSecurityTarget current_declsectarget;\r
41                 private PEAPI.NativeType current_field_native_type;\r
42 \r
43                 private MIAssembly this_assembly;\r
44                         \r
45                 private TypeManager type_manager;\r
46                 private ExternTable extern_table;\r
47                 private Hashtable global_field_table;\r
48                 private Hashtable global_method_table;\r
49                 private Hashtable global_methodref_table;\r
50                 private Hashtable global_fieldref_table;\r
51                 private Hashtable data_table;\r
52                 private FileRef file_ref;\r
53                 private ArrayList manifestResources;\r
54                 private Hashtable typeref_table;\r
55                 \r
56                 private ArrayList defcont_list;\r
57 \r
58                 private int sub_system;\r
59                 private int cor_flags;\r
60                 private long image_base;\r
61                 private long stack_reserve;\r
62 \r
63                 private string output_file;\r
64                 private bool is_dll;\r
65                 private bool entry_point;\r
66 \r
67                 private Module this_module;\r
68 \r
69                 public CodeGen (string output_file, bool is_dll, bool debugging_info)\r
70                 {\r
71                         this.output_file = output_file;\r
72                         this.is_dll = is_dll;\r
73 \r
74                         if (debugging_info)\r
75                                 symwriter = new SymbolWriter (output_file);\r
76 \r
77                         type_manager = new TypeManager (this);\r
78                         extern_table = new ExternTable ();\r
79                         typedef_stack = new ArrayList ();\r
80                         typedef_stack_top = 0;\r
81                         global_field_table = new Hashtable ();\r
82                         global_method_table = new Hashtable ();\r
83 \r
84                         data_table = new Hashtable ();\r
85 \r
86                         defcont_list = new ArrayList ();\r
87 \r
88                         sub_system = -1;\r
89                         cor_flags = -1;\r
90                         image_base = -1;\r
91                         stack_reserve = -1;\r
92                         entry_point = false;\r
93                         this_module = null;\r
94                 }\r
95 \r
96                 public PEFile PEFile {\r
97                         get { return pefile; }\r
98                 }\r
99 \r
100                 public SymbolWriter SymbolWriter {\r
101                         get { return symwriter; }\r
102                 }\r
103 \r
104                 public string CurrentNameSpace {\r
105                         get { return current_namespace; }\r
106                         set { current_namespace = value; }\r
107                 }\r
108 \r
109                 public TypeDef CurrentTypeDef {\r
110                         get { return current_typedef; }\r
111                 }\r
112 \r
113                 public MethodDef CurrentMethodDef {\r
114                         get { return current_methoddef; }\r
115                 }\r
116 \r
117                 public ExternAssembly CurrentAssemblyRef {\r
118                         get { return current_assemblyref; }\r
119                 }\r
120 \r
121 //                public ExternModule CurrentModuleRef {\r
122 //                        get { return current_moduleref; }\r
123 //                }\r
124 \r
125                 public ICustomAttrTarget CurrentCustomAttrTarget {\r
126                         get { return current_customattrtarget; }\r
127                         set { current_customattrtarget = value; }\r
128                 }\r
129 \r
130                 public IDeclSecurityTarget CurrentDeclSecurityTarget {\r
131                         get { return current_declsectarget; }\r
132                         set { current_declsectarget = value; }\r
133                 }\r
134 \r
135                 public ExternTable ExternTable {\r
136                         get { return extern_table; }\r
137                 }\r
138 \r
139                 public TypeManager TypeManager {\r
140                         get { return type_manager; }\r
141                 }\r
142 \r
143                 public bool HasEntryPoint {\r
144                         get { return entry_point; }\r
145                         set { \r
146                                 /* if (!value) error: unsetting entrypoint ? */\r
147                                 if (entry_point)\r
148                                         Report.Error ("Multiple .entrypoint declarations.");\r
149                                 entry_point = value;\r
150                         }                \r
151                 }\r
152 \r
153                 public TypeRef GetTypeRef (string name)\r
154                 {\r
155                         TypeRef tr = null;\r
156 \r
157                         if (typeref_table == null) \r
158                                 typeref_table = new Hashtable ();\r
159                         else \r
160                                 tr = typeref_table [name] as TypeRef;\r
161 \r
162                         if (tr == null) {\r
163                                 tr = new TypeRef (name, false, null);\r
164                                 typeref_table [name] = tr;\r
165                         }\r
166 \r
167                         return tr;\r
168                 }\r
169 \r
170                 public GlobalMethodRef GetGlobalMethodRef (BaseTypeRef ret_type, PEAPI.CallConv call_conv,\r
171                                 string name, BaseTypeRef[] param, int gen_param_count)\r
172                 {\r
173                         string key = MethodDef.CreateSignature (ret_type, call_conv, name, param, gen_param_count, true);\r
174 \r
175                         GlobalMethodRef methref = null;\r
176 \r
177                         if (global_methodref_table == null)\r
178                                 global_methodref_table = new Hashtable ();\r
179                         else\r
180                                 methref = (GlobalMethodRef) global_methodref_table [key];\r
181 \r
182                         if (methref == null) {\r
183                                 methref = new GlobalMethodRef (ret_type, call_conv, name, param, gen_param_count);\r
184                                 global_methodref_table [key] = methref;\r
185                         }\r
186                         \r
187                         return methref;\r
188                 }\r
189 \r
190                 public GlobalFieldRef GetGlobalFieldRef (BaseTypeRef ret_type, string name)\r
191                 {\r
192                         string key = ret_type.FullName + name;\r
193 \r
194                         GlobalFieldRef fieldref = null;\r
195 \r
196                         if (global_fieldref_table == null)\r
197                                 global_fieldref_table = new Hashtable ();\r
198                         else\r
199                                 fieldref = (GlobalFieldRef) global_fieldref_table [key];\r
200 \r
201                         if (fieldref == null) {\r
202                                 fieldref = new GlobalFieldRef (ret_type, name);\r
203                                 global_fieldref_table [key] = fieldref;\r
204                         }\r
205                         \r
206                         return fieldref;\r
207                 }\r
208 \r
209                 public void SetSubSystem (int sub_system)\r
210                 {\r
211                         this.sub_system = sub_system;\r
212                 }\r
213 \r
214                 public void SetCorFlags (int cor_flags)\r
215                 {\r
216                         this.cor_flags = cor_flags;\r
217                 }\r
218 \r
219                 public void SetImageBase (long image_base)\r
220                 {\r
221                         this.image_base = image_base;\r
222                 }\r
223 \r
224                 public void SetStackReserve (long stack_reserve)\r
225                 {\r
226                         this.stack_reserve = stack_reserve;\r
227                 }\r
228 \r
229                 public void SetThisAssembly (string name, PEAPI.AssemAttr attr)\r
230                 {\r
231                         if (this_assembly != null && this_assembly.Name != name)\r
232                                 Report.Error ("Multiple assembly declarations");\r
233 \r
234                         this_assembly = new Assembly (name);\r
235                         this_assembly.SetAssemblyAttr (attr);\r
236                         if (name != "mscorlib")\r
237                                 ExternTable.AddCorlib ();\r
238                 }\r
239 \r
240                 public void SetModuleName (string module_name)\r
241                 {\r
242                         this_module = new Module (module_name);\r
243                         CurrentCustomAttrTarget = this_module;\r
244                 }\r
245 \r
246                 public void SetFileRef (FileRef file_ref)\r
247                 {\r
248                         this.file_ref = file_ref;\r
249                 }\r
250 \r
251                 public MIAssembly ThisAssembly {\r
252                         get { return this_assembly; }\r
253                 }\r
254 \r
255                 public bool IsThisAssembly (string name)\r
256                 {\r
257                         return (this_assembly != null && name == this_assembly.Name);\r
258                 }\r
259 \r
260                 public Module ThisModule {\r
261                         get { return this_module; }\r
262                 }\r
263                 \r
264                 public bool IsThisModule (string name)\r
265                 {\r
266                         return (this_module != null && name == this_module.Name);\r
267                 }\r
268 \r
269                 public void BeginSourceFile (string name)\r
270                 {\r
271                         if (symwriter != null)\r
272                                 symwriter.BeginSourceFile (name);\r
273                 }\r
274 \r
275                 public void EndSourceFile ()\r
276                 {\r
277                         if (symwriter != null)\r
278                                 symwriter.EndSourceFile ();\r
279                 }\r
280 \r
281                 public void BeginTypeDef (TypeAttr attr, string name, BaseClassRef parent,\r
282                                 ArrayList impl_list, Location location, GenericParameters gen_params)\r
283                 {\r
284                         TypeDef outer = null;\r
285                         string cache_name = CacheName (name);\r
286                         if (typedef_stack_top > 0) {\r
287                                 StringBuilder sb = new StringBuilder ();\r
288 \r
289                                 for (int i = 0; i < typedef_stack_top; i++){\r
290                                         outer = (TypeDef) typedef_stack [i];\r
291                                         if (i == 0)\r
292                                                 /* Use FullName for outermost class to get the\r
293                                                    namespace also */\r
294                                                 sb.Append (outer.FullName);\r
295                                         else\r
296                                                 sb.Append (outer.Name);\r
297                                         sb.Append ("/");\r
298                                 }\r
299                                 sb.Append (name);\r
300                                 cache_name = sb.ToString ();\r
301                         }\r
302 \r
303                         TypeDef typedef = type_manager[cache_name];\r
304 \r
305                         if (typedef != null) {\r
306                                 // Class head is allready defined, we are just reopening the class\r
307                                 current_customattrtarget = current_typedef = typedef;\r
308                                 current_declsectarget = typedef;\r
309                                 typedef_stack.Add (current_typedef);\r
310                                 typedef_stack_top++;\r
311                                 return;\r
312                         }\r
313 \r
314                         typedef = new TypeDef (attr, current_namespace,\r
315                                         name, parent, impl_list, location, gen_params, outer);\r
316 \r
317                         type_manager[cache_name] = typedef;\r
318                         current_customattrtarget = current_typedef = typedef;\r
319                         current_declsectarget = typedef;\r
320                         typedef_stack.Add (typedef);\r
321                         typedef_stack_top++;\r
322                 }\r
323 \r
324                 public void AddFieldMarshalInfo (PEAPI.NativeType native_type)\r
325                 {\r
326                         current_field_native_type = native_type;\r
327                 }\r
328 \r
329                 public void AddFieldDef (FieldDef fielddef)\r
330                 {\r
331                         if (current_field_native_type != null) {\r
332                                 fielddef.AddMarshalInfo (current_field_native_type);\r
333                                 current_field_native_type = null;\r
334                         }\r
335 \r
336                         if (current_typedef != null) {\r
337                                 current_typedef.AddFieldDef (fielddef);\r
338                         } else {\r
339                                 global_field_table.Add (\r
340                                         new DictionaryEntry (fielddef.Name, fielddef.Type.FullName),\r
341                                         fielddef);\r
342                         }\r
343                 }\r
344 \r
345                 public void AddDataDef (DataDef datadef)\r
346                 {\r
347                         if (data_table [datadef.Name] != null)\r
348                                 Report.Error ("Duplicate global label '" + datadef.Name + "'");\r
349                         data_table [datadef.Name] = datadef;\r
350                 }\r
351 \r
352                 public void AddManifestResource (ManifestResource mr)\r
353                 {\r
354                         if (manifestResources == null)\r
355                                 manifestResources = new ArrayList ();\r
356                         manifestResources.Add (mr);\r
357                 }\r
358 \r
359                 public PEAPI.DataConstant GetDataConst (string name)\r
360                 {\r
361                         DataDef def = (DataDef) data_table [name];\r
362                         if (def == null)\r
363                                 return null;\r
364 \r
365                         return (DataConstant) def.PeapiConstant;\r
366                 }\r
367 \r
368                 public void BeginMethodDef (MethodDef methoddef)\r
369                 {\r
370                         if (current_typedef != null) {\r
371                                 current_typedef.AddMethodDef (methoddef);\r
372                         } else {\r
373                                 global_method_table.Add (methoddef.Signature,\r
374                                                 methoddef);\r
375                         }\r
376 \r
377                         current_customattrtarget = current_methoddef = methoddef;\r
378                         current_declsectarget = methoddef;\r
379                 }\r
380 \r
381                 public void EndMethodDef (Location location)\r
382                 {\r
383                         if (symwriter != null)\r
384                                 symwriter.EndMethod (location);\r
385 \r
386                         current_methoddef = null;\r
387                 }\r
388 \r
389                 public void EndTypeDef ()\r
390                 {\r
391                         typedef_stack_top--;\r
392                         typedef_stack.RemoveAt (typedef_stack_top);\r
393 \r
394                         if (typedef_stack_top > 0)\r
395                                 current_typedef = (TypeDef) typedef_stack [typedef_stack_top-1];\r
396                         else\r
397                                 current_typedef = null;\r
398 \r
399                 }\r
400 \r
401                 public void BeginAssemblyRef (string name, AssemblyName asmb_name, PEAPI.AssemAttr attr)\r
402                 {\r
403                         current_customattrtarget = current_assemblyref = ExternTable.AddAssembly (name, asmb_name, attr);\r
404                         current_declsectarget = current_assemblyref;\r
405                 }\r
406 \r
407                 public void EndAssemblyRef ()\r
408                 {\r
409                         current_assemblyref = null;\r
410                         current_customattrtarget = null;\r
411                         current_declsectarget = null;\r
412                 }\r
413 \r
414                 public void AddToDefineContentsList (TypeDef typedef)\r
415                 {\r
416                         defcont_list.Add (typedef);\r
417                 }\r
418 \r
419                 public void AddPermission (PEAPI.SecurityAction sec_action, object perm)\r
420                 {\r
421                         if (CurrentDeclSecurityTarget == null)\r
422                                 return;\r
423 \r
424                         AddPermission (sec_action, perm, CurrentDeclSecurityTarget.DeclSecurity);\r
425                 }\r
426 \r
427                 private void AddPermission (PEAPI.SecurityAction sec_action, object perm, DeclSecurity decl_sec)\r
428                 {\r
429                         SSPermissionSet ps = perm as SSPermissionSet;\r
430                         if (ps != null) {\r
431                                 decl_sec.AddPermissionSet (sec_action, ps);\r
432                                 return;\r
433                         }\r
434 \r
435                         IPermission iper = perm as IPermission;\r
436                         if (iper != null) {\r
437                                 decl_sec.AddPermission (sec_action, iper);\r
438                                 return;\r
439                         }\r
440 \r
441                         MIPermissionSet ps20 = perm as MIPermissionSet;\r
442                         if (ps20 != null) {\r
443                                 decl_sec.AddPermissionSet (sec_action, ps20);\r
444                                 return;\r
445                         }\r
446                 }\r
447 \r
448                 public void Write ()\r
449                 {\r
450                         FileStream out_stream = null;\r
451 \r
452                         try {\r
453                                 if (ThisModule == null)\r
454                                         this_module = new Module (Path.GetFileName (output_file));\r
455 \r
456                                 out_stream = new FileStream (output_file, FileMode.Create, FileAccess.Write);\r
457                                 pefile = new PEFile (ThisAssembly != null ? ThisAssembly.Name : null, ThisModule.Name, is_dll, ThisAssembly != null, null, out_stream);\r
458                                 PEAPI.Assembly asmb = pefile.GetThisAssembly ();\r
459 \r
460                                 ThisModule.PeapiModule = pefile.GetThisModule ();\r
461 \r
462                                 if (file_ref != null)\r
463                                         file_ref.Resolve (this);\r
464 \r
465                                 extern_table.Resolve (this);\r
466                                 type_manager.DefineAll ();\r
467 \r
468                                 if (manifestResources != null) {\r
469                                         foreach (ManifestResource mr in manifestResources)\r
470                                                 pefile.AddManifestResource (mr);\r
471                                 }\r
472 \r
473                                 foreach (FieldDef fielddef in global_field_table.Values) {\r
474                                         fielddef.Define (this);\r
475                                 }\r
476 \r
477                                 foreach (MethodDef methoddef in global_method_table.Values) {\r
478                                         methoddef.Define (this);\r
479                                 }\r
480 \r
481                                 foreach (TypeDef typedef in defcont_list) {\r
482                                         typedef.DefineContents (this);\r
483                                 }\r
484 \r
485                                 if (ThisAssembly != null)\r
486                                         ThisAssembly.Resolve (this, pefile.GetThisAssembly ());\r
487                                 ThisModule.Resolve (this, pefile.GetThisModule ());\r
488 \r
489                                 if (sub_system != -1)\r
490                                         pefile.SetSubSystem ((PEAPI.SubSystem) sub_system);\r
491                                 if (cor_flags != -1)\r
492                                         pefile.SetCorFlags (cor_flags);\r
493                                 if (stack_reserve != -1)\r
494                                         pefile.SetStackReserve (stack_reserve);\r
495 \r
496                                 pefile.WritePEFile ();\r
497 \r
498                                 if (symwriter != null) {\r
499                                         Guid guid = pefile.GetThisModule ().Guid;\r
500                                         symwriter.Write (guid);\r
501                                 }\r
502                         } finally {\r
503                                 if (out_stream != null)\r
504                                         out_stream.Close ();\r
505                         }\r
506                 }\r
507 \r
508                 public PEAPI.Method ResolveMethod (string signature)\r
509                 {\r
510                         MethodDef methoddef = (MethodDef) global_method_table[signature];\r
511                         if (methoddef == null)\r
512                                 Report.Error ("Unable to resolve global method : " + signature);\r
513 \r
514                         return methoddef.Resolve (this);\r
515                 }\r
516 \r
517                 public PEAPI.Method ResolveVarargMethod (string sig_only_required_params, string sig_with_optional_params,\r
518                                 CodeGen code_gen, PEAPI.Type[] opt)\r
519                 {\r
520                         MethodDef methoddef = (MethodDef) global_method_table [sig_only_required_params];\r
521                         if (methoddef == null)\r
522                                 Report.Error ("Unable to resolve global method : " + sig_only_required_params);\r
523 \r
524                         methoddef.Resolve (code_gen);\r
525                         return methoddef.GetVarargSig (opt, sig_with_optional_params);\r
526                 }\r
527 \r
528                 public PEAPI.Field ResolveField (string name, string type_name)\r
529                 {\r
530                         FieldDef fielddef = (FieldDef) global_field_table[new DictionaryEntry (name, type_name)]; \r
531                         if (fielddef == null)\r
532                                 Report.Error (String.Format ("Unable to resolve global field : {0} {1}", type_name, name));\r
533 \r
534                         return fielddef.Resolve (this);\r
535                 }\r
536 \r
537                 private string CacheName (string name)\r
538                 {\r
539                         if (current_namespace == null ||\r
540                                         current_namespace == String.Empty)\r
541                                 return name;\r
542 \r
543                         return current_namespace + "." + name;\r
544                 }\r
545         }\r
546 \r
547 }\r
548 \r