public override IReadOnlyDictionary <IField, ValueOrRefObject> GetFieldValues(ValueOrRefObject value) { var t = value.Object.GetType(); var results = new Dictionary <IField, ValueOrRefObject>(); foreach (var field in t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { var flameField = Assembly.Resolve(Assembly.Definition.MainModule.ImportReference(field)); var val = field.GetValue(value.Object); results[flameField] = flameField.FieldType.IsPointerType(PointerKind.Box) ? ValueOrRefObject.Reference(val) : ValueOrRefObject.Value(val); } return(results); }
public override bool TryEncodePrimitive(ValueOrRefObject value, MirrorBufferPtr buffer) { var val = value.Object; if (val == null) { Marshal.WriteIntPtr(buffer.HostBuffer, IntPtr.Zero); return(true); } else if (val is IntPtr) { Marshal.WriteIntPtr(buffer.HostBuffer, (IntPtr)val); return(true); } else if (val is byte) { Marshal.WriteByte(buffer.HostBuffer, (byte)val); return(true); } else if (val is sbyte) { Marshal.WriteByte(buffer.HostBuffer, (byte)(sbyte)val); return(true); } else if (val is short) { Marshal.WriteInt16(buffer.HostBuffer, (short)val); return(true); } else if (val is ushort) { Marshal.WriteInt16(buffer.HostBuffer, (short)(ushort)val); return(true); } else if (val is int) { Marshal.WriteInt32(buffer.HostBuffer, (int)val); return(true); } else if (val is uint) { Marshal.WriteInt32(buffer.HostBuffer, (int)(uint)val); return(true); } else if (val is long) { Marshal.WriteInt64(buffer.HostBuffer, (long)val); return(true); } else if (val is ulong) { Marshal.WriteInt64(buffer.HostBuffer, (long)(ulong)val); return(true); } // TODO: handle other primitive types, e.g., floating-point numbers and delegates. else if (val is Array) { var arr = (Array)val; var arrType = val.GetType(); var elemType = ToClr(arrType.GetElementType()); bool refElements = false; if (elemType.IsReferenceType()) { elemType = elemType.MakePointerType(PointerKind.Box); refElements = true; } var elemSize = SizeOf(elemType); var totalElements = arr.Length; // Allocate a buffer for the array. var buf = AllocateBuffer(MetadataSize + arr.Rank * 8 + totalElements * elemSize); // Initialize the array's vtable. InitializeObject(buf, ToClr(arrType)); buf = IndexPointer(buf, MetadataSize); // Map the array to its encoded version. RegisterEncoded(value, buf); EncodePointer(buffer, buf); // Encode array dimensions. // FIXME: this logic is directly dependent on the GC interface. Can we abstract // over this in a reasonable way at the Flame.Llvm level? for (int i = 0; i < arr.Rank; i++) { Marshal.WriteInt64(buf.HostBuffer, arr.GetLongLength(i)); buf = IndexPointer(buf, 8); } // Encode array contents. foreach (var item in arr) { var elem = refElements ? ValueOrRefObject.Reference(item) : ValueOrRefObject.Value(item); Encode(elem, buf); buf = IndexPointer(buf, elemSize); } return(true); } else { return(false); } }
public override ValueOrRefObject LoadBoxPointer(ValueOrRefObject pointer) { return(ValueOrRefObject.Value(pointer.Object)); }