1614 lines
61 KiB
C#
1614 lines
61 KiB
C#
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: mkmar.cs
|
||
|
//
|
||
|
// Make static marshaller.
|
||
|
//
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Diagnostics;
|
||
|
using System.IO;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using System.Text;
|
||
|
using System.Xml;
|
||
|
|
||
|
using Bartok.MSIL;
|
||
|
using System.Reflection;
|
||
|
|
||
|
public class mkmar
|
||
|
{
|
||
|
private static void Usage()
|
||
|
{
|
||
|
Console.WriteLine("Usage:\n" +
|
||
|
" mkmar /in:file.cs /out:file.cs [assemblies]\n");
|
||
|
}
|
||
|
|
||
|
public static int Main(string[] args)
|
||
|
{
|
||
|
ArrayList infiles = new ArrayList();
|
||
|
StreamWriter outfile = null;
|
||
|
StreamReader infile = null;
|
||
|
|
||
|
if (args.Length == 0) {
|
||
|
Usage();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < args.Length; i++) {
|
||
|
string arg = args[i];
|
||
|
|
||
|
if (arg.Length >= 2 && (arg[0] == '-' || arg[0] == '/')) {
|
||
|
string name = null;
|
||
|
string value = null;
|
||
|
|
||
|
int n = arg.IndexOf(':');
|
||
|
|
||
|
if (n > -1) {
|
||
|
name = arg.Substring(1, n - 1).ToLower();
|
||
|
|
||
|
if (n < arg.Length + 1) {
|
||
|
value = arg.Substring(n + 1);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
name = arg.Substring(1).ToLower();
|
||
|
}
|
||
|
|
||
|
bool badArg = false;
|
||
|
|
||
|
switch (name) {
|
||
|
case "out" :
|
||
|
if (value != null) {
|
||
|
outfile = new StreamWriter(value);
|
||
|
} else {
|
||
|
badArg = true;
|
||
|
}
|
||
|
break;
|
||
|
case "in" :
|
||
|
if (value != null) {
|
||
|
infile = new StreamReader(value);
|
||
|
} else {
|
||
|
badArg = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default :
|
||
|
badArg = true;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (badArg) {
|
||
|
Console.WriteLine("Malformed argument: \"" + arg + "\"");
|
||
|
Usage();
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
// This is just an assembly name
|
||
|
infiles.Add(arg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (outfile == null) {
|
||
|
Console.WriteLine("You must specify the output file.");
|
||
|
Usage();
|
||
|
return 1;
|
||
|
}
|
||
|
if (infile == null) {
|
||
|
Console.WriteLine("You must specify the input file.");
|
||
|
Usage();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (infiles.Count == 0) {
|
||
|
Console.WriteLine("You must specify at least one input file.");
|
||
|
Usage();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
ProcessAssemblies(infiles, infile, outfile);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
private static SortedList used;
|
||
|
private static MetaDataResolver resolver;
|
||
|
private static TypeInfo tiObject;
|
||
|
private static TypeInfo tiString;
|
||
|
|
||
|
private static void ProcessAssemblies(ArrayList infiles, TextReader tr, TextWriter tw)
|
||
|
{
|
||
|
resolver = new MetaDataResolver(infiles,
|
||
|
new ArrayList(),
|
||
|
new DateTime(),
|
||
|
false,
|
||
|
false);
|
||
|
|
||
|
MetaDataResolver.ResolveCustomAttributes(
|
||
|
new MetaDataResolver[]{resolver});
|
||
|
|
||
|
TypeInfo.Add("bool");
|
||
|
TypeInfo.Add("char");
|
||
|
TypeInfo.Add("byte");
|
||
|
TypeInfo.Add("sbyte");
|
||
|
TypeInfo.Add("ushort");
|
||
|
TypeInfo.Add("short");
|
||
|
TypeInfo.Add("uint");
|
||
|
TypeInfo.Add("int");
|
||
|
TypeInfo.Add("ulong");
|
||
|
TypeInfo.Add("long");
|
||
|
tiObject = TypeInfo.Add("object");
|
||
|
tiObject.isParent = true;
|
||
|
tiString = TypeInfo.Add("string");
|
||
|
tiObject.isRefType = true;
|
||
|
|
||
|
// We must always support null.
|
||
|
SortedList spaces = new SortedList();
|
||
|
tw.WriteLine("#define TRACE_CHEAP_STATE");
|
||
|
tw.WriteLine("#if !USE_CLR_REMOTING");
|
||
|
tw.WriteLine("using System;");
|
||
|
tw.WriteLine("using System.Runtime.Serialization;");
|
||
|
tw.WriteLine("using Bartok.Marshal;");
|
||
|
foreach (MetaData metadata in resolver.MetaDataList) {
|
||
|
foreach (MetaDataTypeDefinition type in metadata.TypeDefs) {
|
||
|
if (IsMarshalType(type) &&
|
||
|
type.Namespace != "" &&
|
||
|
!spaces.Contains(type.Namespace)) {
|
||
|
|
||
|
spaces.Add(type.Namespace, null);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
for (int id = 0; id < spaces.Count; id++) {
|
||
|
tw.WriteLine("using {0};", spaces.GetKey(id));
|
||
|
}
|
||
|
tw.WriteLine();
|
||
|
|
||
|
#if false
|
||
|
foreach (MetaData metadata in resolver.MetaDataList) {
|
||
|
Console.WriteLine("{0}", metadata.Name);
|
||
|
foreach (MetaDataTypeDefinition type in metadata.TypeDefs) {
|
||
|
Console.WriteLine(" {0,4} {1}", type.GetHashCode(), type.FullName);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// We first try to get all of the types from serialized fields
|
||
|
// so we have a Signature.Type.
|
||
|
foreach (MetaData metadata in resolver.MetaDataList) {
|
||
|
foreach (MetaDataTypeDefinition type in metadata.TypeDefs) {
|
||
|
if (!IsMarshalType(type)) {
|
||
|
continue;
|
||
|
}
|
||
|
foreach (MetaDataField field in type.Fields) {
|
||
|
if (!IsMarshalField(field)) {
|
||
|
continue;
|
||
|
}
|
||
|
TypeInfo.Add(field.Signature.FieldType, "field");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Then we pick up any [Serializable] classes.
|
||
|
foreach (MetaData metadata in resolver.MetaDataList) {
|
||
|
foreach (MetaDataTypeDefinition type in metadata.TypeDefs) {
|
||
|
if (IsMarshalType(type)) {
|
||
|
TypeInfo.Add(type, "serial");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Last we pick up any enclosing classes.
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
if (ti == null) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ti.type != null) {
|
||
|
MetaDataTypeDefinition md = ti.type;
|
||
|
if (md.EnclosingClass != null) {
|
||
|
MetaDataTypeDefinition type = md.EnclosingClass;
|
||
|
TypeInfo.Add(type, "enclose");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CompleteTypeInfoFields();
|
||
|
|
||
|
tw.WriteLine("// {0} types.", used.Count);
|
||
|
tw.WriteLine("// {0:x8}: null", 0);
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
|
||
|
if (ti == null) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
string attrs = "";
|
||
|
attrs += (ti.type != null) ? "d" : "-";
|
||
|
attrs += (ti.isUsedInField) ? "f" : "-";
|
||
|
attrs += (ti.isParent) ? "p" : "-";
|
||
|
attrs += (ti.isAbstract) ? "a" : "-";
|
||
|
attrs += (ti.isSealed) ? "s" : "-";
|
||
|
attrs += (ti.isOverload) ? "o" : "-";
|
||
|
attrs += (ti.isRefType) ? "r" : "-";
|
||
|
attrs += (ti.isInterface) ? "i" : "-";
|
||
|
attrs += (ti.isEnum) ? "e" : "-";
|
||
|
attrs += (ti.isStruct) ? "s" : "-";
|
||
|
attrs += (ti.isBuiltIn) ? "b" : "-";
|
||
|
attrs += (ti.hasArray != null) ? "v" : "-";
|
||
|
|
||
|
tw.WriteLine("// {0:x8}: {1,-7} {2} {3,4} {4} {5}",
|
||
|
id,
|
||
|
ti.reason,
|
||
|
attrs,
|
||
|
((ti.type != null) ? ti.type.GetHashCode() : 0),
|
||
|
ti.kind,
|
||
|
ti.isArray ? ":" + ti.arrayOf.kind : "");
|
||
|
}
|
||
|
tw.WriteLine("#endif // !USE_CLR_REMOTING");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
string ns = "";
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
if (ti == null) {
|
||
|
// ignore null.
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ti.type == null) {
|
||
|
continue;
|
||
|
}
|
||
|
if (ti.isEnclosed) {
|
||
|
// We pick up the enclosed types with their outer class.
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// need to handle nested classes...
|
||
|
|
||
|
if (ns != ti.type.Namespace) {
|
||
|
if (ns != "") {
|
||
|
tw.WriteLine("}"); //
|
||
|
tw.WriteLine();
|
||
|
}
|
||
|
ns = ti.type.Namespace;
|
||
|
tw.WriteLine("namespace {0} {{", ns);
|
||
|
}
|
||
|
|
||
|
DoClass(ti, tw);
|
||
|
}
|
||
|
|
||
|
if (ns != "") {
|
||
|
tw.WriteLine("}"); //
|
||
|
tw.WriteLine();
|
||
|
}
|
||
|
|
||
|
tw.WriteLine(new String('/', 78));
|
||
|
tw.WriteLine("//");
|
||
|
tw.WriteLine("namespace Bartok.Marshal {");
|
||
|
tw.WriteLine("#if !USE_CLR_REMOTING");
|
||
|
tw.WriteLine(" public delegate void CheapWriteDelegate(CheapState __cs, Object __ob);");
|
||
|
tw.WriteLine(" public delegate object CheapReadDelegate(uint __id, CheapState __cs);");
|
||
|
tw.WriteLine("#endif // !USE_CLR_REMOTING");
|
||
|
tw.WriteLine();
|
||
|
tw.WriteLine(" public class CheapState {");
|
||
|
tw.WriteLine("#if !USE_CLR_REMOTING");
|
||
|
tw.WriteLine(" public enum Types {");
|
||
|
tw.WriteLine(" {0,-23} = 0x{1:x8},", "Null", 0);
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
if (ti == null) {
|
||
|
continue;
|
||
|
}
|
||
|
if (ti.isBuiltIn) {
|
||
|
if (ti.isArray) {
|
||
|
tw.WriteLine(" {0,-23} = 0x{1:x8},",
|
||
|
ToEnumName(ti.arrayOf.kind + "Array"),
|
||
|
id);
|
||
|
}
|
||
|
else {
|
||
|
tw.WriteLine(" {0,-23} = 0x{1:x8},",
|
||
|
ToEnumName(ti.kind),
|
||
|
id);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
tw.WriteLine(" };");
|
||
|
tw.WriteLine();
|
||
|
for (string line; (line = tr.ReadLine()) != null;) {
|
||
|
tw.WriteLine(line);
|
||
|
}
|
||
|
tw.WriteLine("#endif //!USE_CLR_REMOTING");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine("}");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
tw.WriteLine("namespace Bartok.Marshal {");
|
||
|
tw.WriteLine(" public class CheapMarshal {");
|
||
|
tw.WriteLine(" public static int Main()");
|
||
|
tw.WriteLine(" {");
|
||
|
tw.WriteLine(" Console.WriteLine(\"Testing\");");
|
||
|
tw.WriteLine(" CheapState cs = new CheapState(0);");
|
||
|
tw.WriteLine(" Test(cs);");
|
||
|
tw.WriteLine(" return 0;");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
tw.WriteLine(" static CheapMarshal() {");
|
||
|
tw.WriteLine("#if !USE_CLR_REMOTING");
|
||
|
tw.WriteLine(" System.Collections.Hashtable writeHash = new System.Collections.Hashtable({0});",
|
||
|
used.Count + 1);
|
||
|
tw.WriteLine(" System.Collections.Hashtable readHash = new System.Collections.Hashtable({0});",
|
||
|
used.Count + 1);
|
||
|
tw.WriteLine();
|
||
|
tw.WriteLine(" CheapState.writeHash = writeHash;");
|
||
|
tw.WriteLine(" CheapState.readHash = readHash;");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
if (ti == null) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ti.kind == "object" || ti.isInterface) {
|
||
|
tw.WriteLine(" // dropping {0} as interface.", ti.kind);
|
||
|
continue;
|
||
|
}
|
||
|
if (ti.isArray) {
|
||
|
tw.WriteLine(" // dropping {0} as array.", ti.kind);
|
||
|
continue;
|
||
|
}
|
||
|
if (ti.isEnum) {
|
||
|
tw.WriteLine(" // dropping {0} as enum.", ti.kind);
|
||
|
continue;
|
||
|
}
|
||
|
if (ti.isAbstract && ti.children == null) {
|
||
|
tw.WriteLine(" // dropping {0} as abstract without children.",
|
||
|
ti.kind);
|
||
|
continue;
|
||
|
}
|
||
|
if (ti.isBuiltIn) {
|
||
|
// for now we just drop theses.
|
||
|
tw.WriteLine(" // dropping {0} as builtin.", ti.kind);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
tw.WriteLine(" writeHash.Add(typeof({0}),", ti.kind);
|
||
|
tw.WriteLine(" new CheapWriteDelegate({1}.CheapWriteItem));",
|
||
|
ti.kind, ti.kind);
|
||
|
if (!ti.isAbstract) {
|
||
|
tw.WriteLine(" readHash.Add((uint)0x{0:x8},", ti.id);
|
||
|
tw.WriteLine(" new CheapReadDelegate({1}.CheapReadItem));",
|
||
|
ti.kind, ti.kind);
|
||
|
}
|
||
|
else {
|
||
|
tw.WriteLine(" // dropping read.{0} as abstract.", ti.kind);
|
||
|
}
|
||
|
|
||
|
if (ti.hasArray != null) {
|
||
|
tw.WriteLine(" writeHash.Add(typeof({0}),", ti.hasArray.kind);
|
||
|
tw.WriteLine(" new CheapWriteDelegate({1}.CheapWriteArray));",
|
||
|
ti.hasArray.kind, ti.kind);
|
||
|
tw.WriteLine(" readHash.Add((uint)0x{0:x8},", ti.hasArray.id);
|
||
|
tw.WriteLine(" new CheapReadDelegate({1}.CheapReadArray));",
|
||
|
ti.hasArray.kind, ti.kind);
|
||
|
}
|
||
|
}
|
||
|
tw.WriteLine("#endif // !USE_CLR_REMOTING");
|
||
|
tw.WriteLine(" }");
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
tw.WriteLine(" public static void Test(CheapState __cw) {");
|
||
|
tw.WriteLine(" CheapState __cr = new CheapState(__cw);");
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
|
||
|
if (ti == null) {
|
||
|
// We ignore null here.
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!ti.isBuiltIn || ti.isRefType) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ti.kind == "bool" || ti.kind == "char") {
|
||
|
continue;
|
||
|
}
|
||
|
tw.WriteLine(" {");
|
||
|
tw.WriteLine(" __cw.Trace(\"Testing {0}\");", ti.kind);
|
||
|
tw.WriteLine(" {0} value = 0x77;", ti.kind);
|
||
|
tw.WriteLine(" __cw.WriteOpen();");
|
||
|
tw.WriteLine(" __cw.Write(value);");
|
||
|
tw.WriteLine(" __cw.WriteClose();");
|
||
|
tw.WriteLine(" __cw.Trace();");
|
||
|
tw.WriteLine(" __cr.ReadOpen();");
|
||
|
tw.WriteLine(" __cr.Read(out value);");
|
||
|
tw.WriteLine(" __cr.ReadClose();");
|
||
|
tw.WriteLine(" __cr.Trace();");
|
||
|
tw.WriteLine(" Console.WriteLine(\"Testing {0}\");", ti.kind);
|
||
|
tw.WriteLine(" }");
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
|
||
|
if (ti == null) {
|
||
|
// We ignore null here.
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ti.isInterface || ti.isAbstract) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ti.isBuiltIn || ti.isArray || !ti.isRefType) {
|
||
|
// Base types are handled manually.
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
tw.WriteLine(" {");
|
||
|
tw.WriteLine(" __cw.Trace(\"Testing {0}\");", ti.kind);
|
||
|
tw.WriteLine(" {0} value = new {0}();", ti.kind);
|
||
|
tw.WriteLine(" __cw.WriteOpen();");
|
||
|
tw.WriteLine(" {0}.CheapWrite(__cw, value);", ti.kind);
|
||
|
tw.WriteLine(" __cw.WriteClose();");
|
||
|
tw.WriteLine(" __cw.Trace();");
|
||
|
tw.WriteLine(" __cr.ReadOpen();");
|
||
|
tw.WriteLine(" {0}.CheapRead(__cr, out value);", ti.kind);
|
||
|
tw.WriteLine(" __cr.ReadClose();");
|
||
|
tw.WriteLine(" __cr.Trace();");
|
||
|
tw.WriteLine(" Console.WriteLine(\"Testing {0}\");", ti.kind);
|
||
|
tw.WriteLine(" }");
|
||
|
}
|
||
|
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
|
||
|
if (ti == null) {
|
||
|
// We ignore null here.
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ti.isInterface || ti.isAbstract) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ti.isBuiltIn || ti.isArray || !ti.isRefType) {
|
||
|
// Base types are handled manually.
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
tw.WriteLine(" {");
|
||
|
tw.WriteLine(" __cw.Trace(\"Testing {0}\");", ti.kind);
|
||
|
tw.WriteLine(" {0} value = new {0}();", ti.kind);
|
||
|
if (ti.fields != null) {
|
||
|
foreach (FieldInfo fi in ti.fields) {
|
||
|
fi.WriteTestInit(tw);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
tw.WriteLine(" __cw.WriteOpen();");
|
||
|
tw.WriteLine(" {0}.CheapWrite(__cw, value);", ti.kind);
|
||
|
tw.WriteLine(" __cw.WriteClose();");
|
||
|
tw.WriteLine(" __cw.Trace();");
|
||
|
tw.WriteLine(" __cr.ReadOpen();");
|
||
|
tw.WriteLine(" {0}.CheapRead(__cr, out value);", ti.kind);
|
||
|
tw.WriteLine(" __cr.ReadClose();");
|
||
|
tw.WriteLine(" __cr.Trace();");
|
||
|
tw.WriteLine(" Console.WriteLine(\"Testing {0}\");", ti.kind);
|
||
|
tw.WriteLine(" }");
|
||
|
}
|
||
|
|
||
|
tw.WriteLine(" {");
|
||
|
tw.WriteLine(" __cw.Trace(\"Testing Linked List\");");
|
||
|
tw.WriteLine(" NullType[] nt = new NullType[4];");
|
||
|
tw.WriteLine(" for (int i = 0; i < nt.Length; i++) {");
|
||
|
tw.WriteLine(" nt[i] = new NullType();");
|
||
|
tw.WriteLine(" nt[i].name = \"nt[\" + i.ToString() + \"]\";");
|
||
|
tw.WriteLine(" nt[i].hashCode = i;");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" for (int i = 0; i < nt.Length - 1; i++) {");
|
||
|
tw.WriteLine(" nt[i].backEndRep = nt[i+1];");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" for (int i = 1; i < nt.Length; i++) {");
|
||
|
tw.WriteLine(" nt[i].backEndMangledName = nt[i-1];");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" ");
|
||
|
tw.WriteLine(" __cw.WriteOpen();");
|
||
|
tw.WriteLine(" NullType.CheapWrite(__cw, nt[0]);");
|
||
|
tw.WriteLine(" __cw.WriteClose();");
|
||
|
tw.WriteLine(" __cw.Trace();");
|
||
|
tw.WriteLine(" NullType value = null;");
|
||
|
tw.WriteLine(" __cr.ReadOpen();");
|
||
|
tw.WriteLine(" NullType.CheapRead(__cr, out value);");
|
||
|
tw.WriteLine(" __cr.ReadClose();");
|
||
|
tw.WriteLine(" __cr.Trace();");
|
||
|
tw.WriteLine(" for (int i = 0; value != null; i++) {");
|
||
|
tw.WriteLine(" __cr.Trace(\"{0,2}: {1,-10} : {2,2} : {3} {4}\",");
|
||
|
tw.WriteLine(" i, value.name, value.hashCode,");
|
||
|
tw.WriteLine(" value.backEndRep != null ? ((NullType)value.backEndRep).name : \"<null>\",");
|
||
|
tw.WriteLine(" value.backEndMangledName != null ? ((NullType)value.backEndMangledName).name : \"<null>\");");
|
||
|
tw.WriteLine(" value = (NullType)value.backEndRep;");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" __cr.Trace();");
|
||
|
tw.WriteLine(" Console.WriteLine(\"Testing Linked List\");");
|
||
|
tw.WriteLine(" }");
|
||
|
|
||
|
tw.WriteLine(" }"); // end of Test() method.
|
||
|
tw.WriteLine(" }"); // end of CheapMarshal class.
|
||
|
tw.WriteLine("}"); // end of Bartok.Marshal namespace.
|
||
|
tw.Flush();
|
||
|
}
|
||
|
|
||
|
private static string ToEnumName(string name)
|
||
|
{
|
||
|
int pos = name.LastIndexOf('.');
|
||
|
if (pos >= 0) {
|
||
|
return Char.ToUpper(name[pos + 1]) + name.Substring(pos + 2);
|
||
|
}
|
||
|
return Char.ToUpper(name[0]) + name.Substring(1);
|
||
|
}
|
||
|
|
||
|
private static void DoClass(TypeInfo ti, TextWriter tw)
|
||
|
{
|
||
|
int id = ti.id;
|
||
|
MetaDataTypeDefinition type = ti.type;
|
||
|
|
||
|
if (ti.isEnum) {
|
||
|
tw.WriteLine(" public enum {0} {{ // {1}",
|
||
|
type.Name,
|
||
|
type.FullName);
|
||
|
tw.WriteLine(" VALUE = 0,");
|
||
|
tw.WriteLine(" }");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (ti.isOverload) {
|
||
|
tw.WriteLine(" // is child class");
|
||
|
}
|
||
|
if (ti.isParent) {
|
||
|
tw.WriteLine(" // is parent class");
|
||
|
foreach (TypeInfo ci in ti.children) {
|
||
|
tw.WriteLine(" // child {0}", ci.kind);
|
||
|
}
|
||
|
foreach (TypeInfo ci in ti.descendants) {
|
||
|
tw.WriteLine(" // des {0}", ci.kind);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ti.isStruct) {
|
||
|
tw.WriteLine(" public struct {0} {{ // {1}",
|
||
|
type.Name,
|
||
|
type.FullName);
|
||
|
}
|
||
|
else if (ti.isInterface) {
|
||
|
if (ti.isOverload) {
|
||
|
// else if (type.Extends != null && type.Extends.FullName != "System.Object")
|
||
|
tw.WriteLine(" public interface {0} : {1} {{ // {2}",
|
||
|
type.Name,
|
||
|
type.Extends.FullName,
|
||
|
type.FullName);
|
||
|
}
|
||
|
else {
|
||
|
tw.WriteLine(" public interface {0} {{ // {1}",
|
||
|
type.Name,
|
||
|
type.FullName);
|
||
|
}
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
return;
|
||
|
}
|
||
|
else {
|
||
|
if (ti.isOverload) {
|
||
|
// else if (type.Extends != null && type.Extends.FullName != "System.Object")
|
||
|
tw.WriteLine(" public {0}class {1} : {2} {{ // {3}",
|
||
|
ti.isAbstract ? "abstract " : "",
|
||
|
type.Name,
|
||
|
type.Extends.FullName,
|
||
|
type.FullName);
|
||
|
}
|
||
|
else {
|
||
|
tw.WriteLine(" public {0}class {1} : Object {{ // {2}",
|
||
|
ti.isAbstract ? "abstract " : "",
|
||
|
type.Name,
|
||
|
type.FullName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
string vlabel = "";
|
||
|
if (ti.isOverload) {
|
||
|
vlabel = "override ";
|
||
|
}
|
||
|
else if (ti.isParent) {
|
||
|
vlabel = "virtual ";
|
||
|
}
|
||
|
|
||
|
FieldInfo[] fields = ti.fields;
|
||
|
|
||
|
//////////////////////////////////////// Null Constructor for Testing.
|
||
|
//
|
||
|
if (!ti.isStruct && !ti.isAbstract) {
|
||
|
tw.WriteLine(" // For Testing.");
|
||
|
tw.WriteLine(" public {0}() {{", type.Name);
|
||
|
tw.WriteLine(" }");
|
||
|
}
|
||
|
tw.WriteLine(" // For Testing.");
|
||
|
for (int i = 0; i < fields.Length; i++) {
|
||
|
tw.WriteLine(" public {0} {1};",
|
||
|
fields[i].Type.kind, fields[i].Name);
|
||
|
}
|
||
|
tw.WriteLine();
|
||
|
|
||
|
//////////////////////////////////////////////////////////// Core Constructor.
|
||
|
//
|
||
|
if (ti.isAbstract && ti.children == null) {
|
||
|
// Abort early since class exists only to hold inner types...
|
||
|
if (ti.inner != null) {
|
||
|
tw.WriteLine();
|
||
|
foreach (TypeInfo inner in ti.inner) {
|
||
|
DoClass(inner, tw);
|
||
|
}
|
||
|
}
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
tw.WriteLine("#if !USE_CLR_REMOTING");
|
||
|
if (ti.isAbstract) {
|
||
|
tw.WriteLine(" public {0}() {{", type.Name);
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
}
|
||
|
|
||
|
if (ti.isOverload) {
|
||
|
tw.WriteLine(" private {0}(uint __id, CheapState __cs)",
|
||
|
type.Name);
|
||
|
tw.WriteLine(" : base(__cs) {");
|
||
|
}
|
||
|
else {
|
||
|
tw.WriteLine(" private {0}(uint __id, CheapState __cs) {{", type.Name);
|
||
|
}
|
||
|
tw.WriteLine(" if (__id != 0x{0:x8}) {{", ti.id);
|
||
|
tw.WriteLine(" throw new Exception(\"__id != Type(0x{0:x8}) for {1}\");", ti.id, type.FullName);
|
||
|
tw.WriteLine(" }");
|
||
|
if (!ti.isOverload && !ti.isStruct) {
|
||
|
tw.WriteLine(" __cs.AddPtr(this, 0x{0:x8});", ti.id);
|
||
|
}
|
||
|
|
||
|
bool hadEv = false;
|
||
|
bool hadOb = false;
|
||
|
for (int i = 0; i < fields.Length; i++) {
|
||
|
TypeInfo fi = fields[i].Type;
|
||
|
if (fi.isInterface) {
|
||
|
if (!hadOb) {
|
||
|
tw.WriteLine(" object __ob;");
|
||
|
hadOb = true;
|
||
|
}
|
||
|
tw.WriteLine(" __cs.Read(out __ob);");
|
||
|
tw.WriteLine(" {0} = ({1})__ob;",
|
||
|
fields[i].Name, fi.kind);
|
||
|
}
|
||
|
else if (fi.isArray) {
|
||
|
if (fi.arrayOf.type != null) {
|
||
|
tw.WriteLine(" {0}.CheapRead(__cs, out {1}); // {2}",
|
||
|
fi.arrayOf.kind,
|
||
|
fields[i].Name,
|
||
|
fi.kind);
|
||
|
}
|
||
|
else {
|
||
|
tw.WriteLine(" __cs.Read(out {0}); // {1}",
|
||
|
fields[i].Name, fi.kind);
|
||
|
}
|
||
|
}
|
||
|
else if (fi.isEnum) {
|
||
|
if (!hadEv) {
|
||
|
tw.WriteLine(" uint __ev;");
|
||
|
hadEv = true;
|
||
|
}
|
||
|
tw.WriteLine(" __cs.Read(out __ev); // {0}", fi.kind);
|
||
|
tw.WriteLine(" {0} = unchecked(({1})__ev);",
|
||
|
fields[i].Name, fi.kind);
|
||
|
}
|
||
|
else if (fi.type != null) {
|
||
|
tw.WriteLine(" {0}.CheapRead(__cs, out {1});",
|
||
|
fi.kind,
|
||
|
fields[i].Name);
|
||
|
}
|
||
|
else {
|
||
|
// It is a builtin.
|
||
|
tw.WriteLine(" __cs.Read(out {0}); // {1}",
|
||
|
fields[i].Name, fi.kind);
|
||
|
}
|
||
|
}
|
||
|
tw.WriteLine(" __cs.ReadTypeEnd(0x{0:x8});", ti.id);
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
if (!ti.isStruct) {
|
||
|
tw.WriteLine(" {0}{1}(CheapState __cs)",
|
||
|
ti.isSealed ? "private " : "protected ",
|
||
|
type.Name);
|
||
|
tw.WriteLine(" : this(__cs.ReadType(0x{0:x8}), __cs) {{", ti.id);
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
}
|
||
|
|
||
|
if (ti.isStruct) {
|
||
|
tw.WriteLine(" private void CheapWrite(CheapState __cs) {");
|
||
|
}
|
||
|
else {
|
||
|
tw.WriteLine(" {0}{1}void CheapWrite(CheapState __cs) {{",
|
||
|
(ti.isSealed && !ti.isOverload) ? "private " : "protected ",
|
||
|
vlabel);
|
||
|
}
|
||
|
tw.WriteLine(" __cs.WriteType(0x{0:x8}); ", ti.id);
|
||
|
if (ti.isOverload) {
|
||
|
tw.WriteLine(" base.CheapWrite(__cs);");
|
||
|
}
|
||
|
for (int i = 0; i < fields.Length; i++) {
|
||
|
TypeInfo fi = fields[i].Type;
|
||
|
if (fi.isInterface) {
|
||
|
tw.WriteLine(" __cs.Write((object){0}); // {1}",
|
||
|
fields[i].Name, fi.kind);
|
||
|
}
|
||
|
else if (fi.isArray) {
|
||
|
if (fi.arrayOf.type != null) {
|
||
|
tw.WriteLine(" {0}.CheapWrite(__cs, {1}); // {2}",
|
||
|
fi.arrayOf.kind,
|
||
|
fields[i].Name,
|
||
|
fi.kind);
|
||
|
}
|
||
|
else {
|
||
|
tw.WriteLine(" __cs.Write({0}); // {1}",
|
||
|
fields[i].Name, fi.kind);
|
||
|
}
|
||
|
}
|
||
|
else if (fi.isEnum) {
|
||
|
tw.WriteLine(" __cs.Write(unchecked((uint){0})); // {1}",
|
||
|
fields[i].Name, fi.kind);
|
||
|
}
|
||
|
else if (fi.type != null) {
|
||
|
tw.WriteLine(" {0}.CheapWrite(__cs, {1}); // {2}",
|
||
|
fi.kind,
|
||
|
fields[i].Name,
|
||
|
fi.kind);
|
||
|
}
|
||
|
else {
|
||
|
// It is a builtin.
|
||
|
tw.WriteLine(" __cs.Write({0}); // {1}",
|
||
|
fields[i].Name, fi.kind);
|
||
|
}
|
||
|
}
|
||
|
tw.WriteLine(" __cs.WriteTypeEnd(0x{0:x8}); ", ti.id);
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
tw.WriteLine(" public static {0}void CheapWriteItem(CheapState __cs, Object __ob) {{",
|
||
|
ti.isOverload ? "new " : "");
|
||
|
tw.WriteLine(" CheapWrite(__cs, ({0})__ob);", type.Name);
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
if (!ti.isAbstract) {
|
||
|
tw.WriteLine(" public static {0}Object CheapReadItem(uint __id, CheapState __cs) {{",
|
||
|
(ti.isOverload && !ti.ParentsAreAllAbstract()) ? "new " : "");
|
||
|
tw.WriteLine(" if ((__id & 0x8000) != 0) {");
|
||
|
tw.WriteLine(" return __cs.LoadPtr(__id);");
|
||
|
tw.WriteLine(" }");
|
||
|
if (!ti.isRefType) {
|
||
|
tw.WriteLine(" object __ob = new {0}(__id, __cs);", type.Name);
|
||
|
tw.WriteLine(" __cs.AddPtr(__ob, __id);");
|
||
|
tw.WriteLine(" return __ob;");
|
||
|
}
|
||
|
else {
|
||
|
tw.WriteLine(" return new {0}(__id, __cs);", type.Name);
|
||
|
}
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
}
|
||
|
|
||
|
tw.WriteLine(" public static void CheapWrite(CheapState __cs, {0} value) {{",
|
||
|
type.Name);
|
||
|
tw.WriteLine(" __cs.Trace(\"Write {0} [outer]\");", type.Name);
|
||
|
if (ti.isRefType) {
|
||
|
tw.WriteLine(" if (value == null) {");
|
||
|
tw.WriteLine(" __cs.WriteType(0);");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" else if (__cs.SavePtr(0x{0:x8}, value)) {{", ti.id);
|
||
|
tw.WriteLine(" value.CheapWrite(__cs); ");
|
||
|
tw.WriteLine(" }");
|
||
|
}
|
||
|
else {
|
||
|
tw.WriteLine(" value.CheapWrite(__cs); ");
|
||
|
}
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
tw.WriteLine(" public static void CheapRead(CheapState __cs, out {0} value) {{",
|
||
|
type.Name);
|
||
|
tw.WriteLine(" __cs.Trace(\"Read {0} [outer]\");", type.Name);
|
||
|
if (ti.isParent) {
|
||
|
// Parent ref type.
|
||
|
tw.WriteLine(" object __ob;");
|
||
|
tw.WriteLine(" __cs.Read(out __ob);");
|
||
|
tw.WriteLine(" value = __ob as {0};", type.Name);
|
||
|
}
|
||
|
else if (ti.isRefType) {
|
||
|
// Leaf ref type.
|
||
|
tw.WriteLine(" uint __id = __cs.ReadTypeOrNull(0x{0:x8});", ti.id);
|
||
|
tw.WriteLine(" if (__id == 0) {");
|
||
|
tw.WriteLine(" value = null;");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" else {");
|
||
|
tw.WriteLine(" value = ({0})CheapReadItem(__id, __cs);", type.Name);
|
||
|
tw.WriteLine(" }");
|
||
|
}
|
||
|
else {
|
||
|
// Value type.
|
||
|
tw.WriteLine(" uint __id = __cs.ReadType(0x{0:x8});", ti.id);
|
||
|
tw.WriteLine(" value = new {0}(__id, __cs);", type.Name);
|
||
|
tw.WriteLine(" __cs.AddPtr(value, __id);");
|
||
|
|
||
|
}
|
||
|
tw.WriteLine(" }");
|
||
|
|
||
|
if (ti.hasArray != null) {
|
||
|
string alabel = "";
|
||
|
if (ti.isOverload && ti.parent.hasArray != null) {
|
||
|
alabel = "new ";
|
||
|
}
|
||
|
|
||
|
tw.WriteLine();
|
||
|
tw.WriteLine(" public static {0}void CheapWriteArray(CheapState __cs, Object __ob) {{", alabel);
|
||
|
tw.WriteLine(" CheapWrite(__cs, ({0}[])__ob);", type.Name);
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
tw.WriteLine(" public static void CheapWrite(CheapState __cs, {0}[] value) {{", type.Name);
|
||
|
tw.WriteLine(" __cs.Trace(\"Write {0}[]\");", ti.kind);
|
||
|
tw.WriteLine(" if (value == null) {");
|
||
|
tw.WriteLine(" __cs.WriteType(0);");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" else if (__cs.SavePtr(0x{0:x8}, value)) {{", ti.hasArray.id);
|
||
|
tw.WriteLine(" __cs.WriteType(0x{0:x8});", ti.hasArray.id);
|
||
|
tw.WriteLine(" __cs.WriteRaw((uint)value.Length);");
|
||
|
tw.WriteLine(" for (int i = 0; i < value.Length; i++) {");
|
||
|
tw.WriteLine(" CheapWrite(__cs, value[i]);");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" __cs.WriteTypeEnd(0x{0:x8});", ti.hasArray.id);
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
tw.WriteLine(" public static void CheapRead(CheapState __cs, out {0}[] value) {{",
|
||
|
type.Name);
|
||
|
tw.WriteLine(" __cs.Trace(\"Read {0}[] [outer]\");", ti.kind);
|
||
|
tw.WriteLine(" uint __id = __cs.ReadTypeOrNull(0x{0:x8});", ti.hasArray.id);
|
||
|
tw.WriteLine(" value = CheapReadArrayBody(__id, __cs);");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
tw.WriteLine(" public static {0}Object CheapReadArray(uint __id, CheapState __cs) {{", alabel);
|
||
|
tw.WriteLine(" return (Object)CheapReadArrayBody(__id, __cs);");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
tw.WriteLine(" private static {0}[] CheapReadArrayBody(uint __id, CheapState __cs) {{",
|
||
|
type.Name);
|
||
|
tw.WriteLine(" __cs.Trace(\"Read {0}[] [inner]\");", ti.kind);
|
||
|
tw.WriteLine(" if (__id == 0) {");
|
||
|
tw.WriteLine(" return null;");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" else if ((__id & 0x8000) != 0) {");
|
||
|
tw.WriteLine(" if (__id != 0x{0:x8}) {{", ti.hasArray.id | 0x8000);
|
||
|
tw.WriteLine(" throw new Exception(\"__id != Type(0x{0:x8}) for {1}[]\");", ti.hasArray.id | 0x8000, ti.kind);
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" return ({0}[])__cs.LoadPtr(__id);", type.Name);
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" else {");
|
||
|
tw.WriteLine(" if (__id != 0x{0:x8}) {{", ti.hasArray.id);
|
||
|
tw.WriteLine(" throw new Exception(\"__id != Type(0x{0:x8}) for {1}[]\");", ti.hasArray.id, ti.kind);
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" uint len;");
|
||
|
tw.WriteLine(" __cs.ReadRaw(out len);");
|
||
|
tw.WriteLine(" {0}[] value = new {1} [len];", type.Name, type.Name);
|
||
|
tw.WriteLine(" __cs.AddPtr(value, 0x{0:x8});", ti.hasArray.id);
|
||
|
tw.WriteLine(" for (int i = 0; i < len; i++) {");
|
||
|
tw.WriteLine(" CheapRead(__cs, out value[i]);");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" __cs.ReadTypeEnd(0x{0:x8});", ti.hasArray.id);
|
||
|
tw.WriteLine(" return value;");
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine(" }");
|
||
|
}
|
||
|
tw.WriteLine("#endif // !USE_CLR_REMOTING");
|
||
|
tw.WriteLine();
|
||
|
|
||
|
if (ti.inner != null) {
|
||
|
tw.WriteLine();
|
||
|
foreach (TypeInfo inner in ti.inner) {
|
||
|
DoClass(inner, tw);
|
||
|
}
|
||
|
}
|
||
|
tw.WriteLine(" }");
|
||
|
tw.WriteLine();
|
||
|
}
|
||
|
|
||
|
private static bool IsMarshalType(MetaDataTypeDefinition type)
|
||
|
{
|
||
|
uint flags = (uint)type.Flags & 0xfffffff8;
|
||
|
|
||
|
if ((type.Flags & TypeAttributes.Serializable) == 0) {
|
||
|
// We're only looking for serializable types.
|
||
|
return false;
|
||
|
}
|
||
|
if ((type.Flags & TypeAttributes.Interface) != 0) {
|
||
|
// Skip interfaces.
|
||
|
return false;
|
||
|
}
|
||
|
if ((type.Flags & TypeAttributes.Class) != 0) {
|
||
|
// We're only looking for classes.
|
||
|
// return false; // Currently unreachable
|
||
|
}
|
||
|
|
||
|
if (type.Name == "CheapState" ||
|
||
|
type.Name == "ObjectIDGenerator") {
|
||
|
// we drop some specific classes.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private static bool IsMarshalField(MetaDataField field)
|
||
|
{
|
||
|
uint flags = (uint)field.Flags & 0xfff8;
|
||
|
if (TestAndClear(ref flags, (uint)MetaDataField.FieldAttributes.NotSerialized)) {
|
||
|
// We skip over NonSerialized fields.
|
||
|
return false;
|
||
|
}
|
||
|
if (TestAndClear(ref flags, (uint)MetaDataField.FieldAttributes.Static)) {
|
||
|
// We skip static.
|
||
|
return false;
|
||
|
}
|
||
|
if (TestAndClear(ref flags, (uint)MetaDataField.FieldAttributes.InitOnly)) {
|
||
|
return true;
|
||
|
#if false
|
||
|
// We skip readonly.
|
||
|
return false;
|
||
|
#endif
|
||
|
}
|
||
|
if (TestAndClear(ref flags, (uint)MetaDataField.FieldAttributes.Literal)) {
|
||
|
// We skip const.
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private static string ClassToString(MetaDataObject mdo)
|
||
|
{
|
||
|
if (mdo is MetaDataTypeDefinition) {
|
||
|
return ((MetaDataTypeDefinition) mdo).FullName;
|
||
|
}
|
||
|
else if (mdo is MetaDataTypeReference) {
|
||
|
return ((MetaDataTypeReference) mdo).FullName;
|
||
|
}
|
||
|
else if (mdo == null) {
|
||
|
return "<null>";
|
||
|
}
|
||
|
else {
|
||
|
throw new Exception("unknown type: " + mdo.GetType());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static string TypeToString(Signature.Type type)
|
||
|
{
|
||
|
switch (type.ElementType) {
|
||
|
case ElementTypes.VOID:
|
||
|
return "void";
|
||
|
case ElementTypes.BOOLEAN:
|
||
|
return "bool";
|
||
|
case ElementTypes.CHAR:
|
||
|
return "char";
|
||
|
case ElementTypes.I1:
|
||
|
return "sbyte";
|
||
|
case ElementTypes.U1:
|
||
|
return "byte";
|
||
|
case ElementTypes.I2:
|
||
|
return "short";
|
||
|
case ElementTypes.U2:
|
||
|
return "ushort";
|
||
|
case ElementTypes.I4:
|
||
|
return "int";
|
||
|
case ElementTypes.U4:
|
||
|
return "uint";
|
||
|
case ElementTypes.I8:
|
||
|
return "long";
|
||
|
case ElementTypes.U8:
|
||
|
return "ulong";
|
||
|
case ElementTypes.R4:
|
||
|
return "float";
|
||
|
case ElementTypes.R8:
|
||
|
return "double";
|
||
|
case ElementTypes.STRING:
|
||
|
return "string";
|
||
|
//case ElementTypes.PTR:
|
||
|
//case ElementTypes.BYREF:
|
||
|
case ElementTypes.VALUETYPE:
|
||
|
return ClassToString(type.ClassObject);
|
||
|
case ElementTypes.CLASS:
|
||
|
return ClassToString(type.ClassObject);
|
||
|
//case ElementTypes.VAR:
|
||
|
//case ElementTypes.ARRAY:
|
||
|
//case ElementTypes.GENERICINST:
|
||
|
//case ElementTypes.TYPEDBYREF:
|
||
|
case ElementTypes.I:
|
||
|
return "IntPtr";
|
||
|
case ElementTypes.U:
|
||
|
return "UIntPtr";
|
||
|
//case ElementTypes.FNPTR:
|
||
|
case ElementTypes.OBJECT:
|
||
|
return "object";
|
||
|
case ElementTypes.SZARRAY:
|
||
|
return TypeToString(type.TypeObject) + "[]";
|
||
|
//case ElementTypes.MVAR:
|
||
|
//case ElementTypes.CMOD_REQD:
|
||
|
//case ElementTypes.CMOD_OPT:
|
||
|
//case ElementTypes.INTERNAL:
|
||
|
default:
|
||
|
throw new Exception("Unknown Field type");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static bool TestAndClear(ref uint flags, uint bit)
|
||
|
{
|
||
|
if ((flags & bit) != 0) {
|
||
|
// Console.WriteLine(" [{0:x4} had {1:x4}]", flags, bit);
|
||
|
flags &= ~bit;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private class FieldInfo
|
||
|
{
|
||
|
public readonly String Name;
|
||
|
public readonly TypeInfo Type;
|
||
|
|
||
|
public FieldInfo(String name, TypeInfo type)
|
||
|
{
|
||
|
this.Name = name;
|
||
|
this.Type = type;
|
||
|
}
|
||
|
|
||
|
public void WriteTestInit(TextWriter tw)
|
||
|
{
|
||
|
if (Type.kind == "bool") {
|
||
|
tw.WriteLine(" value.{0} = true;", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "char") {
|
||
|
tw.WriteLine(" value.{0} = 'A';", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "sbyte") {
|
||
|
tw.WriteLine(" value.{0} = 0x76;", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "byte") {
|
||
|
tw.WriteLine(" value.{0} = 0xfe;", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "short") {
|
||
|
tw.WriteLine(" value.{0} = 0x7654;", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "ushort") {
|
||
|
tw.WriteLine(" value.{0} = 0xfedc;", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "int") {
|
||
|
tw.WriteLine(" value.{0} = 0x76543210;", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "uint") {
|
||
|
tw.WriteLine(" value.{0} = 0xfedcba98;", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "long") {
|
||
|
tw.WriteLine(" value.{0} = 0x7654321001234567;", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "ulong") {
|
||
|
tw.WriteLine(" value.{0} = 0xfedcba9876543210;", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "string") {
|
||
|
tw.WriteLine(" value.{0} = \"Hello {1}!\";", Name, Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "object") {
|
||
|
tw.WriteLine(" value.{0} = new LirBasicBlock();", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "object[]") {
|
||
|
tw.WriteLine(" value.{0} = new Object[] " +
|
||
|
"{{ new LirBasicBlock(), new LirBasicBlock() }};",
|
||
|
Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "uint[]") {
|
||
|
tw.WriteLine(" value.{0} = new uint[] " +
|
||
|
"{{ 0xfedcba98, 0xfedcba97 }};", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.kind == "int[]") {
|
||
|
tw.WriteLine(" value.{0} = new int[] " +
|
||
|
"{{ 0x76543210, 0x76543219 }};", Name);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.isArray) {
|
||
|
tw.WriteLine(" value.{0} = new {1} {{ null }};",
|
||
|
Name, Type.kind);
|
||
|
return;
|
||
|
}
|
||
|
if (Type.isRefType && !Type.isInterface) {
|
||
|
TypeInfo ti = Type;
|
||
|
while (ti.isAbstract) {
|
||
|
#if false
|
||
|
tw.WriteLine("// {0} Bypassing {1} for {2}",
|
||
|
Name, ti.kind, ti.children[0].kind);
|
||
|
#endif
|
||
|
ti = ti.children[0];
|
||
|
}
|
||
|
tw.WriteLine(" value.{0} = new {1}();",
|
||
|
Name, ti.kind);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private class TypeInfo
|
||
|
{
|
||
|
static TypeInfo()
|
||
|
{
|
||
|
used = new SortedList();
|
||
|
used.Add("0", null);
|
||
|
}
|
||
|
|
||
|
public String kind;
|
||
|
public String reason;
|
||
|
public MetaDataTypeDefinition type;
|
||
|
public TypeInfo parent;
|
||
|
public TypeInfo[] children;
|
||
|
public TypeInfo[] descendants;
|
||
|
public TypeInfo[] inner;
|
||
|
public TypeInfo[] users;
|
||
|
public TypeInfo arrayOf;
|
||
|
public TypeInfo hasArray;
|
||
|
public FieldInfo[] fields;
|
||
|
public int id;
|
||
|
public bool isUsedInField;
|
||
|
public bool isRefType;
|
||
|
public bool isBuiltIn;
|
||
|
public bool isArray;
|
||
|
public bool isEnum;
|
||
|
public bool isStruct;
|
||
|
public bool isEnclosed;
|
||
|
public bool isSealed;
|
||
|
public bool isAbstract; // "abstract class foo"
|
||
|
public bool isParent; // has children.
|
||
|
public bool isOverload; // has a parent.
|
||
|
public bool isInterface;
|
||
|
// public bool hasZeroConstructor; // Currently unused
|
||
|
|
||
|
private TypeInfo()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public static TypeInfo Add(string builtin)
|
||
|
{
|
||
|
TypeInfo ti = new TypeInfo();
|
||
|
ti.kind = builtin;
|
||
|
ti.reason = "builtin";
|
||
|
ti.isBuiltIn = true;
|
||
|
used.Add(builtin, ti);
|
||
|
return ti;
|
||
|
}
|
||
|
|
||
|
public static TypeInfo Add(MetaDataTypeDefinition md, string reason)
|
||
|
{
|
||
|
string kind = md.FullName;
|
||
|
|
||
|
if (kind == "") {
|
||
|
System.Diagnostics.Debugger.Break();
|
||
|
}
|
||
|
|
||
|
TypeInfo ti;
|
||
|
int id = used.IndexOfKey(kind);
|
||
|
if (id > 0) {
|
||
|
ti = used.GetByIndex(id) as TypeInfo;
|
||
|
if (ti.type == null) {
|
||
|
ti.SetMetaData(md);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
ti = new TypeInfo();
|
||
|
ti.kind = kind;
|
||
|
ti.reason = reason;
|
||
|
ti.SetMetaData(md);
|
||
|
used.Add(ti.kind, ti);
|
||
|
}
|
||
|
return ti;
|
||
|
}
|
||
|
|
||
|
public static TypeInfo Add(Signature.Type st, string reason)
|
||
|
{
|
||
|
string kind = TypeToString(st);
|
||
|
if (kind == "") {
|
||
|
System.Diagnostics.Debugger.Break();
|
||
|
}
|
||
|
int id = used.IndexOfKey(kind);
|
||
|
TypeInfo ti;
|
||
|
if (id > 0) {
|
||
|
ti = used.GetByIndex(id) as TypeInfo;
|
||
|
if (!ti.isUsedInField) {
|
||
|
ti.isUsedInField = true;
|
||
|
ti.SetFieldInfo(st);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
ti = new TypeInfo();
|
||
|
ti.kind = kind;
|
||
|
ti.reason = reason;
|
||
|
ti.SetFieldInfo(st);
|
||
|
used.Add(ti.kind, ti);
|
||
|
}
|
||
|
return ti;
|
||
|
}
|
||
|
|
||
|
private void SetMetaData(MetaDataTypeDefinition md)
|
||
|
{
|
||
|
type = md;
|
||
|
isInterface = ((md.Flags & TypeAttributes.Interface) != 0);
|
||
|
isAbstract = ((md.Flags & TypeAttributes.Abstract) != 0);
|
||
|
isSealed = ((md.Flags & TypeAttributes.Sealed) != 0);
|
||
|
}
|
||
|
|
||
|
private void SetFieldInfo(Signature.Type st)
|
||
|
{
|
||
|
switch (st.ElementType) {
|
||
|
case ElementTypes.VOID:
|
||
|
break;
|
||
|
case ElementTypes.BOOLEAN:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.CHAR:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.I1:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.U1:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.I2:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.U2:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.I4:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.U4:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.I8:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.U8:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.R4:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.R8:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.STRING:
|
||
|
isRefType = true;
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
//case ElementTypes.PTR:
|
||
|
//case ElementTypes.BYREF:
|
||
|
case ElementTypes.VALUETYPE:
|
||
|
if (type == null) {
|
||
|
if (st.ClassObject is MetaDataTypeDefinition) {
|
||
|
SetMetaData((MetaDataTypeDefinition)st.ClassObject);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case ElementTypes.CLASS:
|
||
|
if (type == null) {
|
||
|
if (st.ClassObject is MetaDataTypeDefinition) {
|
||
|
SetMetaData((MetaDataTypeDefinition)st.ClassObject);
|
||
|
}
|
||
|
}
|
||
|
isRefType = true;
|
||
|
break;
|
||
|
//case ElementTypes.VAR:
|
||
|
//case ElementTypes.ARRAY:
|
||
|
//case ElementTypes.GENERICINST:
|
||
|
//case ElementTypes.TYPEDBYREF:
|
||
|
case ElementTypes.I:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
case ElementTypes.U:
|
||
|
isBuiltIn = true;
|
||
|
break;
|
||
|
//case ElementTypes.FNPTR:
|
||
|
case ElementTypes.OBJECT:
|
||
|
isBuiltIn = true;
|
||
|
isRefType = true;
|
||
|
break;
|
||
|
case ElementTypes.SZARRAY:
|
||
|
isRefType = true;
|
||
|
isBuiltIn = false;
|
||
|
isArray = true;
|
||
|
if (st.TypeObject.ClassObject is MetaDataTypeDefinition) {
|
||
|
MetaDataTypeDefinition md = (MetaDataTypeDefinition)st.TypeObject.ClassObject;
|
||
|
arrayOf = TypeInfo.Add(md, "arrayed");
|
||
|
arrayOf.hasArray = this;
|
||
|
if (arrayOf.isBuiltIn) {
|
||
|
isBuiltIn = true;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
arrayOf = TypeInfo.Find(kind.Remove(kind.Length-2, 2));
|
||
|
arrayOf.hasArray = this;
|
||
|
if (arrayOf.isBuiltIn) {
|
||
|
isBuiltIn = true;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
//case ElementTypes.MVAR:
|
||
|
//case ElementTypes.CMOD_REQD:
|
||
|
//case ElementTypes.CMOD_OPT:
|
||
|
//case ElementTypes.INTERNAL:
|
||
|
default:
|
||
|
throw new Exception("Unknown Field type");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static TypeInfo Find(string name)
|
||
|
{
|
||
|
return used[name] as TypeInfo;
|
||
|
}
|
||
|
|
||
|
public static TypeInfo Find(Signature.Type type)
|
||
|
{
|
||
|
string name = TypeToString(type);
|
||
|
return Find(name);
|
||
|
}
|
||
|
|
||
|
public ArrayList GetDescendants(ArrayList des)
|
||
|
{
|
||
|
if (descendants != null) {
|
||
|
foreach (TypeInfo di in descendants) {
|
||
|
des.Add(di);
|
||
|
}
|
||
|
}
|
||
|
else if (children != null) {
|
||
|
foreach (TypeInfo di in children) {
|
||
|
di.GetDescendants(des);
|
||
|
des.Add(di);
|
||
|
}
|
||
|
}
|
||
|
return des;
|
||
|
}
|
||
|
|
||
|
public bool ParentsAreAllAbstract()
|
||
|
{
|
||
|
for (TypeInfo ti = this; ti.parent != null; ti = ti.parent) {
|
||
|
if (!ti.parent.isAbstract) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static TypeInfo[] FindChildren(string parent)
|
||
|
{
|
||
|
ArrayList children = null;
|
||
|
|
||
|
foreach (MetaData metadata in resolver.MetaDataList) {
|
||
|
foreach (MetaDataTypeDefinition type in metadata.TypeDefs) {
|
||
|
if (type.Extends != null && type.Extends.FullName == parent) {
|
||
|
TypeInfo ti = used[type.FullName] as TypeInfo;
|
||
|
if (ti == null) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
#if false
|
||
|
Console.WriteLine("{0} is extended by {1}", parent, ti.kind);
|
||
|
#endif
|
||
|
if (children == null) {
|
||
|
children = new ArrayList();
|
||
|
}
|
||
|
children.Add(ti);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (children != null) {
|
||
|
return (TypeInfo[])children.ToArray(typeof(TypeInfo));
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
private static TypeInfo[] FindUsers(string iface)
|
||
|
{
|
||
|
ArrayList users = null;
|
||
|
|
||
|
foreach (MetaData metadata in resolver.MetaDataList) {
|
||
|
foreach (MetaDataTypeDefinition type in metadata.TypeDefs) {
|
||
|
foreach (MetaDataObject imd in type.Interfaces) {
|
||
|
if (imd.FullName == iface) {
|
||
|
TypeInfo ti = used[type.FullName] as TypeInfo;
|
||
|
if (ti == null) {
|
||
|
continue;
|
||
|
}
|
||
|
#if true
|
||
|
Console.WriteLine("{0} implemented by {1}", iface, ti.kind);
|
||
|
#endif
|
||
|
if (users == null) {
|
||
|
users = new ArrayList();
|
||
|
}
|
||
|
users.Add(ti);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (users != null) {
|
||
|
return (TypeInfo[])users.ToArray(typeof(TypeInfo));
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
private static TypeInfo[] FindInner(string outer)
|
||
|
{
|
||
|
ArrayList inner = null;
|
||
|
|
||
|
foreach (MetaData metadata in resolver.MetaDataList) {
|
||
|
foreach (MetaDataTypeDefinition type in metadata.TypeDefs) {
|
||
|
if ((type.EnclosingClass != null) &&
|
||
|
(type.EnclosingClass.FullName == outer)) {
|
||
|
TypeInfo ti = used[type.FullName] as TypeInfo;
|
||
|
if (ti == null) {
|
||
|
continue;
|
||
|
}
|
||
|
#if false
|
||
|
Console.WriteLine("{0} encloses {1}", outer, ti.kind);
|
||
|
#endif
|
||
|
if (inner == null) {
|
||
|
inner = new ArrayList();
|
||
|
}
|
||
|
inner.Add(ti);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (inner != null) {
|
||
|
return (TypeInfo[])inner.ToArray(typeof(TypeInfo));
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
private static void CompleteTypeInfoFields()
|
||
|
{
|
||
|
// First, fill in the missing base information.
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
if (ti == null) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
ti.id = id;
|
||
|
|
||
|
// Fill in the type definition if we don't have one.
|
||
|
if (ti.type == null) {
|
||
|
ti.type = resolver.ResolveName(ti.kind);
|
||
|
if (ti.type == null && !ti.isBuiltIn && !ti.isArray) {
|
||
|
Console.WriteLine("!!! Couldn't resolve: {0}", ti.kind);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now fill in information for inheritance tree.
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
if (ti == null || ti.type == null) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
#if false
|
||
|
Console.WriteLine("{0}:", ti.type.FullName);
|
||
|
#endif
|
||
|
if (ti.type.Extends != null) {
|
||
|
ti.isEnum = (ti.type.Extends.FullName == "System.Enum");
|
||
|
ti.isStruct = (ti.type.Extends.FullName == "System.ValueType");
|
||
|
if (ti.isEnum == false && ti.isStruct == false) {
|
||
|
ti.isOverload = !(ti.type.Extends.FullName == "System.Object");
|
||
|
}
|
||
|
ti.parent = TypeInfo.Find(ti.type.Extends.FullName);
|
||
|
}
|
||
|
|
||
|
if (ti.type.EnclosingClass != null) {
|
||
|
ti.isEnclosed = true;
|
||
|
}
|
||
|
|
||
|
ti.children = FindChildren(ti.type.FullName);
|
||
|
ti.inner = FindInner(ti.type.FullName);
|
||
|
ti.isParent = (ti.children != null);
|
||
|
|
||
|
if (ti.isStruct || ti.isEnum) {
|
||
|
ti.isRefType = false;
|
||
|
}
|
||
|
else if (!ti.isBuiltIn){
|
||
|
ti.isRefType = true;
|
||
|
}
|
||
|
|
||
|
if (ti.isInterface) {
|
||
|
ti.users = FindUsers(ti.kind);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now fill in deep information for inheritance tree.
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
if (ti == null || ti.type == null) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ti.children != null && ti.descendants == null) {
|
||
|
ArrayList des = ti.GetDescendants(new ArrayList());
|
||
|
|
||
|
ti.descendants = (TypeInfo[])des.ToArray(typeof(TypeInfo));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now collect all of the field information.
|
||
|
for (int id = 0; id < used.Count; id++) {
|
||
|
TypeInfo ti = used.GetByIndex(id) as TypeInfo;
|
||
|
if (ti == null || ti.type == null) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
ArrayList fieldList = new ArrayList();
|
||
|
foreach (MetaDataField field in ti.type.Fields) {
|
||
|
if (!IsMarshalField(field)) {
|
||
|
continue;
|
||
|
}
|
||
|
TypeInfo fi = TypeInfo.Find(field.Signature.FieldType);
|
||
|
|
||
|
fieldList.Add(new FieldInfo(field.Name, fi));
|
||
|
}
|
||
|
|
||
|
ti.fields = (FieldInfo[])fieldList.ToArray(typeof(FieldInfo));
|
||
|
}
|
||
|
}
|
||
|
}
|