using System;
using System.Collections.Generic;
+
+#if STATIC
+using MetaType = IKVM.Reflection.Type;
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
+#else
+using MetaType = System.Type;
using System.Reflection;
using System.Reflection.Emit;
-using System.Runtime.InteropServices;
-using System.Security.Cryptography;
-
-namespace Mono.CSharp {
-
- /// <summary>
- /// Code generator class.
- /// </summary>
- public class CodeGen {
- static AppDomain current_domain;
-
- // Breaks dynamic and repl
- public static AssemblyClass Assembly;
-
- static CodeGen ()
- {
- Reset ();
- }
-
- public static void Reset ()
- {
- Assembly = new AssemblyClass ();
- }
-
- public static string Basename (string name)
- {
- int pos = name.LastIndexOf ('/');
-
- if (pos != -1)
- return name.Substring (pos + 1);
-
- pos = name.LastIndexOf ('\\');
- if (pos != -1)
- return name.Substring (pos + 1);
-
- return name;
- }
-
- public static string Dirname (string name)
- {
- int pos = name.LastIndexOf ('/');
-
- if (pos != -1)
- return name.Substring (0, pos);
-
- pos = name.LastIndexOf ('\\');
- if (pos != -1)
- return name.Substring (0, pos);
-
- return ".";
- }
-
- static public string FileName;
-
- //
- // Initializes the code generator variables for interactive use (repl)
- //
- static public void InitDynamic (CompilerContext ctx, string name)
- {
- current_domain = AppDomain.CurrentDomain;
- AssemblyName an = Assembly.GetAssemblyName (name, name);
-
- Assembly.Builder = current_domain.DefineDynamicAssembly (an, AssemblyBuilderAccess.Run);
- RootContext.ToplevelTypes = new ModuleCompiled (ctx, true);
- RootContext.ToplevelTypes.Builder = Assembly.Builder.DefineDynamicModule (Basename (name), false);
- Assembly.Name = Assembly.Builder.GetName ();
- }
-
- //
- // Initializes the code generator variables
- //
- static public bool Init (string name, string output, bool want_debugging_support, CompilerContext ctx)
- {
- FileName = output;
- AssemblyName an = Assembly.GetAssemblyName (name, output);
- if (an == null)
- return false;
-
- if (an.KeyPair != null) {
- // If we are going to strong name our assembly make
- // sure all its refs are strong named
- foreach (Assembly a in ctx.GlobalRootNamespace.Assemblies) {
- AssemblyName ref_name = a.GetName ();
- byte [] b = ref_name.GetPublicKeyToken ();
- if (b == null || b.Length == 0) {
- ctx.Report.Error (1577, "Assembly generation failed " +
- "-- Referenced assembly '" +
- ref_name.Name +
- "' does not have a strong name.");
- //Environment.Exit (1);
- }
- }
- }
-
- current_domain = AppDomain.CurrentDomain;
-
- try {
- Assembly.Builder = current_domain.DefineDynamicAssembly (an,
- AssemblyBuilderAccess.RunAndSave, Dirname (name));
- }
- catch (ArgumentException) {
- // specified key may not be exportable outside it's container
- if (RootContext.StrongNameKeyContainer != null) {
- ctx.Report.Error (1548, "Could not access the key inside the container `" +
- RootContext.StrongNameKeyContainer + "'.");
- Environment.Exit (1);
- }
- throw;
- }
- catch (CryptographicException) {
- if ((RootContext.StrongNameKeyContainer != null) || (RootContext.StrongNameKeyFile != null)) {
- ctx.Report.Error (1548, "Could not use the specified key to strongname the assembly.");
- Environment.Exit (1);
- }
- return false;
- }
-
- // Get the complete AssemblyName from the builder
- // (We need to get the public key and token)
- Assembly.Name = Assembly.Builder.GetName ();
-
- //
- // Pass a path-less name to DefineDynamicModule. Wonder how
- // this copes with output in different directories then.
- // FIXME: figure out how this copes with --output /tmp/blah
- //
- // If the third argument is true, the ModuleBuilder will dynamically
- // load the default symbol writer.
- //
- try {
- RootContext.ToplevelTypes.Builder = Assembly.Builder.DefineDynamicModule (
- Basename (name), Basename (output), want_debugging_support);
-
-#if !MS_COMPATIBLE
- // TODO: We should use SymbolWriter from DefineDynamicModule
- if (want_debugging_support && !SymbolWriter.Initialize (RootContext.ToplevelTypes.Builder, output)) {
- ctx.Report.Error (40, "Unexpected debug information initialization error `{0}'",
- "Could not find the symbol writer assembly (Mono.CompilerServices.SymbolWriter.dll)");
- return false;
- }
#endif
- } catch (ExecutionEngineException e) {
- ctx.Report.Error (40, "Unexpected debug information initialization error `{0}'",
- e.Message);
- return false;
- }
-
- return true;
- }
-
- public static void Save (string name, Report Report)
- {
- PortableExecutableKinds pekind;
- ImageFileMachine machine;
-
- switch (RootContext.Platform) {
- case Platform.X86:
- pekind = PortableExecutableKinds.Required32Bit | PortableExecutableKinds.ILOnly;
- machine = ImageFileMachine.I386;
- break;
- case Platform.X64:
- pekind = PortableExecutableKinds.ILOnly;
- machine = ImageFileMachine.AMD64;
- break;
- case Platform.IA64:
- pekind = PortableExecutableKinds.ILOnly;
- machine = ImageFileMachine.IA64;
- break;
- case Platform.AnyCPU:
- default:
- pekind = PortableExecutableKinds.ILOnly;
- machine = ImageFileMachine.I386;
- break;
- }
- try {
- Assembly.Builder.Save (Basename (name), pekind, machine);
- }
- catch (COMException) {
- if ((RootContext.StrongNameKeyFile == null) || (!RootContext.StrongNameDelaySign))
- throw;
-
- // FIXME: it seems Microsoft AssemblyBuilder doesn't like to delay sign assemblies
- Report.Error (1548, "Couldn't delay-sign the assembly with the '" +
- RootContext.StrongNameKeyFile +
- "', Use MCS with the Mono runtime or CSC to compile this assembly.");
- }
- catch (System.IO.IOException io) {
- Report.Error (16, "Could not write to file `"+name+"', cause: " + io.Message);
- return;
- }
- catch (System.UnauthorizedAccessException ua) {
- Report.Error (16, "Could not write to file `"+name+"', cause: " + ua.Message);
- return;
- }
- catch (System.NotImplementedException nie) {
- Report.RuntimeMissingSupport (Location.Null, nie.Message);
- return;
- }
- }
- }
+namespace Mono.CSharp
+{
/// <summary>
/// An Emit Context is created for each body of code (from methods,
/// properties bodies, indexer bodies or constructor bodies)
public class EmitContext : BuilderContext
{
// TODO: Has to be private
- public ILGenerator ig;
+ public readonly ILGenerator ig;
/// <summary>
/// The value that is allowed to be returned or NULL if there is no
/// return type.
/// </summary>
- TypeSpec return_type;
+ readonly TypeSpec return_type;
/// <summary>
/// Keeps track of the Type to LocalBuilder temporary storage created
/// </summary>
public AnonymousExpression CurrentAnonymousMethod;
- public readonly IMemberContext MemberContext;
+ readonly IMemberContext member_context;
DynamicSiteClass dynamic_site_container;
public EmitContext (IMemberContext rc, ILGenerator ig, TypeSpec return_type)
{
- this.MemberContext = rc;
+ this.member_context = rc;
this.ig = ig;
this.return_type = return_type;
+
+#if STATIC
+ ig.__CleverExceptionBlockAssistance ();
+#endif
}
#region Properties
+ public BuiltinTypes BuiltinTypes {
+ get {
+ return MemberContext.Module.Compiler.BuiltinTypes;
+ }
+ }
+
public TypeSpec CurrentType {
- get { return MemberContext.CurrentType; }
+ get { return member_context.CurrentType; }
}
public TypeParameter[] CurrentTypeParameters {
- get { return MemberContext.CurrentTypeParameters; }
+ get { return member_context.CurrentTypeParameters; }
}
public MemberCore CurrentTypeDefinition {
- get { return MemberContext.CurrentMemberDefinition; }
+ get { return member_context.CurrentMemberDefinition; }
}
public bool IsStatic {
- get { return MemberContext.IsStatic; }
+ get { return member_context.IsStatic; }
}
- bool IsAnonymousStoreyMutateRequired {
+ public bool IsAnonymousStoreyMutateRequired {
get {
return CurrentAnonymousMethod != null &&
CurrentAnonymousMethod.Storey != null &&
}
}
- // Has to be used for emitter errors only
+ public IMemberContext MemberContext {
+ get {
+ return member_context;
+ }
+ }
+
+ public ModuleContainer Module {
+ get {
+ return member_context.Module;
+ }
+ }
+
+ // Has to be used for specific emitter errors only any
+ // possible resolver errors have to be reported during Resolve
public Report Report {
- get { return MemberContext.Compiler.Report; }
+ get {
+ return member_context.Module.Compiler.Report;
+ }
}
public TypeSpec ReturnType {
return return_type;
}
}
-#endregion
+ #endregion
/// <summary>
/// This is called immediately before emitting an IL opcode to tell the symbol
public void BeginScope ()
{
- ig.BeginScope();
SymbolWriter.OpenScope(ig);
}
public void EndScope ()
{
- ig.EndScope();
SymbolWriter.CloseScope(ig);
}
//
// Creates a nested container in this context for all dynamic compiler generated stuff
//
- public DynamicSiteClass CreateDynamicSite ()
+ internal DynamicSiteClass CreateDynamicSite ()
{
if (dynamic_site_container == null) {
- var mc = MemberContext.CurrentMemberDefinition as MemberBase;
+ var mc = member_context.CurrentMemberDefinition as MemberBase;
dynamic_site_container = new DynamicSiteClass (CurrentTypeDefinition.Parent.PartialContainer, mc, CurrentTypeParameters);
- RootContext.ToplevelTypes.AddCompilerGeneratedClass (dynamic_site_container);
+ CurrentTypeDefinition.Module.AddCompilerGeneratedClass (dynamic_site_container);
dynamic_site_container.CreateType ();
dynamic_site_container.DefineType ();
dynamic_site_container.ResolveTypeParameters ();
dynamic_site_container.Define ();
+
+ var inflator = new TypeParameterInflator (Module, CurrentType, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes);
+ var inflated = dynamic_site_container.CurrentType.InflateMember (inflator);
+ CurrentType.MemberCache.AddMember (inflated);
}
return dynamic_site_container;
ig.Emit (opcode, method);
}
- // TODO: REMOVE breaks mutator
- public void Emit (OpCode opcode, FieldBuilder field)
- {
- ig.Emit (opcode, field);
- }
-
- public void Emit (OpCode opcode, MethodSpec method, Type[] vargs)
+ public void Emit (OpCode opcode, MethodSpec method, MetaType[] vargs)
{
// TODO MemberCache: This should mutate too
ig.EmitCall (opcode, (MethodInfo) method.GetMetaInfo (), vargs);
}
var type = ac.Element;
- if (TypeManager.IsEnumType (type))
+ if (type.Kind == MemberKind.Enum)
type = EnumSpec.GetUnderlyingType (type);
- if (type == TypeManager.byte_type || type == TypeManager.bool_type)
+ switch (type.BuiltinType) {
+ case BuiltinTypeSpec.Type.Byte:
+ case BuiltinTypeSpec.Type.Bool:
Emit (OpCodes.Ldelem_U1);
- else if (type == TypeManager.sbyte_type)
+ return;
+ case BuiltinTypeSpec.Type.SByte:
Emit (OpCodes.Ldelem_I1);
- else if (type == TypeManager.short_type)
+ return;
+ case BuiltinTypeSpec.Type.Short:
Emit (OpCodes.Ldelem_I2);
- else if (type == TypeManager.ushort_type || type == TypeManager.char_type)
+ return;
+ case BuiltinTypeSpec.Type.UShort:
+ case BuiltinTypeSpec.Type.Char:
Emit (OpCodes.Ldelem_U2);
- else if (type == TypeManager.int32_type)
+ return;
+ case BuiltinTypeSpec.Type.Int:
Emit (OpCodes.Ldelem_I4);
- else if (type == TypeManager.uint32_type)
+ return;
+ case BuiltinTypeSpec.Type.UInt:
Emit (OpCodes.Ldelem_U4);
- else if (type == TypeManager.uint64_type)
- Emit (OpCodes.Ldelem_I8);
- else if (type == TypeManager.int64_type)
+ return;
+ case BuiltinTypeSpec.Type.ULong:
+ case BuiltinTypeSpec.Type.Long:
Emit (OpCodes.Ldelem_I8);
- else if (type == TypeManager.float_type)
+ return;
+ case BuiltinTypeSpec.Type.Float:
Emit (OpCodes.Ldelem_R4);
- else if (type == TypeManager.double_type)
+ return;
+ case BuiltinTypeSpec.Type.Double:
Emit (OpCodes.Ldelem_R8);
- else if (type == TypeManager.intptr_type)
+ return;
+ case BuiltinTypeSpec.Type.IntPtr:
Emit (OpCodes.Ldelem_I);
- else if (TypeManager.IsStruct (type)) {
+ return;
+ }
+
+ switch (type.Kind) {
+ case MemberKind.Struct:
Emit (OpCodes.Ldelema, type);
Emit (OpCodes.Ldobj, type);
- } else if (type.IsGenericParameter) {
+ break;
+ case MemberKind.TypeParameter:
Emit (OpCodes.Ldelem, type);
- } else if (type.IsPointer)
+ break;
+ case MemberKind.PointerType:
Emit (OpCodes.Ldelem_I);
- else
+ break;
+ default:
Emit (OpCodes.Ldelem_Ref);
+ break;
+ }
}
//
var type = ac.Element;
- if (type.IsEnum)
+ if (type.Kind == MemberKind.Enum)
type = EnumSpec.GetUnderlyingType (type);
- if (type == TypeManager.byte_type || type == TypeManager.sbyte_type || type == TypeManager.bool_type)
+ switch (type.BuiltinType) {
+ case BuiltinTypeSpec.Type.Byte:
+ case BuiltinTypeSpec.Type.SByte:
+ case BuiltinTypeSpec.Type.Bool:
Emit (OpCodes.Stelem_I1);
- else if (type == TypeManager.short_type || type == TypeManager.ushort_type || type == TypeManager.char_type)
+ return;
+ case BuiltinTypeSpec.Type.Short:
+ case BuiltinTypeSpec.Type.UShort:
+ case BuiltinTypeSpec.Type.Char:
Emit (OpCodes.Stelem_I2);
- else if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
+ return;
+ case BuiltinTypeSpec.Type.Int:
+ case BuiltinTypeSpec.Type.UInt:
Emit (OpCodes.Stelem_I4);
- else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
+ return;
+ case BuiltinTypeSpec.Type.Long:
+ case BuiltinTypeSpec.Type.ULong:
Emit (OpCodes.Stelem_I8);
- else if (type == TypeManager.float_type)
+ return;
+ case BuiltinTypeSpec.Type.Float:
Emit (OpCodes.Stelem_R4);
- else if (type == TypeManager.double_type)
+ return;
+ case BuiltinTypeSpec.Type.Double:
Emit (OpCodes.Stelem_R8);
- else if (type == TypeManager.intptr_type)
- Emit (OpCodes.Stobj, type);
- else if (TypeManager.IsStruct (type))
+ return;
+ }
+
+ switch (type.Kind) {
+ case MemberKind.Struct:
Emit (OpCodes.Stobj, type);
- else if (type.IsGenericParameter)
+ break;
+ case MemberKind.TypeParameter:
Emit (OpCodes.Stelem, type);
- else if (type.IsPointer)
+ break;
+ case MemberKind.PointerType:
Emit (OpCodes.Stelem_I);
- else
+ break;
+ default:
Emit (OpCodes.Stelem_Ref);
+ break;
+ }
}
public void EmitInt (int i)
//
// Load the object from the pointer.
//
- public void EmitLoadFromPtr (TypeSpec t)
+ public void EmitLoadFromPtr (TypeSpec type)
{
- if (t == TypeManager.int32_type)
+ if (type.Kind == MemberKind.Enum)
+ type = EnumSpec.GetUnderlyingType (type);
+
+ switch (type.BuiltinType) {
+ case BuiltinTypeSpec.Type.Int:
ig.Emit (OpCodes.Ldind_I4);
- else if (t == TypeManager.uint32_type)
+ return;
+ case BuiltinTypeSpec.Type.UInt:
ig.Emit (OpCodes.Ldind_U4);
- else if (t == TypeManager.short_type)
+ return;
+ case BuiltinTypeSpec.Type.Short:
ig.Emit (OpCodes.Ldind_I2);
- else if (t == TypeManager.ushort_type)
- ig.Emit (OpCodes.Ldind_U2);
- else if (t == TypeManager.char_type)
+ return;
+ case BuiltinTypeSpec.Type.UShort:
+ case BuiltinTypeSpec.Type.Char:
ig.Emit (OpCodes.Ldind_U2);
- else if (t == TypeManager.byte_type)
+ return;
+ case BuiltinTypeSpec.Type.Byte:
ig.Emit (OpCodes.Ldind_U1);
- else if (t == TypeManager.sbyte_type)
+ return;
+ case BuiltinTypeSpec.Type.SByte:
+ case BuiltinTypeSpec.Type.Bool:
ig.Emit (OpCodes.Ldind_I1);
- else if (t == TypeManager.uint64_type)
- ig.Emit (OpCodes.Ldind_I8);
- else if (t == TypeManager.int64_type)
+ return;
+ case BuiltinTypeSpec.Type.ULong:
+ case BuiltinTypeSpec.Type.Long:
ig.Emit (OpCodes.Ldind_I8);
- else if (t == TypeManager.float_type)
+ return;
+ case BuiltinTypeSpec.Type.Float:
ig.Emit (OpCodes.Ldind_R4);
- else if (t == TypeManager.double_type)
+ return;
+ case BuiltinTypeSpec.Type.Double:
ig.Emit (OpCodes.Ldind_R8);
- else if (t == TypeManager.bool_type)
- ig.Emit (OpCodes.Ldind_I1);
- else if (t == TypeManager.intptr_type)
+ return;
+ case BuiltinTypeSpec.Type.IntPtr:
ig.Emit (OpCodes.Ldind_I);
- else if (t.IsEnum) {
- if (t == TypeManager.enum_type)
- ig.Emit (OpCodes.Ldind_Ref);
- else
- EmitLoadFromPtr (EnumSpec.GetUnderlyingType (t));
- } else if (TypeManager.IsStruct (t) || TypeManager.IsGenericParameter (t))
- Emit (OpCodes.Ldobj, t);
- else if (t.IsPointer)
+ return;
+ }
+
+ switch (type.Kind) {
+ case MemberKind.Struct:
+ case MemberKind.TypeParameter:
+ Emit (OpCodes.Ldobj, type);
+ break;
+ case MemberKind.PointerType:
ig.Emit (OpCodes.Ldind_I);
- else
+ break;
+ default:
ig.Emit (OpCodes.Ldind_Ref);
+ break;
+ }
}
//
if (type.IsEnum)
type = EnumSpec.GetUnderlyingType (type);
- if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
+ switch (type.BuiltinType) {
+ case BuiltinTypeSpec.Type.Int:
+ case BuiltinTypeSpec.Type.UInt:
ig.Emit (OpCodes.Stind_I4);
- else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
+ return;
+ case BuiltinTypeSpec.Type.Long:
+ case BuiltinTypeSpec.Type.ULong:
ig.Emit (OpCodes.Stind_I8);
- else if (type == TypeManager.char_type || type == TypeManager.short_type ||
- type == TypeManager.ushort_type)
+ return;
+ case BuiltinTypeSpec.Type.Char:
+ case BuiltinTypeSpec.Type.Short:
+ case BuiltinTypeSpec.Type.UShort:
ig.Emit (OpCodes.Stind_I2);
- else if (type == TypeManager.float_type)
+ return;
+ case BuiltinTypeSpec.Type.Float:
ig.Emit (OpCodes.Stind_R4);
- else if (type == TypeManager.double_type)
+ return;
+ case BuiltinTypeSpec.Type.Double:
ig.Emit (OpCodes.Stind_R8);
- else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
- type == TypeManager.bool_type)
+ return;
+ case BuiltinTypeSpec.Type.Byte:
+ case BuiltinTypeSpec.Type.SByte:
+ case BuiltinTypeSpec.Type.Bool:
ig.Emit (OpCodes.Stind_I1);
- else if (type == TypeManager.intptr_type)
+ return;
+ case BuiltinTypeSpec.Type.IntPtr:
ig.Emit (OpCodes.Stind_I);
- else if (TypeManager.IsStruct (type) || TypeManager.IsGenericParameter (type))
- ig.Emit (OpCodes.Stobj, type.GetMetaInfo ());
+ return;
+ }
+
+ if (type.IsStruct || TypeManager.IsGenericParameter (type))
+ Emit (OpCodes.Stobj, type);
else
ig.Emit (OpCodes.Stind_Ref);
}