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