+2005-02-11 Marek Safar <marek.safar@seznam.cz>
+
+ 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 <miguel@novell.com>
* anonymous.cs (CaptureContext): Track whether `this' has been
public void CloseTypes ()
{
- RootContext.RegisterHelperClass (ScopeTypeBuilder);
+ RootContext.RegisterCompilerGeneratedType (ScopeTypeBuilder);
foreach (ScopeInfo si in children)
si.CloseTypes ();
}
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 ()
{
}
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 ()
{
interfaces.Add (iface);
}
- public void AddField (Field field)
+ public void AddField (FieldMember field)
{
if (!AddToMemberContainer (field))
return;
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;
}
if (fields != null)
- foreach (Field f in fields)
+ foreach (FieldMember f in fields)
f.Emit ();
if (events != null){
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;
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;
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 ());
}
}
}
+ 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.
//
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 ();
- }
}
//
{
object value;
LookupConstantValue (out value);
-
- if (OptAttributes != null) {
- OptAttributes.Emit (const_ec, this);
- }
-
base.Emit ();
}
}
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 ();
current_container.AddField (field);
}
}
+ | 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
}
;
+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
{
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) {
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;
}
{
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;
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;
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)
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)
}
}
- //
- // 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)
- {
- Type array_type = TypeManager.GetElementType (array.Type);
+ public FixedBufferPtr (Expression array, Type array_type, Location l)
+ {
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)
}
}
+
+ //
+ // 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
//
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)
// 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;
/// 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);
}
TypeAttributes.NotPublic,
TypeManager.object_type);
- RegisterHelperClass (impl_details_class);
+ RegisterCompilerGeneratedType (impl_details_class);
}
fb = impl_details_class.DefineInitializedData (
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)
{
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");
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;
// 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;
// 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'
//
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);
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);
}
}
}
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
//
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
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.
//
//
// 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);
return TypeToCoreType (t.GetElementType ());
}
+ /// <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>
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;