//
// Module (top-level type) container
//
- public class ModuleContainer : TypeContainer
+ public sealed class ModuleContainer : TypeContainer
{
- public CharSet DefaultCharSet = CharSet.Ansi;
+#if STATIC
+ //
+ // Compiler generated container for static data
+ //
+ sealed class StaticDataContainer : CompilerGeneratedClass
+ {
+ readonly Dictionary<int, Struct> size_types;
+ new int fields;
+
+ public StaticDataContainer (ModuleContainer module)
+ : base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null), Modifiers.STATIC)
+ {
+ size_types = new Dictionary<int, Struct> ();
+ }
+
+ public override void CloseType ()
+ {
+ base.CloseType ();
+
+ foreach (var entry in size_types) {
+ entry.Value.CloseType ();
+ }
+ }
+
+ public FieldSpec DefineInitializedData (byte[] data, Location loc)
+ {
+ Struct size_type;
+ if (!size_types.TryGetValue (data.Length, out size_type)) {
+ //
+ // Build common type for this data length. We cannot use
+ // DefineInitializedData because it creates public type,
+ // and its name is not unique among modules
+ //
+ size_type = new Struct (null, this, new MemberName ("$ArrayType=" + data.Length, loc), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, null);
+ size_type.CreateType ();
+ size_type.DefineType ();
+
+ size_types.Add (data.Length, size_type);
+
+ // It has to work even if StructLayoutAttribute does not exist
+ size_type.TypeBuilder.__SetLayout (1, data.Length);
+ }
+
+ var name = "$field-" + fields.ToString ("X");
+ ++fields;
+ const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL;
+ var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
+ fbuilder.__SetDataAndRVA (data);
+
+ return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
+ }
+ }
+
+ StaticDataContainer static_data;
+
+ //
+ // Makes const data field inside internal type container
+ //
+ public FieldSpec MakeStaticData (byte[] data, Location loc)
+ {
+ if (static_data == null) {
+ static_data = new StaticDataContainer (this);
+ static_data.CreateType ();
+ static_data.DefineType ();
+
+ AddCompilerGeneratedClass (static_data);
+ }
+
+ return static_data.DefineInitializedData (data, loc);
+ }
+#endif
+
+ public CharSet? DefaultCharSet;
public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
- Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
+ readonly Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
+ readonly Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> array_types;
+ readonly Dictionary<TypeSpec, PointerContainer> pointer_types;
+ readonly Dictionary<TypeSpec, ReferenceContainer> reference_types;
+ readonly Dictionary<TypeSpec, MethodSpec> attrs_cache;
+
+ // Used for unique namespaces/types during parsing
+ Dictionary<MemberName, ITypesContainer> defined_type_containers;
AssemblyDefinition assembly;
readonly CompilerContext context;
readonly RootNamespace global_ns;
- Dictionary<string, RootNamespace> alias_ns;
+ readonly Dictionary<string, RootNamespace> alias_ns;
ModuleBuilder builder;
- int static_data_counter;
- // HACK
- public List<Enum> hack_corlib_enums = new List<Enum> ();
-
- bool has_default_charset;
bool has_extenstion_method;
PredefinedAttributes predefined_attributes;
PredefinedTypes predefined_types;
+ PredefinedMembers predefined_members;
static readonly string[] attribute_targets = new string[] { "assembly", "module" };
anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
global_ns = new GlobalRootNamespace ();
alias_ns = new Dictionary<string, RootNamespace> ();
+ array_types = new Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ();
+ pointer_types = new Dictionary<TypeSpec, PointerContainer> ();
+ reference_types = new Dictionary<TypeSpec, ReferenceContainer> ();
+ attrs_cache = new Dictionary<TypeSpec, MethodSpec> ();
+
+ defined_type_containers = new Dictionary<MemberName, ITypesContainer> ();
}
#region Properties
+ internal Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ArrayTypesCache {
+ get {
+ return array_types;
+ }
+ }
+
+ //
+ // Cache for parameter-less attributes
+ //
+ internal Dictionary<TypeSpec, MethodSpec> AttributeConstructorCache {
+ get {
+ return attrs_cache;
+ }
+ }
+
public override AttributeTargets AttributeTargets {
get {
return AttributeTargets.Assembly;
}
}
+ internal DocumentationBuilder DocumentationBuilder {
+ get; set;
+ }
+
+ public Evaluator Evaluator {
+ get; set;
+ }
+
public bool HasDefaultCharSet {
get {
- return has_default_charset;
+ return DefaultCharSet.HasValue;
}
}
}
}
+ public bool HasTypesFullyDefined {
+ get; set;
+ }
+
//
// Returns module global:: namespace
//
}
}
+ internal Dictionary<TypeSpec, PointerContainer> PointerTypesCache {
+ get {
+ return pointer_types;
+ }
+ }
+
internal PredefinedAttributes PredefinedAttributes {
get {
return predefined_attributes;
}
}
+ internal PredefinedMembers PredefinedMembers {
+ get {
+ return predefined_members;
+ }
+ }
+
internal PredefinedTypes PredefinedTypes {
get {
return predefined_types;
}
}
+ internal Dictionary<TypeSpec, ReferenceContainer> ReferenceTypesCache {
+ get {
+ return reference_types;
+ }
+ }
+
public override string[] ValidAttributeTargets {
get {
return attribute_targets;
#endregion
+ public override void Accept (StructuralVisitor visitor)
+ {
+ visitor.Visit (this);
+ }
+
public void AddAnonymousType (AnonymousTypeClass type)
{
List<AnonymousTypeClass> existing;
existing.Add (type);
}
- public void AddAttributes (List<Attribute> attrs)
+ public void AddAttribute (Attribute attr, IMemberContext context)
{
- AddAttributes (attrs, this);
- }
-
- public void AddAttributes (List<Attribute> attrs, IMemberContext context)
- {
- foreach (Attribute a in attrs)
- a.AttachTo (this, context);
+ attr.AttachTo (this, context);
if (attributes == null) {
- attributes = new Attributes (attrs);
+ attributes = new Attributes (attr);
return;
}
- attributes.AddAttributes (attrs);
+
+ attributes.AddAttribute (attr);
}
public override TypeContainer AddPartial (TypeContainer nextPart)
return;
}
- if (a.Type == pa.CLSCompliant) {
+ if (a.Type == pa.DefaultCharset) {
+ switch (a.GetCharSetValue ()) {
+ case CharSet.Ansi:
+ case CharSet.None:
+ break;
+ case CharSet.Auto:
+ DefaultCharSet = CharSet.Auto;
+ DefaultCharSetType = TypeAttributes.AutoClass;
+ break;
+ case CharSet.Unicode:
+ DefaultCharSet = CharSet.Unicode;
+ DefaultCharSetType = TypeAttributes.UnicodeClass;
+ break;
+ default:
+ Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid",
+ a.GetSignatureForError ());
+ break;
+ }
+ } else if (a.Type == pa.CLSCompliant) {
Attribute cls = DeclaringAssembly.CLSCompliantAttribute;
if (cls == null) {
Report.Warning (3012, 1, a.Location,
builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
}
- public new void CloseType ()
+ public override void CloseType ()
{
- HackCorlibEnums ();
-
foreach (TypeContainer tc in types) {
tc.CloseType ();
}
if (compiler_generated != null)
foreach (CompilerGeneratedClass c in compiler_generated)
c.CloseType ();
-
- //
- // If we have a <PrivateImplementationDetails> class, close it
- //
- if (TypeBuilder != null) {
- var cg = PredefinedAttributes.CompilerGenerated;
- cg.EmitAttribute (TypeBuilder);
- TypeBuilder.CreateType ();
- }
}
public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize)
public RootNamespace CreateRootNamespace (string alias)
{
if (alias == global_ns.Alias) {
- NamespaceEntry.Error_GlobalNamespaceRedefined (Location.Null, Report);
+ NamespaceContainer.Error_GlobalNamespaceRedefined (Location.Null, Report);
return global_ns;
}
return rn;
}
- public new void Define ()
+ public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder)
{
- builder = assembly.CreateModuleBuilder ();
-
- // FIXME: Temporary hack for repl to reset
- TypeBuilder = null;
+ this.assembly = assembly;
+ builder = moduleBuilder;
+ }
- // TODO: It should be done much later when the types are resolved
- // but that require DefineType clean-up
- ResolveGlobalAttributes ();
+ public new void CreateType ()
+ {
+ // Release cache used by parser only
+ if (Evaluator == null)
+ defined_type_containers = null;
+ else
+ defined_type_containers.Clear ();
foreach (TypeContainer tc in types)
tc.CreateType ();
+ }
- InitializePredefinedTypes ();
-
+ public new void Define ()
+ {
foreach (TypeContainer tc in types)
tc.DefineType ();
throw new InternalErrorException (tc, e);
}
}
+
+ HasTypesFullyDefined = true;
}
public override void Emit ()
if (OptAttributes != null)
OptAttributes.Emit ();
- if (RootContext.Unsafe) {
+ if (Compiler.Settings.Unsafe) {
var pa = PredefinedAttributes.UnverifiableCode;
if (pa.IsDefined)
pa.EmitAttribute (builder);
foreach (var tc in types)
tc.DefineConstants ();
- HackCorlib ();
-
foreach (TypeContainer tc in types)
tc.EmitType ();
c.EmitType ();
}
+ internal override void GenerateDocComment (DocumentationBuilder builder)
+ {
+ foreach (var tc in types)
+ tc.GenerateDocComment (builder);
+ }
+
public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
{
List<AnonymousTypeClass> candidates;
return "<module>";
}
- void HackCorlib ()
- {
-#if !STATIC
- if (RootContext.StdLib)
- return;
-
- //
- // HACK: When building corlib mcs uses loaded mscorlib which
- // has different predefined types and this method sets mscorlib types
- // to be same to avoid type check errors in CreateType.
- //
- var type = typeof (Type);
- var system_4_type_arg = new[] { type, type, type, type };
-
- MethodInfo set_corlib_type_builders =
- typeof (System.Reflection.Emit.AssemblyBuilder).GetMethod (
- "SetCorlibTypeBuilders", BindingFlags.NonPublic | BindingFlags.Instance, null,
- system_4_type_arg, null);
-
- if (set_corlib_type_builders == null) {
- Compiler.Report.Warning (-26, 3,
- "The compilation may fail due to missing `System.Reflection.Emit.AssemblyBuilder.SetCorlibTypeBuilders(...)' method");
- return;
- }
-
- object[] args = new object[4];
- args[0] = TypeManager.object_type.GetMetaInfo ();
- args[1] = TypeManager.value_type.GetMetaInfo ();
- args[2] = TypeManager.enum_type.GetMetaInfo ();
- args[3] = TypeManager.void_type.GetMetaInfo ();
- set_corlib_type_builders.Invoke (assembly.Builder, args);
-#endif
- }
-
- void HackCorlibEnums ()
- {
- if (RootContext.StdLib)
- return;
-
- // Another Mono corlib HACK
- // mono_class_layout_fields requires to have enums created
- // before creating a class which used the enum for any of its fields
- foreach (var e in hack_corlib_enums)
- e.CloseType ();
- }
-
public void InitializePredefinedTypes ()
{
predefined_attributes = new PredefinedAttributes (this);
predefined_types = new PredefinedTypes (this);
+ predefined_members = new PredefinedMembers (this);
}
public override bool IsClsComplianceRequired ()
return DeclaringAssembly.IsCLSCompliant;
}
- //
- // Makes an initialized struct, returns the field builder that
- // references the data. Thanks go to Sergey Chaban for researching
- // how to do this. And coming up with a shorter mechanism than I
- // was able to figure out.
- //
- // This works but makes an implicit public struct $ArrayType$SIZE and
- // makes the fields point to it. We could get more control if we did
- // use instead:
- //
- // 1. DefineNestedType on the impl_details_class with our struct.
- //
- // 2. Define the field on the impl_details_class
- //
- public FieldBuilder MakeStaticData (byte[] data)
+ protected override bool AddMemberType (TypeContainer tc)
{
- if (TypeBuilder == null) {
- TypeBuilder = builder.DefineType ("<PrivateImplementationDetails>",
- TypeAttributes.NotPublic, TypeManager.object_type.GetMetaInfo ());
- }
+ if (AddTypesContainer (tc)) {
+ if ((tc.ModFlags & Modifiers.PARTIAL) != 0)
+ defined_names.Add (tc.Name, tc);
- var fb = TypeBuilder.DefineInitializedData (
- "$$field-" + (static_data_counter++), data,
- FieldAttributes.Static | FieldAttributes.Assembly);
+ tc.NamespaceEntry.NS.AddType (this, tc.Definition);
+ return true;
+ }
- return fb;
+ return false;
}
- protected override bool AddMemberType (TypeContainer ds)
+ public bool AddTypesContainer (ITypesContainer container)
{
- if (!AddToContainer (ds, ds.Name))
- return false;
- ds.NamespaceEntry.NS.AddType (ds.Definition);
- return true;
- }
-
- protected override void RemoveMemberType (DeclSpace ds)
- {
- ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
- base.RemoveMemberType (ds);
- }
+ var mn = container.MemberName;
+ ITypesContainer found;
+ if (!defined_type_containers.TryGetValue (mn, out found)) {
+ defined_type_containers.Add (mn, container);
+ return true;
+ }
- /// <summary>
- /// It is called very early therefore can resolve only predefined attributes
- /// </summary>
- void ResolveGlobalAttributes ()
- {
- if (OptAttributes == null)
- return;
+ if (container is NamespaceContainer && found is NamespaceContainer)
+ return true;
- if (!OptAttributes.CheckTargets ())
- return;
+ var container_tc = container as TypeContainer;
+ var found_tc = found as TypeContainer;
+ if (container_tc != null && found_tc != null && container_tc.Kind == found_tc.Kind) {
+ if ((found_tc.ModFlags & container_tc.ModFlags & Modifiers.PARTIAL) != 0) {
+ return false;
+ }
- // FIXME: Define is wrong as the type may not exist yet
- var DefaultCharSet_attr = new PredefinedAttribute (this, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
- DefaultCharSet_attr.Define ();
- Attribute a = ResolveModuleAttribute (DefaultCharSet_attr);
- if (a != null) {
- has_default_charset = true;
- DefaultCharSet = a.GetCharSetValue ();
- switch (DefaultCharSet) {
- case CharSet.Ansi:
- case CharSet.None:
- break;
- case CharSet.Auto:
- DefaultCharSetType = TypeAttributes.AutoClass;
- break;
- case CharSet.Unicode:
- DefaultCharSetType = TypeAttributes.UnicodeClass;
- break;
- default:
- Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid",
- DefaultCharSet_attr.GetSignatureForError ());
- break;
+ if (((found_tc.ModFlags | container_tc.ModFlags) & Modifiers.PARTIAL) != 0) {
+ Report.SymbolRelatedToPreviousError (found_tc);
+ Error_MissingPartialModifier (container_tc);
+ return false;
}
}
+
+ string ns = mn.Left != null ? mn.Left.GetSignatureForError () : Module.GlobalRootNamespace.GetSignatureForError ();
+ mn = new MemberName (mn.Name, mn.TypeArguments, mn.Location);
+
+ Report.SymbolRelatedToPreviousError (found.Location, "");
+ Report.Error (101, container.Location,
+ "The namespace `{0}' already contains a definition for `{1}'",
+ ns, mn.GetSignatureForError ());
+ return false;
}
- public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
+ protected override void RemoveMemberType (TypeContainer ds)
{
- Attribute a = OptAttributes.Search ("assembly", a_type);
- if (a != null) {
- a.Resolve ();
- }
- return a;
+ defined_type_containers.Remove (ds.MemberName);
+ ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
+ base.RemoveMemberType (ds);
}
- Attribute ResolveModuleAttribute (PredefinedAttribute a_type)
+ public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
{
- Attribute a = OptAttributes.Search ("module", a_type);
+ Attribute a = OptAttributes.Search ("assembly", a_type);
if (a != null) {
a.Resolve ();
}
}
}
- class RootDeclSpace : TypeContainer {
- public RootDeclSpace (NamespaceEntry ns)
+ sealed class RootDeclSpace : TypeContainer {
+ public RootDeclSpace (ModuleContainer module, NamespaceContainer ns)
: base (ns, null, MemberName.Null, null, 0)
{
- PartialContainer = RootContext.ToplevelTypes;
+ PartialContainer = module;
}
public override AttributeTargets AttributeTargets {
}
}
+ public override void Accept (StructuralVisitor visitor)
+ {
+ throw new InternalErrorException ("should not be called");
+ }
+
public override bool IsClsComplianceRequired ()
{
return PartialContainer.IsClsComplianceRequired ();
}
+ public override IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope)
+ {
+ return null;
+ }
+
public override FullNamedExpression LookupNamespaceAlias (string name)
{
return NamespaceEntry.LookupNamespaceAlias (name);