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