Fixes cloning of a variable declarator.
[mono.git] / mcs / mcs / codegen.cs
1 //
2 // codegen.cs: The code generator
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // Copyright 2001, 2002, 2003 Ximian, Inc.
8 // Copyright 2004 Novell, Inc.
9 //
10
11 //
12 // Please leave this defined on SVN: The idea is that when we ship the
13 // compiler to end users, if the compiler crashes, they have a chance
14 // to narrow down the problem.   
15 //
16 // Only remove it if you need to debug locally on your tree.
17 //
18 //#define PRODUCTION
19
20 using System;
21 using System.IO;
22 using System.Collections.Generic;
23 using System.Globalization;
24 using System.Reflection;
25 using System.Reflection.Emit;
26 using System.Runtime.InteropServices;
27 using System.Security;
28 using System.Security.Cryptography;
29 using System.Security.Permissions;
30
31 using Mono.Security.Cryptography;
32
33 namespace Mono.CSharp {
34
35         /// <summary>
36         ///    Code generator class.
37         /// </summary>
38         public class CodeGen {
39                 static AppDomain current_domain;
40
41                 // Breaks dynamic and repl
42                 public static AssemblyClass Assembly;
43
44                 static CodeGen ()
45                 {
46                         Reset ();
47                 }
48
49                 public static void Reset ()
50                 {
51                         Assembly = new AssemblyClass ();
52                 }
53
54                 public static string Basename (string name)
55                 {
56                         int pos = name.LastIndexOf ('/');
57
58                         if (pos != -1)
59                                 return name.Substring (pos + 1);
60
61                         pos = name.LastIndexOf ('\\');
62                         if (pos != -1)
63                                 return name.Substring (pos + 1);
64
65                         return name;
66                 }
67
68                 public static string Dirname (string name)
69                 {
70                         int pos = name.LastIndexOf ('/');
71
72                         if (pos != -1)
73                                 return name.Substring (0, pos);
74
75                         pos = name.LastIndexOf ('\\');
76                         if (pos != -1)
77                                 return name.Substring (0, pos);
78
79                         return ".";
80                 }
81
82                 static public string FileName;
83                                 
84                 //
85                 // Initializes the code generator variables for interactive use (repl)
86                 //
87                 static public void InitDynamic (CompilerContext ctx, string name)
88                 {
89                         current_domain = AppDomain.CurrentDomain;
90                         AssemblyName an = Assembly.GetAssemblyName (name, name);
91                         
92                         Assembly.Builder = current_domain.DefineDynamicAssembly (an, AssemblyBuilderAccess.Run);
93                         RootContext.ToplevelTypes = new ModuleCompiled (ctx, true);
94                         RootContext.ToplevelTypes.Builder = Assembly.Builder.DefineDynamicModule (Basename (name), false);
95                         Assembly.Name = Assembly.Builder.GetName ();
96                 }
97
98                 //
99                 // Initializes the code generator variables
100                 //
101                 static public bool Init (string name, string output, bool want_debugging_support, CompilerContext ctx)
102                 {
103                         FileName = output;
104                         AssemblyName an = Assembly.GetAssemblyName (name, output);
105                         if (an == null)
106                                 return false;
107
108                         if (an.KeyPair != null) {
109                                 // If we are going to strong name our assembly make
110                                 // sure all its refs are strong named
111                                 foreach (Assembly a in ctx.GlobalRootNamespace.Assemblies) {
112                                         AssemblyName ref_name = a.GetName ();
113                                         byte [] b = ref_name.GetPublicKeyToken ();
114                                         if (b == null || b.Length == 0) {
115                                                 ctx.Report.Error (1577, "Assembly generation failed " +
116                                                                 "-- Referenced assembly '" +
117                                                                 ref_name.Name +
118                                                                 "' does not have a strong name.");
119                                                 //Environment.Exit (1);
120                                         }
121                                 }
122                         }
123                         
124                         current_domain = AppDomain.CurrentDomain;
125
126                         try {
127                                 Assembly.Builder = current_domain.DefineDynamicAssembly (an,
128                                         AssemblyBuilderAccess.RunAndSave, Dirname (name));
129                         }
130                         catch (ArgumentException) {
131                                 // specified key may not be exportable outside it's container
132                                 if (RootContext.StrongNameKeyContainer != null) {
133                                         ctx.Report.Error (1548, "Could not access the key inside the container `" +
134                                                 RootContext.StrongNameKeyContainer + "'.");
135                                         Environment.Exit (1);
136                                 }
137                                 throw;
138                         }
139                         catch (CryptographicException) {
140                                 if ((RootContext.StrongNameKeyContainer != null) || (RootContext.StrongNameKeyFile != null)) {
141                                         ctx.Report.Error (1548, "Could not use the specified key to strongname the assembly.");
142                                         Environment.Exit (1);
143                                 }
144                                 return false;
145                         }
146
147                         // Get the complete AssemblyName from the builder
148                         // (We need to get the public key and token)
149                         Assembly.Name = Assembly.Builder.GetName ();
150
151                         //
152                         // Pass a path-less name to DefineDynamicModule.  Wonder how
153                         // this copes with output in different directories then.
154                         // FIXME: figure out how this copes with --output /tmp/blah
155                         //
156                         // If the third argument is true, the ModuleBuilder will dynamically
157                         // load the default symbol writer.
158                         //
159                         try {
160                                 RootContext.ToplevelTypes.Builder = Assembly.Builder.DefineDynamicModule (
161                                         Basename (name), Basename (output), want_debugging_support);
162
163 #if !MS_COMPATIBLE
164                                 // TODO: We should use SymbolWriter from DefineDynamicModule
165                                 if (want_debugging_support && !SymbolWriter.Initialize (RootContext.ToplevelTypes.Builder, output)) {
166                                         ctx.Report.Error (40, "Unexpected debug information initialization error `{0}'",
167                                                 "Could not find the symbol writer assembly (Mono.CompilerServices.SymbolWriter.dll)");
168                                         return false;
169                                 }
170 #endif
171                         } catch (ExecutionEngineException e) {
172                                 ctx.Report.Error (40, "Unexpected debug information initialization error `{0}'",
173                                         e.Message);
174                                 return false;
175                         }
176
177                         return true;
178                 }
179
180                 static public void Save (string name, bool saveDebugInfo, Report Report)
181                 {
182                         PortableExecutableKinds pekind;
183                         ImageFileMachine machine;
184
185                         switch (RootContext.Platform) {
186                         case Platform.X86:
187                                 pekind = PortableExecutableKinds.Required32Bit;
188                                 machine = ImageFileMachine.I386;
189                                 break;
190                         case Platform.X64:
191                                 pekind = PortableExecutableKinds.PE32Plus;
192                                 machine = ImageFileMachine.AMD64;
193                                 break;
194                         case Platform.IA64:
195                                 pekind = PortableExecutableKinds.PE32Plus;
196                                 machine = ImageFileMachine.IA64;
197                                 break;
198                         case Platform.AnyCPU:
199                         default:
200                                 pekind = PortableExecutableKinds.ILOnly;
201                                 machine = ImageFileMachine.I386;
202                                 break;
203                         }
204                         try {
205                                 Assembly.Builder.Save (Basename (name), pekind, machine);
206                         }
207                         catch (COMException) {
208                                 if ((RootContext.StrongNameKeyFile == null) || (!RootContext.StrongNameDelaySign))
209                                         throw;
210
211                                 // FIXME: it seems Microsoft AssemblyBuilder doesn't like to delay sign assemblies 
212                                 Report.Error (1548, "Couldn't delay-sign the assembly with the '" +
213                                         RootContext.StrongNameKeyFile +
214                                         "', Use MCS with the Mono runtime or CSC to compile this assembly.");
215                         }
216                         catch (System.IO.IOException io) {
217                                 Report.Error (16, "Could not write to file `"+name+"', cause: " + io.Message);
218                                 return;
219                         }
220                         catch (System.UnauthorizedAccessException ua) {
221                                 Report.Error (16, "Could not write to file `"+name+"', cause: " + ua.Message);
222                                 return;
223                         }
224                         catch (System.NotImplementedException nie) {
225                                 Report.RuntimeMissingSupport (Location.Null, nie.Message);
226                                 return;
227                         }
228
229                         //
230                         // Write debuger symbol file
231                         //
232                         if (saveDebugInfo)
233                                 SymbolWriter.WriteSymbolFile ();
234                         }
235         }
236
237         /// <summary>
238         ///   An Emit Context is created for each body of code (from methods,
239         ///   properties bodies, indexer bodies or constructor bodies)
240         /// </summary>
241         public class EmitContext : BuilderContext
242         {
243                 // TODO: Has to be private
244                 public ILGenerator ig;
245
246                 /// <summary>
247                 ///   The value that is allowed to be returned or NULL if there is no
248                 ///   return type.
249                 /// </summary>
250                 TypeSpec return_type;
251
252                 /// <summary>
253                 ///   Keeps track of the Type to LocalBuilder temporary storage created
254                 ///   to store structures (used to compute the address of the structure
255                 ///   value on structure method invocations)
256                 /// </summary>
257                 Dictionary<TypeSpec, object> temporary_storage;
258
259                 /// <summary>
260                 ///   The location where we store the return value.
261                 /// </summary>
262                 public LocalBuilder return_value;
263
264                 /// <summary>
265                 ///   The location where return has to jump to return the
266                 ///   value
267                 /// </summary>
268                 public Label ReturnLabel;
269
270                 /// <summary>
271                 ///   If we already defined the ReturnLabel
272                 /// </summary>
273                 public bool HasReturnLabel;
274
275                 /// <summary>
276                 ///   Current loop begin and end labels.
277                 /// </summary>
278                 public Label LoopBegin, LoopEnd;
279
280                 /// <summary>
281                 ///   Default target in a switch statement.   Only valid if
282                 ///   InSwitch is true
283                 /// </summary>
284                 public Label DefaultTarget;
285
286                 /// <summary>
287                 ///   If this is non-null, points to the current switch statement
288                 /// </summary>
289                 public Switch Switch;
290
291                 /// <summary>
292                 ///  Whether we are inside an anonymous method.
293                 /// </summary>
294                 public AnonymousExpression CurrentAnonymousMethod;
295                 
296                 public readonly IMemberContext MemberContext;
297
298                 DynamicSiteClass dynamic_site_container;
299
300                 public EmitContext (IMemberContext rc, ILGenerator ig, TypeSpec return_type)
301                 {
302                         this.MemberContext = rc;
303                         this.ig = ig;
304
305                         this.return_type = return_type;
306                 }
307
308 #region Properties
309
310                 public TypeSpec CurrentType {
311                         get { return MemberContext.CurrentType; }
312                 }
313
314                 public TypeParameter[] CurrentTypeParameters {
315                         get { return MemberContext.CurrentTypeParameters; }
316                 }
317
318                 public MemberCore CurrentTypeDefinition {
319                         get { return MemberContext.CurrentMemberDefinition; }
320                 }
321
322                 public bool IsStatic {
323                         get { return MemberContext.IsStatic; }
324                 }
325
326                 bool IsAnonymousStoreyMutateRequired {
327                         get {
328                                 return CurrentAnonymousMethod != null &&
329                                         CurrentAnonymousMethod.Storey != null &&
330                                         CurrentAnonymousMethod.Storey.Mutator != null;
331                         }
332                 }
333
334                 // Has to be used for emitter errors only
335                 public Report Report {
336                         get { return MemberContext.Compiler.Report; }
337                 }
338
339                 public TypeSpec ReturnType {
340                         get {
341                                 return return_type;
342                         }
343                 }
344 #endregion
345
346                 /// <summary>
347                 ///   This is called immediately before emitting an IL opcode to tell the symbol
348                 ///   writer to which source line this opcode belongs.
349                 /// </summary>
350                 public void Mark (Location loc)
351                 {
352                         if (!SymbolWriter.HasSymbolWriter || HasSet (Options.OmitDebugInfo) || loc.IsNull)
353                                 return;
354
355                         SymbolWriter.MarkSequencePoint (ig, loc);
356                 }
357
358                 public void DefineLocalVariable (string name, LocalBuilder builder)
359                 {
360                         SymbolWriter.DefineLocalVariable (name, builder);
361                 }
362
363                 public void BeginCatchBlock (TypeSpec type)
364                 {
365                         ig.BeginCatchBlock (type.GetMetaInfo ());
366                 }
367
368                 public void BeginExceptionBlock ()
369                 {
370                         ig.BeginExceptionBlock ();
371                 }
372
373                 public void BeginFinallyBlock ()
374                 {
375                         ig.BeginFinallyBlock ();
376                 }
377
378                 public void BeginScope ()
379                 {
380                         ig.BeginScope();
381                         SymbolWriter.OpenScope(ig);
382                 }
383
384                 public void EndExceptionBlock ()
385                 {
386                         ig.EndExceptionBlock ();
387                 }
388
389                 public void EndScope ()
390                 {
391                         ig.EndScope();
392                         SymbolWriter.CloseScope(ig);
393                 }
394
395                 //
396                 // Creates a nested container in this context for all dynamic compiler generated stuff
397                 //
398                 public DynamicSiteClass CreateDynamicSite ()
399                 {
400                         if (dynamic_site_container == null) {
401                                 var mc = MemberContext.CurrentMemberDefinition as MemberBase;
402                                 dynamic_site_container = new DynamicSiteClass (CurrentTypeDefinition.Parent.PartialContainer, mc, CurrentTypeParameters);
403
404                                 RootContext.ToplevelTypes.AddCompilerGeneratedClass (dynamic_site_container);
405                                 dynamic_site_container.CreateType ();
406                                 dynamic_site_container.DefineType ();
407                                 dynamic_site_container.ResolveTypeParameters ();
408                                 dynamic_site_container.Define ();
409                         }
410
411                         return dynamic_site_container;
412                 }
413
414                 public LocalBuilder DeclareLocal (TypeSpec type, bool pinned)
415                 {
416                         if (IsAnonymousStoreyMutateRequired)
417                                 type = CurrentAnonymousMethod.Storey.Mutator.Mutate (type);
418
419                         return ig.DeclareLocal (type.GetMetaInfo (), pinned);
420                 }
421
422                 public Label DefineLabel ()
423                 {
424                         return ig.DefineLabel ();
425                 }
426
427                 public void MarkLabel (Label label)
428                 {
429                         ig.MarkLabel (label);
430                 }
431
432                 public void Emit (OpCode opcode)
433                 {
434                         ig.Emit (opcode);
435                 }
436
437                 public void Emit (OpCode opcode, LocalBuilder local)
438                 {
439                         ig.Emit (opcode, local);
440                 }
441
442                 public void Emit (OpCode opcode, string arg)
443                 {
444                         ig.Emit (opcode, arg);
445                 }
446
447                 public void Emit (OpCode opcode, double arg)
448                 {
449                         ig.Emit (opcode, arg);
450                 }
451
452                 public void Emit (OpCode opcode, float arg)
453                 {
454                         ig.Emit (opcode, arg);
455                 }
456
457                 public void Emit (OpCode opcode, int arg)
458                 {
459                         ig.Emit (opcode, arg);
460                 }
461
462                 public void Emit (OpCode opcode, byte arg)
463                 {
464                         ig.Emit (opcode, arg);
465                 }
466
467                 public void Emit (OpCode opcode, Label label)
468                 {
469                         ig.Emit (opcode, label);
470                 }
471
472                 public void Emit (OpCode opcode, Label[] labels)
473                 {
474                         ig.Emit (opcode, labels);
475                 }
476
477                 public void Emit (OpCode opcode, TypeSpec type)
478                 {
479                         if (IsAnonymousStoreyMutateRequired)
480                                 type = CurrentAnonymousMethod.Storey.Mutator.Mutate (type);
481
482                         ig.Emit (opcode, type.GetMetaInfo ());
483                 }
484
485                 public void Emit (OpCode opcode, FieldSpec field)
486                 {
487                         if (IsAnonymousStoreyMutateRequired)
488                                 field = field.Mutate (CurrentAnonymousMethod.Storey.Mutator);
489
490                         ig.Emit (opcode, field.GetMetaInfo ());
491                 }
492
493                 public void Emit (OpCode opcode, MethodSpec method)
494                 {
495                         if (IsAnonymousStoreyMutateRequired)
496                                 method = method.Mutate (CurrentAnonymousMethod.Storey.Mutator);
497
498                         if (method.IsConstructor)
499                                 ig.Emit (opcode, (ConstructorInfo) method.GetMetaInfo ());
500                         else
501                                 ig.Emit (opcode, (MethodInfo) method.GetMetaInfo ());
502                 }
503
504                 // TODO: REMOVE breaks mutator
505                 public void Emit (OpCode opcode, MethodInfo method)
506                 {
507                         ig.Emit (opcode, method);
508                 }
509
510                 // TODO: REMOVE breaks mutator
511                 public void Emit (OpCode opcode, FieldBuilder field)
512                 {
513                         ig.Emit (opcode, field);
514                 }
515
516                 public void Emit (OpCode opcode, MethodSpec method, Type[] vargs)
517                 {
518                         // TODO MemberCache: This should mutate too
519                         ig.EmitCall (opcode, (MethodInfo) method.GetMetaInfo (), vargs);
520                 }
521
522                 public void EmitArrayNew (ArrayContainer ac)
523                 {
524                         if (ac.Rank == 1) {
525                                 Emit (OpCodes.Newarr, ac.Element);
526                         } else {
527                                 if (IsAnonymousStoreyMutateRequired)
528                                         ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator);
529
530                                 ig.Emit (OpCodes.Newobj, ac.GetConstructor ());
531                         }
532                 }
533
534                 public void EmitArrayAddress (ArrayContainer ac)
535                 {
536                         if (ac.Element.IsGenericParameter)
537                                 ig.Emit (OpCodes.Readonly);
538
539                         if (ac.Rank > 1) {
540                                 if (IsAnonymousStoreyMutateRequired)
541                                         ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator);
542
543                                 ig.Emit (OpCodes.Call, ac.GetAddressMethod ());
544                         } else {
545                                 Emit (OpCodes.Ldelema, ac.Element);
546                         }
547                 }
548
549                 //
550                 // Emits the right opcode to load from an array
551                 //
552                 public void EmitArrayLoad (ArrayContainer ac)
553                 {
554                         if (ac.Rank > 1) {
555                                 if (IsAnonymousStoreyMutateRequired)
556                                         ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator);
557
558                                 ig.Emit (OpCodes.Call, ac.GetGetMethod ());
559                                 return;
560                         }
561
562                         var type = ac.Element;
563                         if (TypeManager.IsEnumType (type))
564                                 type = EnumSpec.GetUnderlyingType (type);
565
566                         if (type == TypeManager.byte_type || type == TypeManager.bool_type)
567                                 Emit (OpCodes.Ldelem_U1);
568                         else if (type == TypeManager.sbyte_type)
569                                 Emit (OpCodes.Ldelem_I1);
570                         else if (type == TypeManager.short_type)
571                                 Emit (OpCodes.Ldelem_I2);
572                         else if (type == TypeManager.ushort_type || type == TypeManager.char_type)
573                                 Emit (OpCodes.Ldelem_U2);
574                         else if (type == TypeManager.int32_type)
575                                 Emit (OpCodes.Ldelem_I4);
576                         else if (type == TypeManager.uint32_type)
577                                 Emit (OpCodes.Ldelem_U4);
578                         else if (type == TypeManager.uint64_type)
579                                 Emit (OpCodes.Ldelem_I8);
580                         else if (type == TypeManager.int64_type)
581                                 Emit (OpCodes.Ldelem_I8);
582                         else if (type == TypeManager.float_type)
583                                 Emit (OpCodes.Ldelem_R4);
584                         else if (type == TypeManager.double_type)
585                                 Emit (OpCodes.Ldelem_R8);
586                         else if (type == TypeManager.intptr_type)
587                                 Emit (OpCodes.Ldelem_I);
588                         else if (TypeManager.IsStruct (type)) {
589                                 Emit (OpCodes.Ldelema, type);
590                                 Emit (OpCodes.Ldobj, type);
591                         } else if (type.IsGenericParameter) {
592                                 Emit (OpCodes.Ldelem, type);
593                         } else if (type.IsPointer)
594                                 Emit (OpCodes.Ldelem_I);
595                         else
596                                 Emit (OpCodes.Ldelem_Ref);
597                 }
598
599                 //
600                 // Emits the right opcode to store to an array
601                 //
602                 public void EmitArrayStore (ArrayContainer ac)
603                 {
604                         if (ac.Rank > 1) {
605                                 if (IsAnonymousStoreyMutateRequired)
606                                         ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator);
607
608                                 ig.Emit (OpCodes.Call, ac.GetSetMethod ());
609                                 return;
610                         }
611
612                         var type = ac.Element;
613
614                         if (type.IsEnum)
615                                 type = EnumSpec.GetUnderlyingType (type);
616
617                         if (type == TypeManager.byte_type || type == TypeManager.sbyte_type || type == TypeManager.bool_type)
618                                 Emit (OpCodes.Stelem_I1);
619                         else if (type == TypeManager.short_type || type == TypeManager.ushort_type || type == TypeManager.char_type)
620                                 Emit (OpCodes.Stelem_I2);
621                         else if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
622                                 Emit (OpCodes.Stelem_I4);
623                         else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
624                                 Emit (OpCodes.Stelem_I8);
625                         else if (type == TypeManager.float_type)
626                                 Emit (OpCodes.Stelem_R4);
627                         else if (type == TypeManager.double_type)
628                                 Emit (OpCodes.Stelem_R8);
629                         else if (type == TypeManager.intptr_type)
630                                 Emit (OpCodes.Stobj, type);
631                         else if (TypeManager.IsStruct (type))
632                                 Emit (OpCodes.Stobj, type);
633                         else if (type.IsGenericParameter)
634                                 Emit (OpCodes.Stelem, type);
635                         else if (type.IsPointer)
636                                 Emit (OpCodes.Stelem_I);
637                         else
638                                 Emit (OpCodes.Stelem_Ref);
639                 }
640
641                 public void EmitInt (int i)
642                 {
643                         switch (i) {
644                         case -1:
645                                 ig.Emit (OpCodes.Ldc_I4_M1);
646                                 break;
647
648                         case 0:
649                                 ig.Emit (OpCodes.Ldc_I4_0);
650                                 break;
651
652                         case 1:
653                                 ig.Emit (OpCodes.Ldc_I4_1);
654                                 break;
655
656                         case 2:
657                                 ig.Emit (OpCodes.Ldc_I4_2);
658                                 break;
659
660                         case 3:
661                                 ig.Emit (OpCodes.Ldc_I4_3);
662                                 break;
663
664                         case 4:
665                                 ig.Emit (OpCodes.Ldc_I4_4);
666                                 break;
667
668                         case 5:
669                                 ig.Emit (OpCodes.Ldc_I4_5);
670                                 break;
671
672                         case 6:
673                                 ig.Emit (OpCodes.Ldc_I4_6);
674                                 break;
675
676                         case 7:
677                                 ig.Emit (OpCodes.Ldc_I4_7);
678                                 break;
679
680                         case 8:
681                                 ig.Emit (OpCodes.Ldc_I4_8);
682                                 break;
683
684                         default:
685                                 if (i >= -128 && i <= 127) {
686                                         ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
687                                 } else
688                                         ig.Emit (OpCodes.Ldc_I4, i);
689                                 break;
690                         }
691                 }
692
693                 public void EmitLong (long l)
694                 {
695                         if (l >= int.MinValue && l <= int.MaxValue) {
696                                 EmitInt (unchecked ((int) l));
697                                 ig.Emit (OpCodes.Conv_I8);
698                                 return;
699                         }
700
701                         if (l >= 0 && l <= uint.MaxValue) {
702                                 EmitInt (unchecked ((int) l));
703                                 ig.Emit (OpCodes.Conv_U8);
704                                 return;
705                         }
706
707                         ig.Emit (OpCodes.Ldc_I8, l);
708                 }
709
710                 //
711                 // Load the object from the pointer.  
712                 //
713                 public void EmitLoadFromPtr (TypeSpec t)
714                 {
715                         if (t == TypeManager.int32_type)
716                                 ig.Emit (OpCodes.Ldind_I4);
717                         else if (t == TypeManager.uint32_type)
718                                 ig.Emit (OpCodes.Ldind_U4);
719                         else if (t == TypeManager.short_type)
720                                 ig.Emit (OpCodes.Ldind_I2);
721                         else if (t == TypeManager.ushort_type)
722                                 ig.Emit (OpCodes.Ldind_U2);
723                         else if (t == TypeManager.char_type)
724                                 ig.Emit (OpCodes.Ldind_U2);
725                         else if (t == TypeManager.byte_type)
726                                 ig.Emit (OpCodes.Ldind_U1);
727                         else if (t == TypeManager.sbyte_type)
728                                 ig.Emit (OpCodes.Ldind_I1);
729                         else if (t == TypeManager.uint64_type)
730                                 ig.Emit (OpCodes.Ldind_I8);
731                         else if (t == TypeManager.int64_type)
732                                 ig.Emit (OpCodes.Ldind_I8);
733                         else if (t == TypeManager.float_type)
734                                 ig.Emit (OpCodes.Ldind_R4);
735                         else if (t == TypeManager.double_type)
736                                 ig.Emit (OpCodes.Ldind_R8);
737                         else if (t == TypeManager.bool_type)
738                                 ig.Emit (OpCodes.Ldind_I1);
739                         else if (t == TypeManager.intptr_type)
740                                 ig.Emit (OpCodes.Ldind_I);
741                         else if (t.IsEnum) {
742                                 if (t == TypeManager.enum_type)
743                                         ig.Emit (OpCodes.Ldind_Ref);
744                                 else
745                                         EmitLoadFromPtr (EnumSpec.GetUnderlyingType (t));
746                         } else if (TypeManager.IsStruct (t) || TypeManager.IsGenericParameter (t))
747                                 Emit (OpCodes.Ldobj, t);
748                         else if (t.IsPointer)
749                                 ig.Emit (OpCodes.Ldind_I);
750                         else
751                                 ig.Emit (OpCodes.Ldind_Ref);
752                 }
753
754                 //
755                 // The stack contains the pointer and the value of type `type'
756                 //
757                 public void EmitStoreFromPtr (TypeSpec type)
758                 {
759                         if (type.IsEnum)
760                                 type = EnumSpec.GetUnderlyingType (type);
761
762                         if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
763                                 ig.Emit (OpCodes.Stind_I4);
764                         else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
765                                 ig.Emit (OpCodes.Stind_I8);
766                         else if (type == TypeManager.char_type || type == TypeManager.short_type ||
767                                  type == TypeManager.ushort_type)
768                                 ig.Emit (OpCodes.Stind_I2);
769                         else if (type == TypeManager.float_type)
770                                 ig.Emit (OpCodes.Stind_R4);
771                         else if (type == TypeManager.double_type)
772                                 ig.Emit (OpCodes.Stind_R8);
773                         else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
774                                  type == TypeManager.bool_type)
775                                 ig.Emit (OpCodes.Stind_I1);
776                         else if (type == TypeManager.intptr_type)
777                                 ig.Emit (OpCodes.Stind_I);
778                         else if (TypeManager.IsStruct (type) || TypeManager.IsGenericParameter (type))
779                                 ig.Emit (OpCodes.Stobj, type.GetMetaInfo ());
780                         else
781                                 ig.Emit (OpCodes.Stind_Ref);
782                 }
783
784                 /// <summary>
785                 ///   Returns a temporary storage for a variable of type t as 
786                 ///   a local variable in the current body.
787                 /// </summary>
788                 public LocalBuilder GetTemporaryLocal (TypeSpec t)
789                 {
790                         if (temporary_storage != null) {
791                                 object o;
792                                 if (temporary_storage.TryGetValue (t, out o)) {
793                                         if (o is Stack<LocalBuilder>) {
794                                                 var s = (Stack<LocalBuilder>) o;
795                                                 o = s.Count == 0 ? null : s.Pop ();
796                                         } else {
797                                                 temporary_storage.Remove (t);
798                                         }
799                                 }
800                                 if (o != null)
801                                         return (LocalBuilder) o;
802                         }
803                         return DeclareLocal (t, false);
804                 }
805
806                 public void FreeTemporaryLocal (LocalBuilder b, TypeSpec t)
807                 {
808                         if (temporary_storage == null) {
809                                 temporary_storage = new Dictionary<TypeSpec, object> (ReferenceEquality<TypeSpec>.Default);
810                                 temporary_storage.Add (t, b);
811                                 return;
812                         }
813                         object o;
814                         
815                         if (!temporary_storage.TryGetValue (t, out o)) {
816                                 temporary_storage.Add (t, b);
817                                 return;
818                         }
819                         var s = o as Stack<LocalBuilder>;
820                         if (s == null) {
821                                 s = new Stack<LocalBuilder> ();
822                                 s.Push ((LocalBuilder)o);
823                                 temporary_storage [t] = s;
824                         }
825                         s.Push (b);
826                 }
827
828                 /// <summary>
829                 ///   ReturnValue creates on demand the LocalBuilder for the
830                 ///   return value from the function.  By default this is not
831                 ///   used.  This is only required when returns are found inside
832                 ///   Try or Catch statements.
833                 ///
834                 ///   This method is typically invoked from the Emit phase, so
835                 ///   we allow the creation of a return label if it was not
836                 ///   requested during the resolution phase.   Could be cleaned
837                 ///   up, but it would replicate a lot of logic in the Emit phase
838                 ///   of the code that uses it.
839                 /// </summary>
840                 public LocalBuilder TemporaryReturn ()
841                 {
842                         if (return_value == null){
843                                 return_value = DeclareLocal (return_type, false);
844                                 if (!HasReturnLabel){
845                                         ReturnLabel = DefineLabel ();
846                                         HasReturnLabel = true;
847                                 }
848                         }
849
850                         return return_value;
851                 }
852         }
853
854         public abstract class CommonAssemblyModulClass : Attributable, IMemberContext
855         {
856                 public void AddAttributes (List<Attribute> attrs, IMemberContext context)
857                 {
858                         foreach (Attribute a in attrs)
859                                 a.AttachTo (this, context);
860
861                         if (attributes == null) {
862                                 attributes = new Attributes (attrs);
863                                 return;
864                         }
865                         attributes.AddAttributes (attrs);
866                 }
867
868                 public virtual void Emit (TypeContainer tc) 
869                 {
870                         if (OptAttributes == null)
871                                 return;
872
873                         OptAttributes.Emit ();
874                 }
875
876                 protected Attribute ResolveAttribute (PredefinedAttribute a_type)
877                 {
878                         Attribute a = OptAttributes.Search (a_type);
879                         if (a != null) {
880                                 a.Resolve ();
881                         }
882                         return a;
883                 }
884
885                 #region IMemberContext Members
886
887                 public CompilerContext Compiler {
888                         get { return RootContext.ToplevelTypes.Compiler; }
889                 }
890
891                 public TypeSpec CurrentType {
892                         get { return null; }
893                 }
894
895                 public TypeParameter[] CurrentTypeParameters {
896                         get { return null; }
897                 }
898
899                 public MemberCore CurrentMemberDefinition {
900                         get { return RootContext.ToplevelTypes; }
901                 }
902
903                 public string GetSignatureForError ()
904                 {
905                         return "<module>";
906                 }
907
908                 public bool HasUnresolvedConstraints {
909                         get { return false; }
910                 }
911
912                 public bool IsObsolete {
913                         get { return false; }
914                 }
915
916                 public bool IsUnsafe {
917                         get { return false; }
918                 }
919
920                 public bool IsStatic {
921                         get { return false; }
922                 }
923
924                 public IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceEntry scope)
925                 {
926                         throw new NotImplementedException ();
927                 }
928
929                 public FullNamedExpression LookupNamespaceOrType (string name, int arity, Location loc, bool ignore_cs0104)
930                 {
931                         return RootContext.ToplevelTypes.LookupNamespaceOrType (name, arity, loc, ignore_cs0104);
932                 }
933
934                 public FullNamedExpression LookupNamespaceAlias (string name)
935                 {
936                         return null;
937                 }
938
939                 #endregion
940         }
941                 
942         public class AssemblyClass : CommonAssemblyModulClass {
943                 // TODO: make it private and move all builder based methods here
944                 public AssemblyBuilder Builder;
945                 bool is_cls_compliant;
946                 bool wrap_non_exception_throws;
947
948                 public Attribute ClsCompliantAttribute;
949
950                 Dictionary<SecurityAction, PermissionSet> declarative_security;
951                 bool has_extension_method;              
952                 public AssemblyName Name;
953                 MethodInfo add_type_forwarder;
954                 Dictionary<ITypeDefinition, Attribute> emitted_forwarders;
955
956                 // Module is here just because of error messages
957                 static string[] attribute_targets = new string [] { "assembly", "module" };
958
959                 public AssemblyClass ()
960                 {
961                         wrap_non_exception_throws = true;
962                 }
963
964                 public bool HasExtensionMethods {
965                         set {
966                                 has_extension_method = value;
967                         }
968                 }
969
970                 public bool IsClsCompliant {
971                         get {
972                                 return is_cls_compliant;
973                         }
974                 }
975
976                 public bool WrapNonExceptionThrows {
977                         get {
978                                 return wrap_non_exception_throws;
979                         }
980                 }
981
982                 public override AttributeTargets AttributeTargets {
983                         get {
984                                 return AttributeTargets.Assembly;
985                         }
986                 }
987
988                 public override bool IsClsComplianceRequired ()
989                 {
990                         return is_cls_compliant;
991                 }
992
993                 Report Report {
994                         get { return Compiler.Report; }
995                 }
996
997                 public void Resolve ()
998                 {
999                         if (RootContext.Unsafe) {
1000                                 //
1001                                 // Emits [assembly: SecurityPermissionAttribute (SecurityAction.RequestMinimum, SkipVerification = true)]
1002                                 // when -unsafe option was specified
1003                                 //
1004                                 
1005                                 Location loc = Location.Null;
1006
1007                                 MemberAccess system_security_permissions = new MemberAccess (new MemberAccess (
1008                                         new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Security", loc), "Permissions", loc);
1009
1010                                 Arguments pos = new Arguments (1);
1011                                 pos.Add (new Argument (new MemberAccess (new MemberAccess (system_security_permissions, "SecurityAction", loc), "RequestMinimum")));
1012
1013                                 Arguments named = new Arguments (1);
1014                                 named.Add (new NamedArgument ("SkipVerification", loc, new BoolLiteral (true, loc)));
1015
1016                                 GlobalAttribute g = new GlobalAttribute (new NamespaceEntry (Compiler, null, null, null), "assembly",
1017                                         new MemberAccess (system_security_permissions, "SecurityPermissionAttribute"),
1018                                         new Arguments[] { pos, named }, loc, false);
1019                                 g.AttachTo (this, this);
1020
1021                                 if (g.Resolve () != null) {
1022                                         declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
1023                                         g.ExtractSecurityPermissionSet (declarative_security);
1024                                 }
1025                         }
1026
1027                         if (OptAttributes == null)
1028                                 return;
1029
1030                         // Ensure that we only have GlobalAttributes, since the Search isn't safe with other types.
1031                         if (!OptAttributes.CheckTargets())
1032                                 return;
1033
1034                         ClsCompliantAttribute = ResolveAttribute (Compiler.PredefinedAttributes.CLSCompliant);
1035
1036                         if (ClsCompliantAttribute != null) {
1037                                 is_cls_compliant = ClsCompliantAttribute.GetClsCompliantAttributeValue ();
1038                         }
1039
1040                         Attribute a = ResolveAttribute (Compiler.PredefinedAttributes.RuntimeCompatibility);
1041                         if (a != null) {
1042                                 var val = a.GetPropertyValue ("WrapNonExceptionThrows") as BoolConstant;
1043                                 if (val != null)
1044                                         wrap_non_exception_throws = val.Value;
1045                         }
1046                 }
1047
1048                 // fix bug #56621
1049                 private void SetPublicKey (AssemblyName an, byte[] strongNameBlob) 
1050                 {
1051                         try {
1052                                 // check for possible ECMA key
1053                                 if (strongNameBlob.Length == 16) {
1054                                         // will be rejected if not "the" ECMA key
1055                                         an.SetPublicKey (strongNameBlob);
1056                                 }
1057                                 else {
1058                                         // take it, with or without, a private key
1059                                         RSA rsa = CryptoConvert.FromCapiKeyBlob (strongNameBlob);
1060                                         // and make sure we only feed the public part to Sys.Ref
1061                                         byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa);
1062                                         
1063                                         // AssemblyName.SetPublicKey requires an additional header
1064                                         byte[] publicKeyHeader = new byte [12] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00 };
1065
1066                                         byte[] encodedPublicKey = new byte [12 + publickey.Length];
1067                                         Buffer.BlockCopy (publicKeyHeader, 0, encodedPublicKey, 0, 12);
1068                                         Buffer.BlockCopy (publickey, 0, encodedPublicKey, 12, publickey.Length);
1069                                         an.SetPublicKey (encodedPublicKey);
1070                                 }
1071                         }
1072                         catch (Exception) {
1073                                 Error_AssemblySigning ("The specified file `" + RootContext.StrongNameKeyFile + "' is incorrectly encoded");
1074                                 Environment.Exit (1);
1075                         }
1076                 }
1077
1078                 void Error_ObsoleteSecurityAttribute (Attribute a, string option)
1079                 {
1080                         Report.Warning (1699, 1, a.Location,
1081                                 "Use compiler option `{0}' or appropriate project settings instead of `{1}' attribute",
1082                                 option, a.Name);
1083                 }
1084
1085                 // TODO: rewrite this code (to kill N bugs and make it faster) and use standard ApplyAttribute way.
1086                 public AssemblyName GetAssemblyName (string name, string output) 
1087                 {
1088                         if (OptAttributes != null) {
1089                                 foreach (Attribute a in OptAttributes.Attrs) {
1090                                         // cannot rely on any resolve-based members before you call Resolve
1091                                         if (a.ExplicitTarget == null || a.ExplicitTarget != "assembly")
1092                                                 continue;
1093
1094                                         // TODO: This code is buggy: comparing Attribute name without resolving is wrong.
1095                                         //       However, this is invoked by CodeGen.Init, when none of the namespaces
1096                                         //       are loaded yet.
1097                                         // TODO: Does not handle quoted attributes properly
1098                                         switch (a.Name) {
1099                                         case "AssemblyKeyFile":
1100                                         case "AssemblyKeyFileAttribute":
1101                                         case "System.Reflection.AssemblyKeyFileAttribute":
1102                                                 if (RootContext.StrongNameKeyFile != null) {
1103                                                         Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ());
1104                                                         Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
1105                                                                         "keyfile", "System.Reflection.AssemblyKeyFileAttribute");
1106                                                 } else {
1107                                                         string value = a.GetString ();
1108                                                         if (!string.IsNullOrEmpty (value)) {
1109                                                                 Error_ObsoleteSecurityAttribute (a, "keyfile");
1110                                                                 RootContext.StrongNameKeyFile = value;
1111                                                         }
1112                                                 }
1113                                                 break;
1114                                         case "AssemblyKeyName":
1115                                         case "AssemblyKeyNameAttribute":
1116                                         case "System.Reflection.AssemblyKeyNameAttribute":
1117                                                 if (RootContext.StrongNameKeyContainer != null) {
1118                                                         Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ());
1119                                                         Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
1120                                                                         "keycontainer", "System.Reflection.AssemblyKeyNameAttribute");
1121                                                 } else {
1122                                                         string value = a.GetString ();
1123                                                         if (!string.IsNullOrEmpty (value)) {
1124                                                                 Error_ObsoleteSecurityAttribute (a, "keycontainer");
1125                                                                 RootContext.StrongNameKeyContainer = value;
1126                                                         }
1127                                                 }
1128                                                 break;
1129                                         case "AssemblyDelaySign":
1130                                         case "AssemblyDelaySignAttribute":
1131                                         case "System.Reflection.AssemblyDelaySignAttribute":
1132                                                 bool b = a.GetBoolean ();
1133                                                 if (b) {
1134                                                         Error_ObsoleteSecurityAttribute (a, "delaysign");
1135                                                 }
1136
1137                                                 RootContext.StrongNameDelaySign = b;
1138                                                 break;
1139                                         }
1140                                 }
1141                         }
1142                         
1143                         AssemblyName an = new AssemblyName ();
1144                         an.Name = Path.GetFileNameWithoutExtension (name);
1145
1146                         // note: delay doesn't apply when using a key container
1147                         if (RootContext.StrongNameKeyContainer != null) {
1148                                 an.KeyPair = new StrongNameKeyPair (RootContext.StrongNameKeyContainer);
1149                                 return an;
1150                         }
1151
1152                         // strongname is optional
1153                         if (RootContext.StrongNameKeyFile == null)
1154                                 return an;
1155
1156                         string AssemblyDir = Path.GetDirectoryName (output);
1157
1158                         // the StrongName key file may be relative to (a) the compiled
1159                         // file or (b) to the output assembly. See bugzilla #55320
1160                         // http://bugzilla.ximian.com/show_bug.cgi?id=55320
1161
1162                         // (a) relative to the compiled file
1163                         string filename = Path.GetFullPath (RootContext.StrongNameKeyFile);
1164                         bool exist = File.Exists (filename);
1165                         if ((!exist) && (AssemblyDir != null) && (AssemblyDir != String.Empty)) {
1166                                 // (b) relative to the outputed assembly
1167                                 filename = Path.GetFullPath (Path.Combine (AssemblyDir, RootContext.StrongNameKeyFile));
1168                                 exist = File.Exists (filename);
1169                         }
1170
1171                         if (exist) {
1172                                 using (FileStream fs = new FileStream (filename, FileMode.Open, FileAccess.Read)) {
1173                                         byte[] snkeypair = new byte [fs.Length];
1174                                         fs.Read (snkeypair, 0, snkeypair.Length);
1175
1176                                         if (RootContext.StrongNameDelaySign) {
1177                                                 // delayed signing - DO NOT include private key
1178                                                 SetPublicKey (an, snkeypair);
1179                                         }
1180                                         else {
1181                                                 // no delay so we make sure we have the private key
1182                                                 try {
1183                                                         CryptoConvert.FromCapiPrivateKeyBlob (snkeypair);
1184                                                         an.KeyPair = new StrongNameKeyPair (snkeypair);
1185                                                 }
1186                                                 catch (CryptographicException) {
1187                                                         if (snkeypair.Length == 16) {
1188                                                                 // error # is different for ECMA key
1189                                                                 Report.Error (1606, "Could not sign the assembly. " + 
1190                                                                         "ECMA key can only be used to delay-sign assemblies");
1191                                                         }
1192                                                         else {
1193                                                                 Error_AssemblySigning ("The specified file `" + RootContext.StrongNameKeyFile + "' does not have a private key");
1194                                                         }
1195                                                         return null;
1196                                                 }
1197                                         }
1198                                 }
1199                         }
1200                         else {
1201                                 Error_AssemblySigning ("The specified file `" + RootContext.StrongNameKeyFile + "' does not exist");
1202                                 return null;
1203                         }
1204                         return an;
1205                 }
1206
1207                 void Error_AssemblySigning (string text)
1208                 {
1209                         Report.Error (1548, "Error during assembly signing. " + text);
1210                 }
1211
1212                 bool CheckInternalsVisibleAttribute (Attribute a)
1213                 {
1214                         string assembly_name = a.GetString ();
1215                         if (assembly_name.Length == 0)
1216                                 return false;
1217                                 
1218                         AssemblyName aname = null;
1219                         try {
1220                                 aname = new AssemblyName (assembly_name);
1221                         } catch (FileLoadException) {
1222                         } catch (ArgumentException) {
1223                         }
1224                                 
1225                         // Bad assembly name format
1226                         if (aname == null)
1227                                 Report.Warning (1700, 3, a.Location, "Assembly reference `" + assembly_name + "' is invalid and cannot be resolved");
1228                         // Report error if we have defined Version or Culture
1229                         else if (aname.Version != null || aname.CultureInfo != null)
1230                                 throw new Exception ("Friend assembly `" + a.GetString () + 
1231                                                 "' is invalid. InternalsVisibleTo cannot have version or culture specified.");
1232                         else if (aname.GetPublicKey () == null && Name.GetPublicKey () != null && Name.GetPublicKey ().Length != 0) {
1233                                 Report.Error (1726, a.Location, "Friend assembly reference `" + aname.FullName + "' is invalid." +
1234                                                 " Strong named assemblies must specify a public key in their InternalsVisibleTo declarations");
1235                                 return false;
1236                         }
1237
1238                         return true;
1239                 }
1240
1241                 static string IsValidAssemblyVersion (string version)
1242                 {
1243                         Version v;
1244                         try {
1245                                 v = new Version (version);
1246                         } catch {
1247                                 try {
1248                                         int major = int.Parse (version, CultureInfo.InvariantCulture);
1249                                         v = new Version (major, 0);
1250                                 } catch {
1251                                         return null;
1252                                 }
1253                         }
1254
1255                         foreach (int candidate in new int [] { v.Major, v.Minor, v.Build, v.Revision }) {
1256                                 if (candidate > ushort.MaxValue)
1257                                         return null;
1258                         }
1259
1260                         return new Version (v.Major, System.Math.Max (0, v.Minor), System.Math.Max (0, v.Build), System.Math.Max (0, v.Revision)).ToString (4);
1261                 }
1262
1263                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1264                 {
1265                         if (a.IsValidSecurityAttribute ()) {
1266                                 if (declarative_security == null)
1267                                         declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
1268
1269                                 a.ExtractSecurityPermissionSet (declarative_security);
1270                                 return;
1271                         }
1272
1273                         if (a.Type == pa.AssemblyCulture) {
1274                                 string value = a.GetString ();
1275                                 if (value == null || value.Length == 0)
1276                                         return;
1277
1278                                 if (RootContext.Target == Target.Exe) {
1279                                         a.Error_AttributeEmitError ("The executables cannot be satelite assemblies, remove the attribute or keep it empty");
1280                                         return;
1281                                 }
1282
1283                                 try {
1284                                         var fi = typeof (AssemblyBuilder).GetField ("culture", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
1285                                         fi.SetValue (Builder, value == "neutral" ? "" : value);
1286                                 } catch {
1287                                         Report.RuntimeMissingSupport (a.Location, "AssemblyCultureAttribute setting");
1288                                 }
1289
1290                                 return;
1291                         }
1292
1293                         if (a.Type == pa.AssemblyVersion) {
1294                                 string value = a.GetString ();
1295                                 if (value == null || value.Length == 0)
1296                                         return;
1297
1298                                 var vinfo = IsValidAssemblyVersion (value.Replace ('*', '0'));
1299                                 if (vinfo == null) {
1300                                         a.Error_AttributeEmitError (string.Format ("Specified version `{0}' is not valid", value));
1301                                         return;
1302                                 }
1303
1304                                 try {
1305                                         var fi = typeof (AssemblyBuilder).GetField ("version", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
1306                                         fi.SetValue (Builder, vinfo);
1307                                 } catch {
1308                                         Report.RuntimeMissingSupport (a.Location, "AssemblyVersionAttribute setting");
1309                                 }
1310
1311                                 return;
1312                         }
1313
1314                         if (a.Type == pa.AssemblyAlgorithmId) {
1315                                 const int pos = 2; // skip CA header
1316                                 uint alg = (uint) cdata [pos];
1317                                 alg |= ((uint) cdata [pos + 1]) << 8;
1318                                 alg |= ((uint) cdata [pos + 2]) << 16;
1319                                 alg |= ((uint) cdata [pos + 3]) << 24;
1320
1321                                 try {
1322                                         var fi = typeof (AssemblyBuilder).GetField ("algid", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
1323                                         fi.SetValue (Builder, alg);
1324                                 } catch {
1325                                         Report.RuntimeMissingSupport (a.Location, "AssemblyAlgorithmIdAttribute setting");
1326                                 }
1327
1328                                 return;
1329                         }
1330
1331                         if (a.Type == pa.AssemblyFlags) {
1332                                 const int pos = 2; // skip CA header
1333                                 uint flags = (uint) cdata[pos];
1334                                 flags |= ((uint) cdata[pos + 1]) << 8;
1335                                 flags |= ((uint) cdata[pos + 2]) << 16;
1336                                 flags |= ((uint) cdata[pos + 3]) << 24;
1337
1338                                 // Ignore set PublicKey flag if assembly is not strongnamed
1339                                 if ((flags & (uint) AssemblyNameFlags.PublicKey) != 0 && (Builder.GetName ().KeyPair == null))
1340                                         flags &= ~(uint)AssemblyNameFlags.PublicKey;
1341
1342                                 try {
1343                                         var fi = typeof (AssemblyBuilder).GetField ("flags", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
1344                                         fi.SetValue (Builder, flags);
1345                                 } catch {
1346                                         Report.RuntimeMissingSupport (a.Location, "AssemblyFlagsAttribute setting");
1347                                 }
1348
1349                                 return;
1350                         }
1351
1352                         if (a.Type == pa.InternalsVisibleTo && !CheckInternalsVisibleAttribute (a))
1353                                 return;
1354
1355                         if (a.Type == pa.TypeForwarder) {
1356                                 TypeSpec t = a.GetArgumentType ();
1357                                 if (t == null || TypeManager.HasElementType (t)) {
1358                                         Report.Error (735, a.Location, "Invalid type specified as an argument for TypeForwardedTo attribute");
1359                                         return;
1360                                 }
1361
1362                                 if (emitted_forwarders == null) {
1363                                         emitted_forwarders = new Dictionary<ITypeDefinition, Attribute>  ();
1364                                 } else if (emitted_forwarders.ContainsKey (t.MemberDefinition)) {
1365                                         Report.SymbolRelatedToPreviousError(emitted_forwarders[t.MemberDefinition].Location, null);
1366                                         Report.Error(739, a.Location, "A duplicate type forward of type `{0}'",
1367                                                 TypeManager.CSharpName(t));
1368                                         return;
1369                                 }
1370
1371                                 emitted_forwarders.Add(t.MemberDefinition, a);
1372
1373                                 if (t.Assembly == Builder) {
1374                                         Report.SymbolRelatedToPreviousError (t);
1375                                         Report.Error (729, a.Location, "Cannot forward type `{0}' because it is defined in this assembly",
1376                                                 TypeManager.CSharpName (t));
1377                                         return;
1378                                 }
1379
1380                                 if (t.IsNested) {
1381                                         Report.Error (730, a.Location, "Cannot forward type `{0}' because it is a nested type",
1382                                                 TypeManager.CSharpName (t));
1383                                         return;
1384                                 }
1385
1386                                 if (add_type_forwarder == null) {
1387                                         add_type_forwarder = typeof (AssemblyBuilder).GetMethod ("AddTypeForwarder",
1388                                                 BindingFlags.NonPublic | BindingFlags.Instance);
1389
1390                                         if (add_type_forwarder == null) {
1391                                                 Report.RuntimeMissingSupport (a.Location, "TypeForwardedTo attribute");
1392                                                 return;
1393                                         }
1394                                 }
1395
1396                                 add_type_forwarder.Invoke (Builder, new object[] { t.GetMetaInfo () });
1397                                 return;
1398                         }
1399                         
1400                         if (a.Type == pa.Extension) {
1401                                 a.Error_MisusedExtensionAttribute ();
1402                                 return;
1403                         }
1404
1405                         Builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1406                 }
1407
1408                 public override void Emit (TypeContainer tc)
1409                 {
1410                         base.Emit (tc);
1411
1412                         if (has_extension_method)
1413                                 Compiler.PredefinedAttributes.Extension.EmitAttribute (Builder);
1414
1415                         PredefinedAttribute pa = tc.Compiler.PredefinedAttributes.RuntimeCompatibility;
1416                         if (pa.IsDefined && (OptAttributes == null || !OptAttributes.Contains (pa))) {
1417                                 var ci = TypeManager.GetPredefinedConstructor (pa.Type, Location.Null, TypeSpec.EmptyTypes);
1418                                 PropertyInfo [] pis = new PropertyInfo [1];
1419
1420                                 pis [0] = TypeManager.GetPredefinedProperty (pa.Type,
1421                                         "WrapNonExceptionThrows", Location.Null, TypeManager.bool_type).MetaInfo;
1422                                 object [] pargs = new object [1];
1423                                 pargs [0] = true;
1424                                 Builder.SetCustomAttribute (new CustomAttributeBuilder ((ConstructorInfo) ci.GetMetaInfo (), new object[0], pis, pargs));
1425                         }
1426
1427                         if (declarative_security != null) {
1428
1429                                 MethodInfo add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
1430                                 object builder_instance = Builder;
1431
1432                                 try {
1433                                         // Microsoft runtime hacking
1434                                         if (add_permission == null) {
1435                                                 var assembly_builder = typeof (AssemblyBuilder).Assembly.GetType ("System.Reflection.Emit.AssemblyBuilderData");
1436                                                 add_permission = assembly_builder.GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
1437
1438                                                 FieldInfo fi = typeof (AssemblyBuilder).GetField ("m_assemblyData", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
1439                                                 builder_instance = fi.GetValue (Builder);
1440                                         }
1441
1442                                         var args = new PermissionSet [3];
1443                                         declarative_security.TryGetValue (SecurityAction.RequestMinimum, out args [0]);
1444                                         declarative_security.TryGetValue (SecurityAction.RequestOptional, out args [1]);
1445                                         declarative_security.TryGetValue (SecurityAction.RequestRefuse, out args [2]);
1446                                         add_permission.Invoke (builder_instance, args);
1447                                 }
1448                                 catch {
1449                                         Report.RuntimeMissingSupport (Location.Null, "assembly permission setting");
1450                                 }
1451                         }
1452                 }
1453
1454                 public override string[] ValidAttributeTargets {
1455                         get {
1456                                 return attribute_targets;
1457                         }
1458                 }
1459
1460                 // Wrapper for AssemblyBuilder.AddModule
1461                 static MethodInfo adder_method;
1462                 static public MethodInfo AddModule_Method {
1463                         get {
1464                                 if (adder_method == null)
1465                                         adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.NonPublic);
1466                                 return adder_method;
1467                         }
1468                 }
1469                 public Module AddModule (string module)
1470                 {
1471                         MethodInfo m = AddModule_Method;
1472                         if (m == null) {
1473                                 Report.RuntimeMissingSupport (Location.Null, "/addmodule");
1474                                 Environment.Exit (1);
1475                         }
1476
1477                         try {
1478                                 return (Module) m.Invoke (Builder, new object [] { module });
1479                         } catch (TargetInvocationException ex) {
1480                                 throw ex.InnerException;
1481                         }
1482                 }               
1483         }
1484 }