Author: martin
Date: 2005-03-22 05:01:15 -0500 (Tue, 22 Mar 2005)
New Revision: 42077
Modified:
trunk/mcs/gmcs/ChangeLog
trunk/mcs/gmcs/anonymous.cs
trunk/mcs/gmcs/attribute.cs
trunk/mcs/gmcs/class.cs
trunk/mcs/gmcs/const.cs
trunk/mcs/gmcs/cs-parser.jay
trunk/mcs/gmcs/ecore.cs
trunk/mcs/gmcs/expression.cs
trunk/mcs/gmcs/flowanalysis.cs
trunk/mcs/gmcs/rootcontext.cs
trunk/mcs/gmcs/statement.cs
trunk/mcs/gmcs/typemanager.cs
Log:
**** Merged r40464 from MCS ****
Modified: trunk/mcs/gmcs/ChangeLog
===================================================================
--- trunk/mcs/gmcs/ChangeLog 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/ChangeLog 2005-03-22 10:01:15 UTC (rev 42077)
@@ -1,3 +1,54 @@
+2005-02-11 Marek Safar <[EMAIL PROTECTED]>
+
+ C# 2.0 Fixed buffer implementation
+
+ * anonymous.cs: Update after RegisterHelperClass renaming.
+
+ * attribute.cs (AttributeTester.fixed_buffer_cache):
+ Cache of external fixed buffers.
+ (AttributeTester.GetFixedBuffer): Returns IFixedBuffer
+ implementation if field is fixed buffer else null.
+
+ * class.cs
+ (TypeContainer.AddField): Accept FieldMember instead of Field.
+ (FieldBase.IsFieldClsCompliant): Extracted code from
+ VerifyClsCompliance descendant customization.
+ (FixedField): New class handles fixed buffer fields.
+ (FixedFieldExternal): Keeps information about imported fixed
+ buffer.
+ (IFixedField): Make access to internal or external fixed buffer
+ same.
+
+ * cs-parser.jay: Add fixed buffer parsing.
+
+ * ecore.cs (FieldExpr.Emit): Add special emit case for fixed
+ buffer.
+
+ * expression.cs (Indirection): Extended implementation to accept
+ fixed buffer field.
+ (PointerArithmetic.Emit): Get element from fixed buffer as well.
+ (ElementAccess.MakePointerAccess): Get type as parameter.
+ (DoResolve): Add fixed buffer field expression conversion.
+ (DoResolveLValue): Ditto.
+ (FixedBufferPtr): New class. Moved most of original ArrayPtr.
+ (ArrayPtr): Derives from FixedBufferPtr.
+ (ArrayPtr.Emit): Add extra emit for array elements.
+
+ * flowanalysis.cs.cs (StructInfo): Use FieldMember.
+
+ * rootcontext.cs (CloseTypes): Emit CompilerGenerated attribute
+ for compiler generated types.
+ (RegisterCompilerGeneratedType): Renamed from RegisterHelperClass.
+
+ * statement.cs (Fixed): Refactored to be easier add fixed buffer
+ and consume less memory.
+ (Fixed.Resolve): Add fixed buffer case.
+
+ * typemanager.cs (compiler_generated_attr_ctor,
+ fixed_buffer_attr_ctor): Add new 2.0 compiler attributes.
+ (HasElementType): Add our own implementation to work on every
+ runtime.
+
2005-02-11 Miguel de Icaza <[EMAIL PROTECTED]>
* anonymous.cs (CaptureContext): Track whether `this' has been
Modified: trunk/mcs/gmcs/anonymous.cs
===================================================================
--- trunk/mcs/gmcs/anonymous.cs 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/anonymous.cs 2005-03-22 10:01:15 UTC (rev 42077)
@@ -561,7 +561,7 @@
public void CloseTypes ()
{
- RootContext.RegisterHelperClass (ScopeTypeBuilder);
+ RootContext.RegisterCompilerGeneratedType
(ScopeTypeBuilder);
foreach (ScopeInfo si in children)
si.CloseTypes ();
}
Modified: trunk/mcs/gmcs/attribute.cs
===================================================================
--- trunk/mcs/gmcs/attribute.cs 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/attribute.cs 2005-03-22 10:01:15 UTC (rev 42077)
@@ -1371,7 +1371,11 @@
static PtrHashtable analyzed_types_obsolete = new PtrHashtable
();
static PtrHashtable analyzed_member_obsolete = new PtrHashtable
();
static PtrHashtable analyzed_method_excluded = new PtrHashtable
();
+ static PtrHashtable fixed_buffer_cache = new PtrHashtable ();
+ static object TRUE = new object ();
+ static object FALSE = new object ();
+
private AttributeTester ()
{
}
@@ -1463,11 +1467,40 @@
}
analyzed_types.Add (type, result ? TRUE : FALSE);
return result;
- }
+ }
+
+ /// <summary>
+ /// Returns IFixedBuffer implementation if field is fixed
buffer else null.
+ /// </summary>
+ public static IFixedBuffer GetFixedBuffer (FieldInfo fi)
+ {
+ FieldBase fb = TypeManager.GetField (fi);
+ if (fb != null) {
+ return fb as IFixedBuffer;
+ }
- static object TRUE = new object ();
- static object FALSE = new object ();
+#if NET_2_0
+ object o = fixed_buffer_cache [fi];
+ if (o == null) {
+ if (System.Attribute.GetCustomAttribute (fi,
TypeManager.fixed_buffer_attr_type) == null) {
+ fixed_buffer_cache.Add (fi, FALSE);
+ return null;
+ }
+
+ IFixedBuffer iff = new FixedFieldExternal (fi);
+ fixed_buffer_cache.Add (fi, iff);
+ return iff;
+ }
+ if (o == FALSE)
+ return null;
+
+ return (IFixedBuffer)o;
+#else
+ return null;
+#endif
+ }
+
public static void VerifyModulesClsCompliance ()
{
Module[] modules = TypeManager.Modules;
Modified: trunk/mcs/gmcs/class.cs
===================================================================
--- trunk/mcs/gmcs/class.cs 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/class.cs 2005-03-22 10:01:15 UTC (rev 42077)
@@ -581,7 +581,7 @@
interfaces.Add (iface);
}
- public void AddField (Field field)
+ public void AddField (FieldMember field)
{
if (!AddToMemberContainer (field))
return;
@@ -1762,7 +1762,7 @@
if (fields != null) {
int len = fields.Count;
for (int i = 0; i < len; i++) {
- Field f = (Field) fields [i];
+ FieldMember f = (FieldMember)
fields [i];
if ((f.ModFlags & modflags) ==
0)
continue;
@@ -2223,7 +2223,7 @@
}
if (fields != null)
- foreach (Field f in fields)
+ foreach (FieldMember f in fields)
f.Emit ();
if (events != null){
@@ -5693,6 +5693,15 @@
return TypeManager.GetFullNameSignature (FieldBuilder);
}
+ protected virtual bool IsFieldClsCompliant {
+ get {
+ if (FieldBuilder == null)
+ return true;
+
+ return AttributeTester.IsClsCompliant
(FieldBuilder.FieldType);
+ }
+ }
+
public override string[] ValidAttributeTargets {
get {
return attribute_targets;
@@ -5704,11 +5713,7 @@
if (!base.VerifyClsCompliance (ds))
return false;
- if (FieldBuilder == null) {
- return true;
- }
-
- if (!AttributeTester.IsClsCompliant
(FieldBuilder.FieldType)) {
+ if (!IsFieldClsCompliant) {
Report.Error (3003, Location, "Type of '{0}' is
not CLS-compliant", GetSignatureForError ());
}
return true;
@@ -5795,6 +5800,11 @@
public override void Emit ()
{
+ if (OptAttributes != null) {
+ EmitContext ec = new EmitContext (Parent,
Location, null, FieldBuilder.FieldType, ModFlags);
+ OptAttributes.Emit (ec, this);
+ }
+
if (Parent.HasExplicitLayout && ((status &
Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0) {
Report.Error (625, Location, "'{0}': Instance
field types marked with StructLayout(LayoutKind.Explicit) must have a
FieldOffset attribute.", GetSignatureForError ());
}
@@ -5810,6 +5820,163 @@
}
}
+ interface IFixedBuffer
+ {
+ FieldInfo Element { get; }
+ Type ElementType { get; }
+ }
+
+ public class FixedFieldExternal: IFixedBuffer
+ {
+ FieldInfo element_field;
+
+ public FixedFieldExternal (FieldInfo fi)
+ {
+ element_field = fi.FieldType.GetField
(FixedField.FixedElementName);
+ }
+
+ #region IFixedField Members
+
+ public FieldInfo Element {
+ get {
+ return element_field;
+ }
+ }
+
+ public Type ElementType {
+ get {
+ return element_field.FieldType;
+ }
+ }
+
+ #endregion
+ }
+
+ /// <summary>
+ /// Fixed buffer implementation
+ /// </summary>
+ public class FixedField: FieldMember, IFixedBuffer
+ {
+ public const string FixedElementName = "FixedElementField";
+ static int GlobalCounter = 0;
+ static object[] ctor_args = new object[] {
(short)LayoutKind.Sequential };
+ static FieldInfo[] fi;
+
+ TypeBuilder fixed_buffer_type;
+ FieldBuilder element;
+ Expression size_expr;
+ int buffer_size;
+
+ const int AllowedModifiers =
+ Modifiers.NEW |
+ Modifiers.PUBLIC |
+ Modifiers.PROTECTED |
+ Modifiers.INTERNAL |
+ Modifiers.PRIVATE;
+
+ public FixedField (TypeContainer parent, Expression type, int
mod, string name,
+ Expression size_expr, Attributes attrs, Location loc):
+ base (parent, type, mod, AllowedModifiers, new
MemberName (name), null, attrs, loc)
+ {
+ if (RootContext.Version == LanguageVersion.ISO_1)
+ Report.FeatureIsNotStandardized (loc, "fixed
sized buffers");
+
+ this.size_expr = size_expr;
+ }
+
+ public override bool Define()
+ {
+#if !NET_2_0
+ if ((ModFlags & (Modifiers.PUBLIC |
Modifiers.PROTECTED)) != 0)
+ Report.Warning (-23, Location, "Only not
private or internal fixed sized buffers are supported by .NET 1.x");
+#endif
+
+ if (Parent.Kind != Kind.Struct) {
+ Report.Error (1642, Location, "Fixed buffer
fields may only be members of structs");
+ return false;
+ }
+
+ if (!base.Define ())
+ return false;
+
+ if (!MemberType.IsPrimitive) {
+ Report.Error (1663, Location, "Fixed sized
buffer type must be one of the following: bool, byte, short, int, long, char,
sbyte, ushort, uint, ulong, float or double");
+ return false;
+ }
+
+ Expression e = size_expr.Resolve (Parent.EmitContext);
+ if (e == null)
+ return false;
+
+ Constant c = e as Constant;
+ if (c == null) {
+ Report.Error (133, Location, "The expression
being assigned to '{0}' must be constant", GetSignatureForError ());
+ return false;
+ }
+
+ buffer_size = (int)c.GetValue ();
+ if (buffer_size <= 0) {
+ Report.Error (1665, Location, "Fixed sized
buffer '{0}' must have a length greater than zero", GetSignatureForError ());
+ return false;
+ }
+ buffer_size *= Expression.GetTypeSize (MemberType);
+
+ // Define nested
+ string name = String.Format ("<{0}>__FixedBuffer{1}",
Name, GlobalCounter++);
+
+ fixed_buffer_type = Parent.TypeBuilder.DefineNestedType
(name,
+ TypeAttributes.NestedPublic |
TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
+ element = fixed_buffer_type.DefineField
(FixedElementName, MemberType, FieldAttributes.Public);
+ RootContext.RegisterCompilerGeneratedType
(fixed_buffer_type);
+
+ FieldBuilder = Parent.TypeBuilder.DefineField (Name,
fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
+ TypeManager.RegisterFieldBase (FieldBuilder, this);
+
+ return true;
+ }
+
+ public override void Emit()
+ {
+ if (fi == null)
+ fi = new FieldInfo [] {
TypeManager.struct_layout_attribute_type.GetField ("Size") };
+
+ object[] fi_val = new object[1];
+ fi_val [0] = buffer_size;
+
+ CustomAttributeBuilder cab = new CustomAttributeBuilder
(TypeManager.struct_layout_attribute_ctor,
+ ctor_args, fi, fi_val);
+ fixed_buffer_type.SetCustomAttribute (cab);
+
+#if NET_2_0
+ cab = new CustomAttributeBuilder
(TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
+ FieldBuilder.SetCustomAttribute (cab);
+#endif
+ base.Emit ();
+ }
+
+ protected override bool IsFieldClsCompliant {
+ get {
+ return false;
+ }
+ }
+
+ #region IFixedField Members
+
+ public FieldInfo Element {
+ get {
+ return element;
+ }
+ }
+
+ public Type ElementType {
+ get {
+ return MemberType;
+ }
+ }
+
+ #endregion
+ }
+
//
// The Field class is used to represents class/struct fields during
parsing.
//
@@ -5910,18 +6077,6 @@
return true;
}
-
- public override void Emit ()
- {
- if (OptAttributes != null) {
- EmitContext ec = new EmitContext (
- Parent, Location, null,
FieldBuilder.FieldType,
- ModFlags);
- OptAttributes.Emit (ec, this);
- }
-
- base.Emit ();
- }
}
//
Modified: trunk/mcs/gmcs/const.cs
===================================================================
--- trunk/mcs/gmcs/const.cs 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/const.cs 2005-03-22 10:01:15 UTC (rev 42077)
@@ -308,11 +308,6 @@
{
object value;
LookupConstantValue (out value);
-
- if (OptAttributes != null) {
- OptAttributes.Emit (const_ec, this);
- }
-
base.Emit ();
}
}
Modified: trunk/mcs/gmcs/cs-parser.jay
===================================================================
--- trunk/mcs/gmcs/cs-parser.jay 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/cs-parser.jay 2005-03-22 10:01:15 UTC (rev 42077)
@@ -937,11 +937,9 @@
int mod = (int) $2;
foreach (VariableDeclaration var in (ArrayList) $4){
- Location l = var.Location;
-
Field field = new Field (current_class, type, mod,
var.identifier,
var.expression_or_array_initializer,
- (Attributes) $1, l);
+ (Attributes) $1, var.Location);
if (RootContext.Documentation != null) {
field.DocComment = Lexer.consume_doc_comment ();
@@ -952,6 +950,27 @@
}
| opt_attributes
opt_modifiers
+ FIXED
+ type
+ fixed_variable_declarators
+ SEMICOLON
+ {
+ Expression type = (Expression) $4;
+ int mod = (int) $2;
+
+ foreach (VariableDeclaration var in (ArrayList) $5) {
+ FixedField field = new FixedField
(current_class, type, mod, var.identifier,
+
(Expression)var.expression_or_array_initializer, (Attributes) $1, var.Location);
+
+ if (RootContext.Documentation != null) {
+ field.DocComment =
Lexer.consume_doc_comment ();
+ Lexer.doc_state =
XmlCommentState.Allowed;
+ }
+ current_container.AddField (field);
+ }
+ }
+ | opt_attributes
+ opt_modifiers
VOID
variable_declarators
SEMICOLON {
@@ -959,6 +978,28 @@
}
;
+fixed_variable_declarators
+ : fixed_variable_declarator
+ {
+ ArrayList decl = new ArrayList (2);
+ decl.Add ($1);
+ $$ = decl;
+ }
+ | fixed_variable_declarators COMMA fixed_variable_declarator
+ {
+ ArrayList decls = (ArrayList) $1;
+ decls.Add ($3);
+ $$ = $1;
+ }
+ ;
+
+fixed_variable_declarator
+ : IDENTIFIER OPEN_BRACKET expression CLOSE_BRACKET
+ {
+ $$ = new VariableDeclaration ((string) $1, $3,
lexer.Location);
+ }
+ ;
+
variable_declarators
: variable_declarator
{
Modified: trunk/mcs/gmcs/ecore.cs
===================================================================
--- trunk/mcs/gmcs/ecore.cs 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/ecore.cs 2005-03-22 10:01:15 UTC (rev 42077)
@@ -3033,7 +3033,15 @@
if (is_volatile)
ig.Emit (OpCodes.Volatile);
- ig.Emit (OpCodes.Ldfld, FieldInfo);
+ IFixedBuffer ff =
AttributeTester.GetFixedBuffer (FieldInfo);
+ if (ff != null)
+ {
+ ig.Emit (OpCodes.Ldflda, FieldInfo);
+ ig.Emit (OpCodes.Ldflda, ff.Element);
+ }
+ else {
+ ig.Emit (OpCodes.Ldfld, FieldInfo);
+ }
}
if (leave_copy) {
Modified: trunk/mcs/gmcs/expression.cs
===================================================================
--- trunk/mcs/gmcs/expression.cs 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/expression.cs 2005-03-22 10:01:15 UTC (rev 42077)
@@ -671,7 +671,7 @@
public Indirection (Expression expr, Location l)
{
this.expr = expr;
- this.type = TypeManager.GetElementType (expr.Type);
+ type = TypeManager.HasElementType (expr.Type) ?
TypeManager.GetElementType (expr.Type) : expr.Type;
eclass = ExprClass.Variable;
loc = l;
}
@@ -3449,7 +3449,12 @@
{
Type op_type = left.Type;
ILGenerator ig = ec.ig;
- Type element = TypeManager.GetElementType (op_type);
+
+ // It must be either array or fixed buffer
+ Type element = TypeManager.HasElementType (op_type) ?
+ element = TypeManager.GetElementType (op_type) :
+ element = AttributeTester.GetFixedBuffer
(((FieldExpr)left).FieldInfo).ElementType;
+
int size = GetTypeSize (element);
Type rtype = right.Type;
@@ -7852,10 +7857,8 @@
return true;
}
- Expression MakePointerAccess (EmitContext ec)
+ Expression MakePointerAccess (EmitContext ec, Type t)
{
- Type t = Expr.Type;
-
if (t == TypeManager.void_ptr_type){
Error (242, "The array index operation is not
valid for void pointers");
return null;
@@ -7892,10 +7895,17 @@
if (t.IsArray)
return (new ArrayAccess (this, loc)).Resolve
(ec);
- else if (t.IsPointer)
- return MakePointerAccess (ec);
- else
- return (new IndexerAccess (this, loc)).Resolve
(ec);
+ if (t.IsPointer)
+ return MakePointerAccess (ec, Expr.Type);
+
+ FieldExpr fe = Expr as FieldExpr;
+ if (fe != null) {
+ IFixedBuffer ff =
AttributeTester.GetFixedBuffer (fe.FieldInfo);
+ if (ff != null) {
+ return MakePointerAccess (ec,
ff.ElementType);
+ }
+ }
+ return (new IndexerAccess (this, loc)).Resolve (ec);
}
public override Expression DoResolveLValue (EmitContext ec,
Expression right_side)
@@ -7906,10 +7916,24 @@
Type t = Expr.Type;
if (t.IsArray)
return (new ArrayAccess (this,
loc)).ResolveLValue (ec, right_side);
- else if (t.IsPointer)
- return MakePointerAccess (ec);
- else
- return (new IndexerAccess (this,
loc)).ResolveLValue (ec, right_side);
+
+ if (t.IsPointer)
+ return MakePointerAccess (ec, Expr.Type);
+
+ FieldExpr fe = Expr as FieldExpr;
+ if (fe != null) {
+ IFixedBuffer ff =
AttributeTester.GetFixedBuffer (fe.FieldInfo);
+ if (ff != null) {
+// TODO: not sure whether it is correct
+// if (!ec.InFixedInitializer) {
+// if (!ec.InFixedInitializer) {
+// Error (1666, "You cannot use
fixed sized buffers contained in unfixed expressions. Try using the fixed
statement.");
+// return null;
+// }
+ return MakePointerAccess (ec,
ff.ElementType);
+ }
+ }
+ return (new IndexerAccess (this, loc)).ResolveLValue
(ec, right_side);
}
public override void Emit (EmitContext ec)
@@ -8935,31 +8959,21 @@
}
}
- //
- // This class is used to represent the address of an array, used
- // only by the Fixed statement, this is like the C "&a [0]" construct.
- //
- public class ArrayPtr : Expression {
+ public class FixedBufferPtr: Expression {
Expression array;
-
- public ArrayPtr (Expression array, Location l)
+
+ public FixedBufferPtr (Expression array, Type array_type,
Location l)
{
- Type array_type = TypeManager.GetElementType
(array.Type);
-
this.array = array;
+ this.loc = l;
type = TypeManager.GetPointerType (array_type);
eclass = ExprClass.Value;
- loc = l;
}
- public override void Emit (EmitContext ec)
+ public override void Emit(EmitContext ec)
{
- ILGenerator ig = ec.ig;
-
array.Emit (ec);
- IntLiteral.EmitInt (ig, 0);
- ig.Emit (OpCodes.Ldelema, TypeManager.GetElementType
(array.Type));
}
public override Expression DoResolve (EmitContext ec)
@@ -8971,7 +8985,32 @@
}
}
+
//
+ // This class is used to represent the address of an array, used
+ // only by the Fixed statement, this generates "&a [0]" construct
+ // for fixed (char *pa = a)
+ //
+ public class ArrayPtr : FixedBufferPtr {
+ Type array_type;
+
+ public ArrayPtr (Expression array, Type array_type, Location l):
+ base (array, array_type, l)
+ {
+ this.array_type = array_type;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ base.Emit (ec);
+
+ ILGenerator ig = ec.ig;
+ IntLiteral.EmitInt (ig, 0);
+ ig.Emit (OpCodes.Ldelema, array_type);
+ }
+ }
+
+ //
// Used by the fixed statement
//
public class StringPtr : Expression {
Modified: trunk/mcs/gmcs/flowanalysis.cs
===================================================================
--- trunk/mcs/gmcs/flowanalysis.cs 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/flowanalysis.cs 2005-03-22 10:01:15 UTC (rev 42077)
@@ -1678,13 +1678,15 @@
if (type is TypeBuilder) {
TypeContainer tc =
TypeManager.LookupTypeContainer (type);
- ArrayList fields = tc.Fields;
+ ArrayList fields = null;
+ if (tc != null)
+ fields = tc.Fields;
ArrayList public_fields = new ArrayList
();
ArrayList non_public_fields = new
ArrayList ();
if (fields != null) {
- foreach (Field field in fields)
{
+ foreach (FieldMember field in
fields) {
if ((field.ModFlags &
Modifiers.STATIC) != 0)
continue;
if ((field.ModFlags &
Modifiers.PUBLIC) != 0)
Modified: trunk/mcs/gmcs/rootcontext.cs
===================================================================
--- trunk/mcs/gmcs/rootcontext.cs 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/rootcontext.cs 2005-03-22 10:01:15 UTC (rev 42077)
@@ -465,8 +465,12 @@
// If we have a <PrivateImplementationDetails> class,
close it
//
if (helper_classes != null){
- foreach (TypeBuilder type_builder in
helper_classes)
+ foreach (TypeBuilder type_builder in
helper_classes) {
+#if NET_2_0
+ type_builder.SetCustomAttribute
(TypeManager.compiler_generated_attr);
+#endif
type_builder.CreateType ();
+ }
}
attribute_types = null;
@@ -480,10 +484,11 @@
/// Used to register classes that need to be closed after all
the
/// user defined classes
/// </summary>
- public static void RegisterHelperClass (TypeBuilder
helper_class)
+ public static void RegisterCompilerGeneratedType (TypeBuilder
helper_class)
{
if (helper_classes == null)
helper_classes = new ArrayList ();
+
helper_classes.Add (helper_class);
}
@@ -692,7 +697,7 @@
TypeAttributes.NotPublic,
TypeManager.object_type);
- RegisterHelperClass (impl_details_class);
+ RegisterCompilerGeneratedType
(impl_details_class);
}
fb = impl_details_class.DefineInitializedData (
Modified: trunk/mcs/gmcs/statement.cs
===================================================================
--- trunk/mcs/gmcs/statement.cs 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/statement.cs 2005-03-22 10:01:15 UTC (rev 42077)
@@ -3312,16 +3312,82 @@
ArrayList declarators;
Statement statement;
Type expr_type;
- FixedData[] data;
+ Emitter[] data;
bool has_ret;
- struct FixedData {
- public bool is_object;
- public LocalInfo vi;
- public Expression expr;
- public Expression converted;
- }
+ abstract class Emitter
+ {
+ protected LocalInfo vi;
+ protected Expression converted;
+ protected Emitter (Expression expr, LocalInfo li)
+ {
+ converted = expr;
+ vi = li;
+ }
+
+ public abstract void Emit (EmitContext ec);
+ public abstract void EmitExit (ILGenerator ig);
+ }
+
+ class ExpressionEmitter: Emitter {
+ public ExpressionEmitter (Expression converted,
LocalInfo li) :
+ base (converted, li)
+ {
+ }
+
+ public override void Emit (EmitContext ec) {
+ //
+ // Store pointer in pinned location
+ //
+ converted.Emit (ec);
+ ec.ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+ }
+
+ public override void EmitExit (ILGenerator ig)
+ {
+ ig.Emit (OpCodes.Ldc_I4_0);
+ ig.Emit (OpCodes.Conv_U);
+ ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+ }
+ }
+
+ class StringEmitter: Emitter {
+ LocalBuilder pinned_string;
+ Location loc;
+
+ public StringEmitter (Expression expr, LocalInfo li,
Location loc):
+ base (expr, li)
+ {
+ this.loc = loc;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ pinned_string = TypeManager.DeclareLocalPinned
(ig, TypeManager.string_type);
+
+ converted.Emit (ec);
+ ig.Emit (OpCodes.Stloc, pinned_string);
+
+ Expression sptr = new StringPtr (pinned_string,
loc);
+ converted = Convert.ImplicitConversionRequired (
+ ec, sptr, vi.VariableType, loc);
+
+ if (converted == null)
+ return;
+
+ converted.Emit (ec);
+ ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+ }
+
+ public override void EmitExit(ILGenerator ig)
+ {
+ ig.Emit (OpCodes.Ldnull);
+ ig.Emit (OpCodes.Stloc, pinned_string);
+ }
+ }
+
public Fixed (Expression type, ArrayList decls, Statement stmt,
Location l)
{
this.type = type;
@@ -3350,7 +3416,7 @@
return false;
}
- data = new FixedData [declarators.Count];
+ data = new Emitter [declarators.Count];
if (!expr_type.IsPointer){
Report.Error (209, loc, "Variables in a fixed
statement must be pointers");
@@ -3407,10 +3473,7 @@
if (!TypeManager.VerifyUnManaged
(child.Type, loc))
return false;
- data [i].is_object = true;
- data [i].expr = e;
- data [i].converted = null;
- data [i].vi = vi;
+ data [i] = new ExpressionEmitter (e,
vi);
i++;
continue;
@@ -3438,17 +3501,14 @@
// and T* is implicitly convertible to
the
// pointer type given in the fixed
statement.
//
- ArrayPtr array_ptr = new ArrayPtr (e,
loc);
+ ArrayPtr array_ptr = new ArrayPtr (e,
array_type, loc);
Expression converted =
Convert.ImplicitConversionRequired (
ec, array_ptr, vi.VariableType,
loc);
if (converted == null)
return false;
- data [i].is_object = false;
- data [i].expr = e;
- data [i].converted = converted;
- data [i].vi = vi;
+ data [i] = new ExpressionEmitter
(converted, vi);
i++;
continue;
@@ -3458,14 +3518,30 @@
// Case 3: string
//
if (e.Type == TypeManager.string_type){
- data [i].is_object = false;
- data [i].expr = e;
- data [i].converted = null;
- data [i].vi = vi;
+ data [i] = new StringEmitter (e, vi,
loc);
i++;
continue;
}
+ // Case 4: fixed buffer
+ FieldExpr fe = e as FieldExpr;
+ if (fe != null) {
+ IFixedBuffer ff =
AttributeTester.GetFixedBuffer (fe.FieldInfo);
+ if (ff != null) {
+ Expression fixed_buffer_ptr =
new FixedBufferPtr (fe, ff.ElementType, loc);
+
+ Expression converted =
Convert.ImplicitConversionRequired (
+ ec, fixed_buffer_ptr,
vi.VariableType, loc);
+ if (converted == null)
+ return false;
+
+ data [i] = new
ExpressionEmitter (converted, vi);
+ i++;
+
+ continue;
+ }
+ }
+
//
// For other cases, flag a `this is already
fixed expression'
//
@@ -3495,60 +3571,8 @@
protected override void DoEmit (EmitContext ec)
{
- ILGenerator ig = ec.ig;
-
- LocalBuilder [] clear_list = new LocalBuilder
[data.Length];
-
for (int i = 0; i < data.Length; i++) {
- LocalInfo vi = data [i].vi;
-
- //
- // Case 1: & object.
- //
- if (data [i].is_object) {
- //
- // Store pointer in pinned location
- //
- data [i].expr.Emit (ec);
- ig.Emit (OpCodes.Stloc,
vi.LocalBuilder);
- clear_list [i] = vi.LocalBuilder;
- continue;
- }
-
- //
- // Case 2: Array
- //
- if (data [i].expr.Type.IsArray){
- //
- // Store pointer in pinned location
- //
- data [i].converted.Emit (ec);
-
- ig.Emit (OpCodes.Stloc,
vi.LocalBuilder);
- clear_list [i] = vi.LocalBuilder;
- continue;
- }
-
- //
- // Case 3: string
- //
- if (data [i].expr.Type ==
TypeManager.string_type){
- LocalBuilder pinned_string =
TypeManager.DeclareLocalPinned (ig, TypeManager.string_type);
- clear_list [i] = pinned_string;
-
- data [i].expr.Emit (ec);
- ig.Emit (OpCodes.Stloc, pinned_string);
-
- Expression sptr = new StringPtr
(pinned_string, loc);
- Expression converted =
Convert.ImplicitConversionRequired (
- ec, sptr, vi.VariableType, loc);
-
- if (converted == null)
- continue;
-
- converted.Emit (ec);
- ig.Emit (OpCodes.Stloc,
vi.LocalBuilder);
- }
+ data [i].Emit (ec);
}
statement.Emit (ec);
@@ -3556,18 +3580,13 @@
if (has_ret)
return;
+ ILGenerator ig = ec.ig;
+
//
// Clear the pinned variable
//
for (int i = 0; i < data.Length; i++) {
- if (data [i].is_object || data
[i].expr.Type.IsArray) {
- ig.Emit (OpCodes.Ldc_I4_0);
- ig.Emit (OpCodes.Conv_U);
- ig.Emit (OpCodes.Stloc, clear_list [i]);
- } else if (data [i].expr.Type ==
TypeManager.string_type){
- ig.Emit (OpCodes.Ldnull);
- ig.Emit (OpCodes.Stloc, clear_list [i]);
- }
+ data [i].EmitExit (ig);
}
}
}
Modified: trunk/mcs/gmcs/typemanager.cs
===================================================================
--- trunk/mcs/gmcs/typemanager.cs 2005-03-22 09:59:34 UTC (rev 42076)
+++ trunk/mcs/gmcs/typemanager.cs 2005-03-22 10:01:15 UTC (rev 42077)
@@ -99,6 +99,14 @@
static public Type field_offset_attribute_type;
static public Type security_attr_type;
+ ///
+ /// .NET 2.0
+ ///
+#if NET_2_0
+ static internal Type compiler_generated_attr_type;
+ static internal Type fixed_buffer_attr_type;
+#endif
+
//
// An empty array of types
//
@@ -184,10 +192,18 @@
static public ConstructorInfo void_decimal_ctor_five_args;
static public ConstructorInfo void_decimal_ctor_int_arg;
static public ConstructorInfo unverifiable_code_ctor;
- static public ConstructorInfo invalid_operation_ctor;
static public ConstructorInfo default_member_ctor;
static public ConstructorInfo decimal_constant_attribute_ctor;
-
+ static internal ConstructorInfo struct_layout_attribute_ctor;
+
+ ///
+ /// A new in C# 2.0
+ ///
+#if NET_2_0
+ static internal CustomAttributeBuilder compiler_generated_attr;
+ static internal ConstructorInfo fixed_buffer_attr_ctor;
+#endif
+
// <remarks>
// Holds the Array of Assemblies that have been loaded
// (either because it is the default or the user used the
@@ -1164,6 +1180,13 @@
InitGenericCoreTypes ();
//
+ // .NET 2.0
+ //
+#if NET_2_0
+ compiler_generated_attr_type = CoreLookupType
("System.Runtime.CompilerServices.CompilerGeneratedAttribute");
+ fixed_buffer_attr_type = CoreLookupType
("System.Runtime.CompilerServices.FixedBufferAttribute");
+#endif
+ //
// When compiling corlib, store the "real" types here.
//
if (!RootContext.StdLib) {
@@ -1375,23 +1398,27 @@
//
// Attributes
//
- cons_param_array_attribute = GetConstructor (
- param_array_type, void_arg);
+ cons_param_array_attribute = GetConstructor (param_array_type,
void_arg);
+ unverifiable_code_ctor = GetConstructor
(unverifiable_code_type, void_arg);
+ default_member_ctor = GetConstructor (default_member_type,
string_);
- unverifiable_code_ctor = GetConstructor (
- unverifiable_code_type, void_arg);
+ Type[] short_arg = { short_type };
+ struct_layout_attribute_ctor = GetConstructor
(struct_layout_attribute_type, short_arg);
decimal_constant_attribute_ctor = GetConstructor
(decimal_constant_attribute_type, new Type []
{ byte_type, byte_type, uint32_type, uint32_type,
uint32_type } );
- default_member_ctor = GetConstructor (default_member_type,
string_);
//
- // InvalidOperationException
+ // .NET 2.0 types
//
- invalid_operation_ctor = GetConstructor (
- invalid_operation_exception_type, void_arg);
+#if NET_2_0
+ compiler_generated_attr = new CustomAttributeBuilder (
+ GetConstructor (compiler_generated_attr_type,
void_arg), new object[0]);
+ Type[] type_int_arg = { type_type, int32_type };
+ fixed_buffer_attr_ctor = GetConstructor
(fixed_buffer_attr_type, type_int_arg);
+#endif
// Object
object_ctor = GetConstructor (object_type, void_arg);
@@ -1805,6 +1832,14 @@
}
/// <summary>
+ /// This method is not implemented by MS runtime for dynamic types
+ /// </summary>
+ public static bool HasElementType (Type t)
+ {
+ return t.IsArray || t.IsPointer || t.IsByRef;
+ }
+
+ /// <summary>
/// Returns the User Defined Types
/// </summary>
public static ArrayList UserTypes {
@@ -2074,7 +2109,7 @@
if (tc.Fields == null)
return true;
- foreach (Field field in tc.Fields) {
+ foreach (FieldMember field in tc.Fields) {
if (field.FieldBuilder == null ||
field.FieldBuilder.IsStatic)
continue;
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches