//
using System;
-using System.Diagnostics;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
static Assembly orig_sec_assembly;
public static readonly object[] EmptyObject = new object [0];
- IList<KeyValuePair<MemberExpr, NamedArgument>> named_values;
+ List<KeyValuePair<MemberExpr, NamedArgument>> named_values;
// Cache for parameter-less attributes
static Dictionary<TypeSpec, MethodSpec> att_cache;
this.nameEscaped = nameEscaped;
}
+ void AddModuleCharSet (ResolveContext rc)
+ {
+ const string dll_import_char_set = "CharSet";
+
+ //
+ // Only when not customized by user
+ //
+ if (HasField (dll_import_char_set))
+ return;
+
+ if (TypeManager.interop_charset == null) {
+ TypeManager.interop_charset = TypeManager.CoreLookupType (rc.Compiler, "System.Runtime.InteropServices", "CharSet", MemberKind.Enum, true);
+
+ if (TypeManager.interop_charset == null)
+ return;
+ }
+
+ if (NamedArguments == null)
+ NamedArguments = new Arguments (1);
+
+ var value = Constant.CreateConstant (rc, TypeManager.interop_charset, rc.CurrentMemberDefinition.Module.DefaultCharSet, Location);
+ NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value));
+ }
+
public Attribute Clone ()
{
Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
// we use @target field as a list of targets. The attribute
// has to be resolved only once but emitted for each target.
//
- public virtual void AttachTo (Attributable target, IMemberContext context)
+ public void AttachTo (Attributable target, IMemberContext context)
{
if (this.targets == null) {
this.targets = new Attributable[] { target };
get { return expression.Name; }
}
- void ApplyModuleCharSet (ResolveContext rc)
- {
- if (Type != context.Compiler.PredefinedAttributes.DllImport)
- return;
-
- if (!RootContext.ToplevelTypes.HasDefaultCharSet)
- return;
-
- const string CharSetEnumMember = "CharSet";
- if (NamedArguments == null) {
- NamedArguments = new Arguments (1);
- } else {
- foreach (NamedArgument a in NamedArguments) {
- if (a.Name == CharSetEnumMember)
- return;
- }
- }
-
- var char_set = rc.Compiler.MetaImporter.ImportType (typeof (CharSet)); // TODO: typeof
- NamedArguments.Add (new NamedArgument (CharSetEnumMember, loc,
- Constant.CreateConstant (rc, char_set, RootContext.ToplevelTypes.DefaultCharSet, Location)));
- }
-
public Report Report {
get { return context.Compiler.Report; }
}
return null;
}
- ApplyModuleCharSet (rc);
+ //
+ // Add [module: DefaultCharSet] to all DllImport import attributes
+ //
+ if (Type == context.Compiler.PredefinedAttributes.DllImport && rc.CurrentMemberDefinition.Module.HasDefaultCharSet) {
+ AddModuleCharSet (rc);
+ }
if (NamedArguments != null && !ResolveNamedArguments (rc)) {
return null;
AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ());
- var field = GetPropertyValue ("AllowMultiple") as BoolConstant;
+ var field = GetNamedValue ("AllowMultiple") as BoolConstant;
if (field != null)
usage_attribute.AllowMultiple = field.Value;
- field = GetPropertyValue ("Inherited") as BoolConstant;
+ field = GetNamedValue ("Inherited") as BoolConstant;
if (field != null)
usage_attribute.Inherited = field.Value;
case "field": Target = AttributeTargets.Field; return true;
case "method": Target = AttributeTargets.Method; return true;
case "property": Target = AttributeTargets.Property; return true;
+ case "module": Target = AttributeTargets.Module; return true;
}
throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
}
System.Security.Permissions.SecurityAction GetSecurityActionValue ()
{
- return (SecurityAction) ((Constant) PosArguments[0].Expr).GetTypedValue ();
+ return (SecurityAction) ((Constant) PosArguments[0].Expr).GetValue ();
}
/// <summary>
if (orig_assembly_type == null) {
args = new object[PosArguments.Count];
for (int j = 0; j < args.Length; ++j) {
- args[j] = ((Constant) PosArguments[j].Expr).GetTypedValue ();
+ args[j] = ((Constant) PosArguments[j].Expr).GetValue ();
}
sa = (SecurityAttribute) Activator.CreateInstance (Type.GetMetaInfo (), args);
if (named_values != null) {
for (int i = 0; i < named_values.Count; ++i) {
PropertyInfo pi = ((PropertyExpr) named_values[i].Key).PropertyInfo.MetaInfo;
- pi.SetValue (sa, ((Constant) named_values [i].Value.Expr).GetTypedValue (), null);
+ pi.SetValue (sa, ((Constant) named_values [i].Value.Expr).GetValue (), null);
}
}
} else {
// TODO: pi can be null
PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name);
- pi.SetValue (sa, ((Constant) named_values[i].Value.Expr).GetTypedValue (), null);
+ pi.SetValue (sa, ((Constant) named_values[i].Value.Expr).GetValue (), null);
}
}
}
ps.AddPermission (perm);
}
- public Constant GetPropertyValue (string name)
+ public Constant GetNamedValue (string name)
{
if (named_values == null)
return null;
return false;
}
- public bool IsInternalMethodImplAttribute {
- get {
- if (Type != context.Compiler.PredefinedAttributes.MethodImpl)
- return false;
-
- MethodImplOptions options;
- if (PosArguments[0].Type.GetMetaInfo () != typeof (MethodImplOptions))
- options = (MethodImplOptions) System.Enum.ToObject (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ());
- else
- options = (MethodImplOptions) ((Constant) PosArguments [0].Expr).GetValue ();
-
- return (options & MethodImplOptions.InternalCall) != 0;
+ //
+ // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
+ //
+ public bool IsInternalCall ()
+ {
+ MethodImplOptions options = 0;
+ if (PosArguments.Count == 1) {
+ options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
+ } else if (HasField ("Value")) {
+ var named = GetNamedValue ("Value");
+ options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
}
+
+ return (options & MethodImplOptions.InternalCall) != 0;
}
- public LayoutKind GetLayoutKindValue ()
+ //
+ // Returns true for StructLayoutAttribute with LayoutKind.Explicit value
+ //
+ public bool IsExplicitLayoutKind ()
{
- if (!RootContext.StdLib || PosArguments[0].Type.GetMetaInfo () != typeof (LayoutKind))
- return (LayoutKind) System.Enum.ToObject (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ());
+ if (PosArguments.Count != 1)
+ return false;
- return (LayoutKind) ((Constant) PosArguments[0].Expr).GetValue ();
+ var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
+ return value == LayoutKind.Explicit;
}
public Constant GetParameterDefaultValue (out TypeSpec type)
na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
}
} else {
- encoder.Stream.Write ((ushort) 0);
+ encoder.EncodeEmptyNamedArguments ();
}
byte[] cdata = encoder.ToArray ();
{
this.ns = ns;
}
-
- public override void AttachTo (Attributable target, IMemberContext context)
- {
- if (ExplicitTarget == "assembly") {
- base.AttachTo (CodeGen.Assembly, context);
- return;
- }
-
- if (ExplicitTarget == "module") {
- base.AttachTo (RootContext.ToplevelTypes, context);
- return;
- }
-
- throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
- }
void Enter ()
{
}
public Attribute Search (PredefinedAttribute t)
+ {
+ return Search (null, t);
+ }
+
+ public Attribute Search (string explicitTarget, PredefinedAttribute t)
{
foreach (Attribute a in Attrs) {
+ if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
+ continue;
+
if (a.ResolveType () == t)
return a;
}
TypeParameter = 1 << 1
}
+ const ushort Version = 1;
+
+ public static readonly byte[] Empty;
+
public readonly BinaryWriter Stream;
+ static AttributeEncoder ()
+ {
+ Empty = new byte[4];
+ Array.Copy (BitConverter.GetBytes (Version), Empty, 2);
+ }
+
public AttributeEncoder (bool empty)
{
if (empty) {
}
Stream = new BinaryWriter (new MemoryStream ());
- const ushort version = 1;
- Stream.Write (version);
+ Stream.Write (Version);
+ }
+
+ public void Encode (byte value)
+ {
+ Stream.Write (value);
+ }
+
+ public void Encode (short value)
+ {
+ Stream.Write (value);
+ }
+
+ public void Encode (int value)
+ {
+ Stream.Write (value);
+ }
+
+ public void Encode (uint value)
+ {
+ Stream.Write (value);
}
public void Encode (string value)
{
- if (value == null)
- throw new ArgumentNullException ();
+ if (value == null) {
+ Stream.Write ((byte) 0xFF);
+ return;
+ }
var buf = Encoding.UTF8.GetBytes(value);
WriteCompressedValue (buf.Length);
Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
}
+ //
+ // Encodes single property named argument per call
+ //
+ public void EncodeNamedPropertyArgument (PropertySpec property, Constant value)
+ {
+ Stream.Write ((ushort) 1); // length
+ Stream.Write ((byte) 0x54); // property
+ Encode (property.MemberType);
+ Encode (property.Name);
+ value.EncodeAttributeValue (null, this, property.MemberType);
+ }
+
+ //
+ // Encodes single field named argument per call
+ //
+ public void EncodeNamedFieldArgument (FieldSpec field, Constant value)
+ {
+ Stream.Write ((ushort) 1); // length
+ Stream.Write ((byte) 0x53); // field
+ Encode (field.MemberType);
+ Encode (field.Name);
+ value.EncodeAttributeValue (null, this, field.MemberType);
+ }
+
+ public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
+ {
+ Stream.Write ((ushort) members.Length);
+
+ for (int i = 0; i < members.Length; ++i)
+ {
+ var member = members[i];
+
+ if (member.Kind == MemberKind.Field)
+ Stream.Write ((byte) 0x53);
+ else if (member.Kind == MemberKind.Property)
+ Stream.Write ((byte) 0x54);
+ else
+ throw new NotImplementedException (member.Kind.ToString ());
+
+ Encode (member.MemberType);
+ Encode (member.Name);
+ values [i].EncodeAttributeValue (null, this, member.MemberType);
+ }
+ }
+
+ public void EncodeEmptyNamedArguments ()
+ {
+ Stream.Write ((ushort) 0);
+ }
+
void WriteCompressedValue (int value)
{
if (value < 0x80) {
return result;
}
- public static void VerifyModulesClsCompliance (CompilerContext ctx)
- {
- Module[] modules = ctx.GlobalRootNamespace.Modules;
- if (modules == null)
- return;
-
- // The first module is generated assembly
- for (int i = 1; i < modules.Length; ++i) {
- Module module = modules [i];
- if (!GetClsCompliantAttributeValue (module, null)) {
- ctx.Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
- "to match the assembly", module.Name);
- return;
- }
- }
- }
-
- static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider, Assembly a)
- {
- object[] cls_attr = attribute_provider.GetCustomAttributes (typeof (CLSCompliantAttribute), false);
- if (cls_attr.Length == 0) {
- if (a == null)
- return false;
-
- return GetClsCompliantAttributeValue (a, null);
- }
-
- return ((CLSCompliantAttribute)cls_attr [0]).IsCompliant;
- }
-
/// <summary>
/// Common method for Obsolete error/warning reporting.
/// </summary>
public readonly PredefinedAttribute AttributeUsage;
public readonly PredefinedAttribute DefaultParameterValue;
public readonly PredefinedAttribute OptionalParameter;
+ public readonly PredefinedAttribute UnverifiableCode;
// New in .NET 2.0
public readonly PredefinedAttribute DefaultCharset;
// Optional types which are used as types and for member lookup
//
public readonly PredefinedAttribute DefaultMember;
- public readonly PredefinedAttribute DecimalConstant;
+ public readonly PredefinedDecimalAttribute DecimalConstant;
public readonly PredefinedAttribute StructLayout;
public readonly PredefinedAttribute FieldOffset;
AttributeUsage = new PredefinedAttribute ("System", "AttributeUsageAttribute");
DefaultParameterValue = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
OptionalParameter = new PredefinedAttribute ("System.Runtime.InteropServices", "OptionalAttribute");
+ UnverifiableCode = new PredefinedAttribute ("System.Security", "UnverifiableCodeAttribute");
DefaultCharset = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
TypeForwarder = new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
Dynamic = new PredefinedDynamicAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
DefaultMember = new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
- DecimalConstant = new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
+ DecimalConstant = new PredefinedDecimalAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
StructLayout = new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
FieldOffset = new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
}
public class PredefinedAttribute
{
protected TypeSpec type;
- CustomAttributeBuilder cab;
- MethodSpec ctor;
+ protected MethodSpec ctor;
readonly string ns, name;
CompilerContext compiler;
+ List<FieldSpec> fields;
+ List<PropertySpec> properties;
static readonly TypeSpec NotFound = InternalType.Null;
this.name = name;
}
+ #region Properties
+
+ public MethodSpec Constructor {
+ get {
+ return ctor;
+ }
+ }
+
+ public bool IsDefined {
+ get {
+ return type != null && type != NotFound;
+ }
+ }
+
+ public TypeSpec Type {
+ get {
+ return type;
+ }
+ }
+
+ #endregion
+
+
public static bool operator == (TypeSpec type, PredefinedAttribute pa)
{
return type == pa.type;
return type != pa.type;
}
- public ConstructorInfo Constructor {
- get { return ctor == null ? null : (ConstructorInfo) ctor.GetMetaInfo (); }
- }
-
public override int GetHashCode ()
{
return base.GetHashCode ();
public void EmitAttribute (ConstructorBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
public void EmitAttribute (MethodBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
public void EmitAttribute (PropertyBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
public void EmitAttribute (FieldBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
+ }
+
+ public void EmitAttribute (FieldBuilder builder, AttributeEncoder argsEncoded)
+ {
+ builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
}
public void EmitAttribute (TypeBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
+ }
+
+ public void EmitAttribute (TypeBuilder builder, AttributeEncoder argsEncoded)
+ {
+ builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
}
public void EmitAttribute (AssemblyBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
+ }
+
+ public void EmitAttribute (ModuleBuilder builder)
+ {
+ if (ResolveBuilder ())
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
public void EmitAttribute (ParameterBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
- public bool IsDefined {
- get { return type != null && type != NotFound; }
+ public void EmitAttribute (ParameterBuilder builder, AttributeEncoder argsEncoded)
+ {
+ builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
+ }
+
+ ConstructorInfo GetCtorMetaInfo ()
+ {
+ return (ConstructorInfo) ctor.GetMetaInfo ();
+ }
+
+ public FieldSpec GetField (string name, TypeSpec memberType, Location loc)
+ {
+ FieldSpec spec;
+ if (fields != null) {
+ spec = fields.Find (l => l.Name == name);
+ } else {
+ spec = null;
+ }
+
+ if (spec == null) {
+ spec = TypeManager.GetPredefinedField (type, name, loc, memberType);
+
+ if (spec != null) {
+ if (fields == null) {
+ fields = new List<FieldSpec> ();
+ }
+
+ fields.Add (spec);
+ }
+ }
+
+ return spec;
+ }
+
+ public PropertySpec GetProperty (string name, TypeSpec memberType, Location loc)
+ {
+ PropertySpec spec;
+
+ if (properties != null) {
+ spec = properties.Find (l => l.Name == name);
+ } else {
+ spec = null;
+ }
+
+ if (spec == null) {
+ spec = TypeManager.GetPredefinedProperty (type, name, loc, memberType);
+
+ if (spec != null) {
+ if (properties == null) {
+ properties = new List<PropertySpec> ();
+ }
+
+ properties.Add (spec);
+ }
+ }
+
+ return spec;
}
public void Initialize (CompilerContext ctx, bool canFail)
return true;
}
- bool ResolveBuilder ()
+ public bool ResolveBuilder ()
{
- if (cab != null)
+ if (ctor != null)
return true;
//
if (!Resolve (true))
return false;
- var ci = TypeManager.GetPredefinedConstructor (type, Location.Null, TypeSpec.EmptyTypes);
- if (ci == null)
- return false;
-
- cab = new CustomAttributeBuilder ((ConstructorInfo) ci.GetMetaInfo (), new object[0]);
- return true;
+ ctor = TypeManager.GetPredefinedConstructor (type, Location.Null, TypeSpec.EmptyTypes);
+ return ctor != null;
}
public bool ResolveConstructor (Location loc, params TypeSpec[] argType)
ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
return ctor != null;
}
+ }
- public TypeSpec Type {
- get { return type; }
+ public class PredefinedDecimalAttribute : PredefinedAttribute
+ {
+ public PredefinedDecimalAttribute (string ns, string name)
+ : base (ns, name)
+ {
+ }
+
+ public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
+ {
+ if (!Resolve (false))
+ return;
+
+ if (ctor == null && !ResolveConstructor (loc, TypeManager.byte_type, TypeManager.byte_type, TypeManager.uint32_type, TypeManager.uint32_type, TypeManager.uint32_type))
+ return;
+
+ int[] bits = decimal.GetBits (value);
+ AttributeEncoder encoder = new AttributeEncoder (false);
+ encoder.Encode ((byte) (bits[3] >> 16));
+ encoder.Encode ((byte) (bits[3] >> 31));
+ encoder.Encode ((uint) bits[2]);
+ encoder.Encode ((uint) bits[1]);
+ encoder.Encode ((uint) bits[0]);
+ encoder.EncodeEmptyNamedArguments ();
+
+ EmitAttribute (builder, encoder);
+ }
+
+ public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
+ {
+ if (!Resolve (false))
+ return;
+
+ if (ctor == null && !ResolveConstructor (loc, TypeManager.byte_type, TypeManager.byte_type, TypeManager.uint32_type, TypeManager.uint32_type, TypeManager.uint32_type))
+ return;
+
+ int[] bits = decimal.GetBits (value);
+ AttributeEncoder encoder = new AttributeEncoder (false);
+ encoder.Encode ((byte) (bits[3] >> 16));
+ encoder.Encode ((byte) (bits[3] >> 31));
+ encoder.Encode ((uint) bits[2]);
+ encoder.Encode ((uint) bits[1]);
+ encoder.Encode ((uint) bits[0]);
+ encoder.EncodeEmptyNamedArguments ();
+
+ EmitAttribute (builder, encoder);
}
}