2 Copyright (C) 2008-2012 Jeroen Frijters
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
25 using System.Collections.Generic;
26 using System.Runtime.CompilerServices;
27 using IKVM.Reflection.Metadata;
28 using IKVM.Reflection.Writer;
30 namespace IKVM.Reflection.Emit
32 public sealed class FieldBuilder : FieldInfo
34 private readonly TypeBuilder typeBuilder;
35 private readonly string name;
36 private readonly int pseudoToken;
37 private FieldAttributes attribs;
38 private readonly int nameIndex;
39 private readonly int signature;
40 private readonly FieldSignature fieldSig;
42 internal FieldBuilder(TypeBuilder type, string name, Type fieldType, CustomModifiers customModifiers, FieldAttributes attribs)
44 this.typeBuilder = type;
46 this.pseudoToken = type.ModuleBuilder.AllocPseudoToken();
47 this.nameIndex = type.ModuleBuilder.Strings.Add(name);
48 this.fieldSig = FieldSignature.Create(fieldType, customModifiers);
49 ByteBuffer sig = new ByteBuffer(5);
50 fieldSig.WriteSig(this.typeBuilder.ModuleBuilder, sig);
51 this.signature = this.typeBuilder.ModuleBuilder.Blobs.Add(sig);
52 this.attribs = attribs;
53 this.typeBuilder.ModuleBuilder.Field.AddVirtualRecord();
56 public void SetConstant(object defaultValue)
58 attribs |= FieldAttributes.HasDefault;
59 typeBuilder.ModuleBuilder.AddConstant(pseudoToken, defaultValue);
62 public override object GetRawConstantValue()
64 if (!typeBuilder.IsCreated())
66 // the .NET FieldBuilder doesn't support this method
67 // (since we dont' have a different FieldInfo object after baking, we will support it once we're baked)
68 throw new NotSupportedException();
70 return typeBuilder.Module.Constant.GetRawConstantValue(typeBuilder.Module, GetCurrentToken());
73 public void __SetDataAndRVA(byte[] data)
75 SetDataAndRvaImpl(data, typeBuilder.ModuleBuilder.initializedData, 0);
78 public void __SetReadOnlyDataAndRVA(byte[] data)
80 SetDataAndRvaImpl(data, typeBuilder.ModuleBuilder.methodBodies, unchecked((int)0x80000000));
83 private void SetDataAndRvaImpl(byte[] data, ByteBuffer bb, int readonlyMarker)
85 attribs |= FieldAttributes.HasFieldRVA;
86 FieldRVATable.Record rec = new FieldRVATable.Record();
88 rec.RVA = bb.Position + readonlyMarker;
89 rec.Field = pseudoToken;
90 typeBuilder.ModuleBuilder.FieldRVA.AddRecord(rec);
94 public override void __GetDataFromRVA(byte[] data, int offset, int length)
96 throw new NotImplementedException();
99 public override int __FieldRVA
101 get { throw new NotImplementedException(); }
104 public override bool __TryGetFieldOffset(out int offset)
106 int pseudoTokenOrIndex = pseudoToken;
107 if (typeBuilder.ModuleBuilder.IsSaved)
109 pseudoTokenOrIndex = typeBuilder.ModuleBuilder.ResolvePseudoToken(pseudoToken) & 0xFFFFFF;
111 foreach (int i in this.Module.FieldLayout.Filter(pseudoTokenOrIndex))
113 offset = this.Module.FieldLayout.records[i].Offset;
120 public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
122 SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
125 public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
127 Universe u = this.Module.universe;
128 if (customBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_FieldOffsetAttribute)
130 customBuilder = customBuilder.DecodeBlob(this.Module.Assembly);
131 SetOffset((int)customBuilder.GetConstructorArgument(0));
133 else if (customBuilder.Constructor.DeclaringType == u.System_Runtime_InteropServices_MarshalAsAttribute)
135 FieldMarshal.SetMarshalAsAttribute(typeBuilder.ModuleBuilder, pseudoToken, customBuilder);
136 attribs |= FieldAttributes.HasFieldMarshal;
138 else if (customBuilder.Constructor.DeclaringType == u.System_NonSerializedAttribute)
140 attribs |= FieldAttributes.NotSerialized;
142 else if (customBuilder.Constructor.DeclaringType == u.System_Runtime_CompilerServices_SpecialNameAttribute)
144 attribs |= FieldAttributes.SpecialName;
148 typeBuilder.ModuleBuilder.SetCustomAttribute(pseudoToken, customBuilder);
152 public void SetOffset(int iOffset)
154 FieldLayoutTable.Record rec = new FieldLayoutTable.Record();
155 rec.Offset = iOffset;
156 rec.Field = pseudoToken;
157 typeBuilder.ModuleBuilder.FieldLayout.AddRecord(rec);
160 public override FieldAttributes Attributes
162 get { return attribs; }
165 public override Type DeclaringType
167 get { return typeBuilder.IsModulePseudoType ? null : typeBuilder; }
170 public override string Name
175 public override int MetadataToken
177 get { return pseudoToken; }
180 public override Module Module
182 get { return typeBuilder.Module; }
185 public FieldToken GetToken()
187 return new FieldToken(pseudoToken);
190 internal void WriteFieldRecords(MetadataWriter mw)
192 mw.Write((short)attribs);
193 mw.WriteStringIndex(nameIndex);
194 mw.WriteBlobIndex(signature);
197 internal void FixupToken(int token)
199 typeBuilder.ModuleBuilder.RegisterTokenFixup(this.pseudoToken, token);
202 internal override FieldSignature FieldSignature
204 get { return fieldSig; }
207 internal override int ImportTo(ModuleBuilder other)
209 return other.ImportMethodOrField(typeBuilder, name, fieldSig);
212 internal override int GetCurrentToken()
214 if (typeBuilder.ModuleBuilder.IsSaved)
216 return typeBuilder.ModuleBuilder.ResolvePseudoToken(pseudoToken);
224 internal override bool IsBaked
226 get { return typeBuilder.IsBaked; }