forked from pythonnet/pythonnet
-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathCodeGenerator.cs
More file actions
81 lines (72 loc) · 2.66 KB
/
CodeGenerator.cs
File metadata and controls
81 lines (72 loc) · 2.66 KB
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
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
namespace Python.Runtime
{
/// <summary>
/// Several places in the runtime generate code on the fly to support
/// dynamic functionality. The CodeGenerator class manages the dynamic
/// assembly used for code generation and provides utility methods for
/// certain repetitive tasks.
/// </summary>
internal class CodeGenerator
{
private AssemblyBuilder aBuilder;
private ModuleBuilder mBuilder;
internal CodeGenerator()
{
var aname = new AssemblyName { Name = "__CodeGenerator_Assembly" };
var aa = AssemblyBuilderAccess.Run;
aBuilder = Thread.GetDomain().DefineDynamicAssembly(aname, aa);
mBuilder = aBuilder.DefineDynamicModule("__CodeGenerator_Module");
}
/// <summary>
/// DefineType is a shortcut utility to get a new TypeBuilder.
/// </summary>
internal TypeBuilder DefineType(string name)
{
var attrs = TypeAttributes.Public;
return mBuilder.DefineType(name, attrs);
}
/// <summary>
/// DefineType is a shortcut utility to get a new TypeBuilder.
/// </summary>
internal TypeBuilder DefineType(string name, Type basetype)
{
var attrs = TypeAttributes.Public;
return mBuilder.DefineType(name, attrs, basetype);
}
/// <summary>
/// Generates code, that copies potentially modified objects in args array
/// back to the corresponding byref arguments
/// </summary>
internal static void GenerateMarshalByRefsBack(ILGenerator il, IReadOnlyList<Type> argTypes)
{
// assumes argument array is in loc_0
for (int i = 0; i < argTypes.Count; ++i)
{
var type = argTypes[i];
if (type.IsByRef)
{
type = type.GetElementType();
il.Emit(OpCodes.Ldarg, i + 1); // for stobj/stind later at the end
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldelem_Ref);
if (type.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, type);
il.Emit(OpCodes.Stobj, type);
}
else
{
il.Emit(OpCodes.Castclass, type);
il.Emit(OpCodes.Stind_Ref);
}
}
}
}
}
}