📄 emitcodegen.cs
字号:
/***************************************************************************\
*
* EmitCodeGen.CreateCLREnumType
*
\***************************************************************************/
public virtual System.Type CreateCLREnumType(SymbolEngine.EnumTypeEntry symEnum)
{
TypeAttributes mods = TypeAttributes.Sealed;
#if Bug_In_EnumBuilder
string stName = symEnum.FullName;
TypeBuilder bld;
// Handle nesting
SymbolEngine.TypeEntry tParent = symEnum.GetContainingType();
if (tParent == null)
{
if (symEnum.Mods.IsPublic)
mods |= TypeAttributes.Public;
else
mods |= TypeAttributes.NotPublic;
Log.WriteLine(Log.LF.CodeGen, "Define enum:{0}", stName);
bld = m_bldModule.DefineType(stName, mods, typeof(System.Enum));
} else {
if (symEnum.Mods.IsPublic)
mods |= TypeAttributes.NestedPublic;
else if (symEnum.Mods.IsPrivate)
mods |= TypeAttributes.NestedPrivate;
else if (symEnum.Mods.IsProtected)
mods |= TypeAttributes.NestedFamily;
else if (symEnum.Mods.IsInternal)
mods |= TypeAttributes.NestedAssembly;
Log.WriteLine(Log.LF.CodeGen, "Define nested enum:{0}", stName);
TypeBuilder bldParent = tParent.CLRType as TypeBuilder;
bld = bldParent.DefineNestedType(symEnum.Name, mods, typeof(System.Enum));
// DefineNestedType says it wants the 'full name', but name Name can't inclue [,],\,+
// So we're in a pickle. And then when the TypeResolve event is fired, we don't
// get enough info (we just get the short name).
//string stName2 = symEnum.FullName.Replace('+', '\\');
//bld = bldParent.DefineNestedType(stName2, mods, typeof(System.Enum));
}
// Enums have a default magical field:
bld.DefineField("value__", typeof(int),
FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
#else
#error - need a DefineNestedEnum()
EnumBuilder bld = m_bldModule.DefineEnum(stName, mods, typeof(int));
#endif
return bld;
}
/***************************************************************************\
*
* EmitCodeGen.SetCLRClassType
*
\***************************************************************************/
public virtual System.Type
CreateCLRClass(
SymbolEngine.TypeEntry symBlueType
)
{
// We call DefineType to get a TypeBuilder, which derives from Type
// We have to pass DefineType all the interesting parameters (ie, we
// have to know stuff like the base class now, not later)
// We get namespaces for free by using the full name
// We also handle nested classes here.
string stClassName = symBlueType.FullName;
System.Type typeBaseClass = null;
TypeAttributes attrClass = (TypeAttributes) 0;
SymbolEngine.TypeEntry [] arBlueInterfaces = symBlueType.BaseInterfaces;
System.Type [] arClrInterfaces = new System.Type[arBlueInterfaces.Length];
for(int i =0; i < arClrInterfaces.Length; i++)
{
arClrInterfaces[i] = arBlueInterfaces[i].CLRType;
Debug.Assert(arClrInterfaces[i] != null);
}
// Setup modifiers
AST.Modifiers mods = symBlueType.Mods;
TypeBuilder bldClass;
if (symBlueType.IsInterface)
attrClass |= TypeAttributes.Interface | TypeAttributes.Abstract;
else
{
typeBaseClass = symBlueType.Super.CLRType;
Debug.Assert(typeBaseClass != null);
}
if (mods.IsSealed)
attrClass |= TypeAttributes.Sealed;
if (mods.IsAbstract)
attrClass |= TypeAttributes.Abstract;
if (mods.IsSealed)
attrClass |= TypeAttributes.Sealed;
// Handle nesting
SymbolEngine.TypeEntry tParent = symBlueType.GetContainingType();
if (tParent == null)
{
// Not nested
if (mods.IsPublic)
attrClass |= TypeAttributes.Public;
else
attrClass |= TypeAttributes.NotPublic;
Log.WriteLine(Log.LF.CodeGen, "Define type:{0}", stClassName);
bldClass = m_bldModule.DefineType(
stClassName,
attrClass,
typeBaseClass,
arClrInterfaces
);
} else {
// Nested
if (mods.IsPublic)
attrClass |= TypeAttributes.NestedPublic;
else if (mods.IsPrivate)
attrClass |= TypeAttributes.NestedPrivate;
else if (mods.IsProtected)
attrClass |= TypeAttributes.NestedFamily;
else if (mods.IsInternal)
attrClass |= TypeAttributes.NestedAssembly;
Log.WriteLine(Log.LF.CodeGen, "Define nested type:{0}", stClassName);
TypeBuilder bldParent = tParent.CLRType as TypeBuilder;
bldClass = bldParent.DefineNestedType(symBlueType.Name, attrClass, typeBaseClass, arClrInterfaces);
}
Debug.Assert(bldClass != null, "Should have TypeBuilder by now");
// Make sure that we can lookup the type that we just created
#if DEBUG
System.Type tNatural = this.FindType(stClassName);
Debug.Assert(tNatural == bldClass);
#endif
// Sanity check that the type builder is complete enough to do
// clr inheritence checks
#if DEBUG
if (typeBaseClass != null)
Debug.Assert(bldClass.IsSubclassOf(typeBaseClass));
foreach(System.Type t in arClrInterfaces)
{
bool f1 = SymbolEngine.TypeEntry.IsAssignable(bldClass, t);
Debug.Assert(f1);
}
#endif
// Return the type and the symbol engine will set it
return bldClass;
}
//-------------------------------------------------------------------------
// Create a CLR event for use w/ reflection-emit
//-------------------------------------------------------------------------
public System.Reflection.EventInfo
CreateCLREvent(
SymbolEngine.EventExpEntry symEvent
)
{
string stName = symEvent.Name;
// Get class that we're defined in
TypeBuilder bldClass = symEvent.SymbolClass.CLRType as TypeBuilder;
Debug.Assert(bldClass != null);
EventAttributes attrs = EventAttributes.None;
AST.Modifiers mods = symEvent.Node.Mods;
EventBuilder bld = bldClass.DefineEvent(
stName, attrs, symEvent.EventType.CLRType
);
Debug.Assert(bld != null);
return null;
}
/***************************************************************************\
*
* EmitCodeGen.SetCLRMethodType
*
\***************************************************************************/
public virtual System.Reflection.PropertyInfo
CreateCLRProperty(
SymbolEngine.PropertyExpEntry symProperty
)
{
string stName = symProperty.Name;
// Get class that we're defined in
TypeBuilder bldClass = symProperty.SymbolClass.CLRType as TypeBuilder;
Debug.Assert(bldClass != null);
PropertyAttributes attrs = PropertyAttributes.None;
// Create the property builder
PropertyBuilder bld = bldClass.DefineProperty(
stName,
attrs,
symProperty.PropertyType.CLRType,
new Type[0]
);
// Create builders for the get / set accessors
if (symProperty.SymbolGet != null)
{
symProperty.SymbolGet.SetInfo(this);
bld.SetGetMethod(symProperty.SymbolGet.Info as MethodBuilder);
}
if (symProperty.SymbolSet != null)
{
symProperty.SymbolSet.SetInfo(this);
bld.SetSetMethod(symProperty.SymbolSet.Info as MethodBuilder);
}
return bld;
}
/***************************************************************************\
*
* EmitCodeGen.SetCLRMethodType
*
\***************************************************************************/
public virtual System.Reflection.MethodBase
CreateCLRMethod(
SymbolEngine.MethodExpEntry symBlueMethod
)
{
// Call DefineMethod on the TypeBuilder to get a MethodBuilder
// MethodBuilder derives from MethodInfo
string stMethodName = symBlueMethod.Name;
Debug.Assert(symBlueMethod.Node != null);
AST.Modifiers mods = symBlueMethod.Node.Mods;
MethodAttributes attrMethod = (MethodAttributes) 0;
// Everything seems to have this; but what does it do?
attrMethod = MethodAttributes.HideBySig;
if (mods.IsPublic)
attrMethod |= MethodAttributes.Public;
else if (mods.IsProtected)
attrMethod |= MethodAttributes.Family;
else if (mods.IsPrivate)
attrMethod |= MethodAttributes.Private;
else if (mods.IsInternal)
attrMethod |= MethodAttributes.Assembly;
if (symBlueMethod.IsSpecialName)
attrMethod |= MethodAttributes.SpecialName;
if (mods.IsStatic)
{
attrMethod |= MethodAttributes.Static;
}
if (mods.IsVirtual)
attrMethod |= MethodAttributes.Virtual | MethodAttributes.NewSlot;
if (mods.IsAbstract)
attrMethod |= MethodAttributes.Abstract | MethodAttributes.Virtual | MethodAttributes.NewSlot;
if (mods.IsOverride)
{
attrMethod |= MethodAttributes.Virtual;
}
if (mods.IsSealed)
attrMethod |= MethodAttributes.Final;
// Overloaded operators have a magical bit sit
if (symBlueMethod.Node.IsOpOverload)
attrMethod |= MethodAttributes.SpecialName;
// Get signature from the parameters
#if false
Type [] alParamTypes = new Type[symBlueMethod.ParamCount];
for(int iParam = 0; iParam < symBlueMethod.ParamCount; iParam++)
{
alParamTypes[iParam] = symBlueMethod.ParamCLRType(iParam);
}
#else
Type [] alParamTypes = symBlueMethod.ParamTypes(false);
#endif
// Get class that we're defined in
TypeBuilder bldClass = symBlueMethod.SymbolClass.CLRType as TypeBuilder;
Debug.Assert(bldClass != null);
bool fIsCtor = symBlueMethod.IsCtor;
System.Reflection.MethodBase bld = null;
// Get the builder
if (fIsCtor)
{
ConstructorBuilder bldCtor = bldClass.DefineConstructor(attrMethod, CallingConventions.Standard, alParamTypes);
if (AST.DelegateDecl.IsDelegate(symBlueMethod.SymbolClass.CLRType))
{
bldCtor.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
}
//return bldCtor;
bld = bldCtor;
}
else
{
Type typeReturn = symBlueMethod.RetType.CLRType;
Debug.Assert(typeReturn != null, "Semantic check should catch null return type");
MethodBuilder bldMethod = bldClass.DefineMethod(stMethodName, attrMethod, typeReturn, alParamTypes);
// The members of a delegate are special because they're implemented by the runtime.
if (AST.DelegateDecl.IsDelegate(symBlueMethod.SymbolClass.CLRType))
{
bldMethod.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
}
//return bldMethod;
bld = bldMethod;
}
// Double check that we set the attributes on the new CLR method properly.
// Do this by converting back to blue modifier from CLR method and comparing
// that modifier to the original.
#if DEBUG
AST.Modifiers modsCheck = new AST.Modifiers(bld);
string stPretty = symBlueMethod.PrettyDecoratedName;
string stBlue = mods.ToString();
string stCLR = modsCheck.ToString();
// The 'new' modifier just tells the C# compiler to suppress warnings. There's
// no IL bit for it, so we lose it when we roundtrip. So just add it to both
// of them.
mods.SetNew();
modsCheck.SetNew();
Debug.Assert(modsCheck == mods, "Modifer mismatch in creating CLR method");
#endif
return bld;
}
#endregion
#region Implementation for Codegen Driver
//-------------------------------------------------------------------------
// Helper class called when a resolve type event is fired.
// This is called when we CreateType() and it needs to also create an inner
// type.
//-------------------------------------------------------------------------
public Assembly ResolveCreateType(Object sender, ResolveEventArgs args)
{
Log.WriteLine(Log.LF.CodeGen, "... got TypeResolveEvent for '{0}'", args.Name);
// Get the full name of whoever originally called CreateType()
string stParent = (string) m_CreateTypeStack.Peek();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -