This is used by the flow analysis code to keep track of the type of local variables and variables. The flow code uses a BitVector to keep track of whether a variable has been assigned or not. This is easy for fundamental types (int, char etc.) or reference types since you can only assign the whole variable as such. For structs, we also need to keep track of all its fields. To do this, we allocate one bit for the struct itself (it's used if you assign/access the whole struct) followed by one bit for each of its fields. This class computes this `layout' for each type.
		protected VariableInfo (VariableInfo parent, TypeInfo type)
		{
			this.Name = parent.Name;
			this.TypeInfo = type;
			this.Offset = parent.Offset + type.Offset;
			this.Parent = parent;
			this.Length = type.TotalLength;

			this.IsParameter = parent.IsParameter;

			Initialize ();
		}
			// Private constructor.  To save memory usage, we only need to create one instance
			// of this class per struct type.
			private StructInfo (TypeSpec type)
			{
				this.Type = type;

				field_type_hash.Add (type, this);

				fields = MemberCache.GetAllFieldsForDefiniteAssignment (type);

				struct_field_hash = new Dictionary<string, TypeInfo> ();
				field_hash = new Dictionary<string, int> (fields.Count);

				StructFields = new TypeInfo[fields.Count];
				StructInfo[] sinfo = new StructInfo[fields.Count];

				InTransit = true;

				for (int i = 0; i < fields.Count; i++) {
					var field = fields [i];

					if (field.MemberType.IsStruct)
						sinfo [i] = GetStructInfo (field.MemberType);

					if (sinfo [i] == null)
						field_hash.Add (field.Name, ++Length);
					else if (sinfo [i].InTransit) {
						sinfo [i] = null;
						return;
					}
				}

				InTransit = false;

				TotalLength = Length + 1;
				for (int i = 0; i < fields.Count; i++) {
					var field = fields [i];

					if (sinfo [i] == null)
						continue;

					field_hash.Add (field.Name, TotalLength);

					StructFields [i] = new TypeInfo (sinfo [i], TotalLength);
					struct_field_hash.Add (field.Name, StructFields [i]);
					TotalLength += sinfo [i].TotalLength;
				}
			}
		protected VariableInfo (string name, TypeSpec type, int offset)
		{
			this.Name = name;
			this.Offset = offset;
			this.TypeInfo = TypeInfo.GetTypeInfo (type);

			Length = TypeInfo.TotalLength;

			Initialize ();
		}
		public static TypeInfo GetTypeInfo (TypeSpec type)
		{
			if (!type.IsStruct)
				return simple_type;

			TypeInfo info;
			if (type_hash.TryGetValue (type, out info))
				return info;

			var struct_info = StructInfo.GetStructInfo (type);
			if (struct_info != null) {
				info = new TypeInfo (struct_info, 0);
			} else {
				info = simple_type;
			}

			type_hash.Add (type, info);
			return info;
		}
			// Private constructor.  To save memory usage, we only need to create one instance
			// of this class per struct type.
			private StructInfo (TypeSpec type)
			{
				this.Type = type;

				field_type_hash.Add (type, this);

				TypeContainer tc = type.MemberDefinition as TypeContainer;

				var public_fields = new List<FieldSpec> ();
				var non_public_fields = new List<FieldSpec> ();

				if (tc != null) {
					var fields = tc.Fields;

					if (fields != null) {
						foreach (FieldBase field in fields) {
							if ((field.ModFlags & Modifiers.STATIC) != 0)
								continue;
							if ((field.ModFlags & Modifiers.PUBLIC) != 0)
								public_fields.Add (field.Spec);
							else
								non_public_fields.Add (field.Spec);
						}
					}
				}

				CountPublic = public_fields.Count;
				CountNonPublic = non_public_fields.Count;
				Count = CountPublic + CountNonPublic;

				Fields = new FieldSpec[Count];
				public_fields.CopyTo (Fields, 0);
				non_public_fields.CopyTo (Fields, CountPublic);

				struct_field_hash = new Dictionary<string, TypeInfo> ();
				field_hash = new Dictionary<string, int> ();

				Length = 0;
				StructFields = new TypeInfo [Count];
				StructInfo[] sinfo = new StructInfo [Count];

				InTransit = true;

				for (int i = 0; i < Count; i++) {
					var field = Fields [i];

					sinfo [i] = GetStructInfo (field.MemberType);
					if (sinfo [i] == null)
						field_hash.Add (field.Name, ++Length);
					else if (sinfo [i].InTransit) {
						sinfo [i] = null;
						return;
					}
				}

				InTransit = false;

				TotalLength = Length + 1;
				for (int i = 0; i < Count; i++) {
					var field = Fields [i];

					if (sinfo [i] == null)
						continue;

					field_hash.Add (field.Name, TotalLength);

					HasStructFields = true;
					StructFields [i] = new TypeInfo (sinfo [i], TotalLength);
					struct_field_hash.Add (field.Name, StructFields [i]);
					TotalLength += sinfo [i].TotalLength;
				}
			}
		public static TypeInfo GetTypeInfo (TypeSpec type)
		{
			TypeInfo info;
			if (type_hash.TryGetValue (type, out info))
				return info;

			info = new TypeInfo (type);
			type_hash.Add (type, info);
			return info;
		}
Exemple #7
0
		VariableInfo (string name, TypeSpec type, int offset, IMemberContext context)
		{
			this.Name = name;
			this.Offset = offset;
			this.TypeInfo = TypeInfo.GetTypeInfo (type, context);

			Length = TypeInfo.TotalLength;

			Initialize ();
		}
Exemple #8
0
		public static TypeInfo GetTypeInfo (TypeSpec type, IMemberContext context)
		{
			if (!type.IsStruct)
				return simple_type;

			TypeInfo info;
			Dictionary<TypeSpec, TypeInfo> type_hash;
			if (type.BuiltinType > 0) {
				// Don't cache built-in types, they are null in most cases except for
				// corlib compilation when we need to distinguish between declaration
				// and referencing
				type_hash = null;
			} else {
				type_hash = context.Module.TypeInfoCache;
				if (type_hash.TryGetValue (type, out info))
					return info;
			}

			var struct_info = StructInfo.GetStructInfo (type, context);
			if (struct_info != null) {
				info = new TypeInfo (struct_info, 0);
			} else {
				info = simple_type;
			}

			if (type_hash != null)
				type_hash.Add (type, info);

			return info;
		}