-
Notifications
You must be signed in to change notification settings - Fork 1
/
ObjectCreation.cs
160 lines (145 loc) · 8.68 KB
/
ObjectCreation.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
using System;
using System.CodeDom;
using System.Reflection;
using System.Reflection.Emit;
using JetBrains.Annotations;
namespace ILGeneratorExtensions
{
/// <summary>
/// Contains extension methods for the creation of objects
/// </summary>
[PublicAPI]
public static class ObjectCreation
{
/// <summary>
/// Creates a new object or instance of a value type, calling the given constructor (and popping the requisite arguments from the evaluation stack) and pushing the reference or value (respectively) onto the evaluation stack
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="constructor">The constructor to call</param>
[PublicAPI]
public static ILGenerator NewObject(this ILGenerator generator, ConstructorInfo constructor) => generator.FluentEmit(OpCodes.Newobj, constructor);
/// <summary>
/// Creates a new object or instance of a value type, calling the default constructor and pushing the reference or value (respectively) onto the evaluation stack
/// </summary>
/// <typeparam name="T">The type of object/value type to create</typeparam>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator NewObject<T>(this ILGenerator generator) where T : new()
=> generator.FluentEmit(OpCodes.Newobj, typeof (T).GetConstructor(Type.EmptyTypes));
/// <summary>
/// Pops the address of the storage location of a value type and initializes each field of the type at that location
/// </summary>
/// <param name="type">The type to initialize</param>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator InitializeValueType(this ILGenerator generator, Type type)
{
if (!type.IsValueType)
{
throw new InvalidOperationException("Cannot initialize a non-value type");
}
return generator.FluentEmit(OpCodes.Initobj, type);
}
/// <summary>
/// Pops the address of the storage location of a value type and initializes each field of the type at that location
/// </summary>
/// <typeparam name="T">The type to initialize</typeparam>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator InitializeValueType<T>(this ILGenerator generator) where T : struct
=> generator.InitializeValueType(typeof (T));
/// <summary>
/// Pops an address, initialization value and number of bytes off the evaluation stack, and initializes the block of memory at the address with the value to that size
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator InitializeBlock(this ILGenerator generator) => generator.FluentEmit(OpCodes.Initblk);
/// <summary>
/// Pops an address off the evaluation stack and initializes the block of memory at the address with the given value to the given size
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="value">The initialization value</param>
/// <param name="bytes">The number of bytes to initialize</param>
[PublicAPI]
public static ILGenerator InitializeBlock(this ILGenerator generator, byte value, uint bytes)
{
return generator.LoadConstant(value)
.LoadConstant(bytes)
.InitializeBlock();
}
/// <summary>
/// Pops an address, initialization value and number of bytes off the evaluation stack, and initializes the block of memory at the address with the value to that size, with volatile semantics
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator InitializeBlockVolatile(this ILGenerator generator)
{
return generator.FluentEmit(OpCodes.Volatile)
.InitializeBlock();
}
/// <summary>
/// Pops an address off the evaluation stack and initializes the block of memory at the address with the given value to the given size, with volatile semantics
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="value">The initialization value</param>
/// <param name="bytes">The number of bytes to initialize</param>
[PublicAPI]
public static ILGenerator InitializeBlockVolatile(this ILGenerator generator, byte value, uint bytes)
{
return generator.FluentEmit(OpCodes.Volatile)
.InitializeBlock(value, bytes);
}
/// <summary>
/// Pops an integer off the evaluation stack and creates an array of the given type with that length, pushing the reference onto the evaluation stack
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="type">The type of the array</param>
[PublicAPI]
public static ILGenerator NewArray(this ILGenerator generator, Type type) => generator.FluentEmit(OpCodes.Newarr);
/// <summary>
/// Pops an integer off the evaluation stack and creates an array of the given type with that length, pushing the reference onto the evaluation stack
/// </summary>
/// <typeparam name="T">The type of the array</typeparam>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator NewArray<T>(this ILGenerator generator) => generator.NewArray(typeof (T));
/// <summary>
/// Creates an array of the given type with the given length, pushing the reference onto the evaluation stack
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="type">The type of the array</param>
/// <param name="length">The length of the array</param>
[PublicAPI]
public static ILGenerator NewArray(this ILGenerator generator, Type type, uint length)
{
return generator.LoadConstant(length)
.NewArray(type);
}
/// <summary>
/// Creates an array of the given type with the given length, pushing the reference onto the evaluation stack
/// </summary>
/// <typeparam name="T">The type of the array</typeparam>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="length">The length of the array</param>
[PublicAPI]
public static ILGenerator NewArray<T>(this ILGenerator generator, uint length) => generator.NewArray(typeof(T), length);
/// <summary>
/// Pops an unsigned native integer from the evaluation stack, and allocates that number of bytes from the local dynamic memory pool, pushing the address onto the evaluation stack
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator AllocateFromLocalMemoryPool(this ILGenerator generator) => generator.FluentEmit(OpCodes.Localloc);
/// <summary>
/// Allocates the given number of bytes from the local dynamic memory pool, pushing the address onto the evaluation stack
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="size"></param>
[PublicAPI]
public static ILGenerator AllocateFromLocalMemoryPool(this ILGenerator generator, uint size)
{
return generator.LoadConstant(size)
.ConvertToUnsignedNativeInteger()
.AllocateFromLocalMemoryPool();
}
}
}