--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using CppSharp.AST;
+using CppSharp.AST.Extensions;
+using CppSharp.Parser;
+
+namespace CppSharp
+{
+ /**
+ * This tool dumps the offsets of structures used in the Mono VM needed
+ * by the AOT compiler for cross-compiling code to target platforms
+ * different than the host the compiler is being invoked on.
+ *
+ * It takes two arguments: the path to your clone of the Mono repo and
+ * the path to the root of Android NDK.
+ */
+ static class MonoAotOffsetsDumper
+ {
+ static string MonoDir = @"";
+
+ static List<string> Abis = new List<string> ();
+ static string OutputDir;
+
+ static string MonodroidDir = @"";
+ static string MaccoreDir = @"";
+
+ public enum TargetPlatform
+ {
+ Android,
+ iOS,
+ WatchOS,
+ }
+
+ public class Target
+ {
+ public Target()
+ {
+ Defines = new List<string>();
+ Arguments = new List<string>();
+ }
+
+ public Target(Target target)
+ {
+ Platform = target.Platform;
+ Triple = target.Triple;
+ Build = target.Build;
+ Defines = target.Defines;
+ Arguments = target.Arguments;
+ }
+
+ public TargetPlatform Platform;
+ public string Triple;
+ public string Build;
+ public List<string> Defines;
+ public List<string> Arguments;
+ };
+
+ public static List<Target> Targets = new List<Target>();
+
+ public static IEnumerable<Target> AndroidTargets
+ {
+ get { return Targets.Where ((t) => t.Platform == TargetPlatform.Android); }
+ }
+
+ public static IEnumerable<Target> DarwinTargets
+ {
+ get
+ {
+ return Targets.Where ((t) => t.Platform == TargetPlatform.iOS ||
+ t.Platform == TargetPlatform.WatchOS);
+ }
+ }
+
+ public static IEnumerable<Target> iOSTargets
+ {
+ get
+ {
+ return Targets.Where ((t) => t.Platform == TargetPlatform.iOS);
+ }
+ }
+
+ public static void SetupAndroidTargets()
+ {
+ Targets.Add (new Target {
+ Platform = TargetPlatform.Android,
+ Triple = "i686-none-linux-android",
+ Build = "mono-x86",
+ Defines = { "TARGET_X86" }
+ });
+
+ Targets.Add (new Target {
+ Platform = TargetPlatform.Android,
+ Triple = "x86_64-none-linux-android",
+ Build = "mono-x86_64",
+ Defines = { "TARGET_AMD64" }
+ });
+
+ Targets.Add (new Target {
+ Platform = TargetPlatform.Android,
+ Triple = "armv5-none-linux-androideabi",
+ Build = "mono-armv6",
+ Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
+ });
+
+ Targets.Add (new Target {
+ Platform = TargetPlatform.Android,
+ Triple = "armv7-none-linux-androideabi",
+ Build = "mono-armv7",
+ Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5", "HAVE_ARMV6",
+ "HAVE_ARMV7"
+ }
+ });
+
+ Targets.Add (new Target {
+ Platform = TargetPlatform.Android,
+ Triple = "aarch64-v8a-linux-android",
+ Build = "mono-aarch64",
+ Defines = { "TARGET_ARM64" }
+ });
+
+ /*Targets.Add(new Target {
+ Platform = TargetPlatform.Android,
+ Triple = "mipsel-none-linux-android",
+ Build = "mono-mips",
+ Defines = { "TARGET_MIPS", "__mips__" }
+ });*/
+
+ foreach (var target in AndroidTargets)
+ target.Defines.AddRange (new string[] { "PLATFORM_ANDROID",
+ "TARGET_ANDROID", "MONO_CROSS_COMPILE", "USE_MONO_CTX"
+ });
+ }
+
+ public static void SetupiOSTargets()
+ {
+ Targets.Add(new Target {
+ Platform = TargetPlatform.iOS,
+ Triple = "arm-apple-darwin10",
+ Build = "target7",
+ Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
+ });
+
+ Targets.Add(new Target {
+ Platform = TargetPlatform.iOS,
+ Triple = "aarch64-apple-darwin10",
+ Build = "target64",
+ Defines = { "TARGET_ARM64" }
+ });
+
+ foreach (var target in iOSTargets) {
+ target.Defines.AddRange (new string[] { "PLATFORM_DARWIN",
+ "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX",
+ "_XOPEN_SOURCE"
+ });
+ }
+
+ Targets.Add(new Target {
+ Platform = TargetPlatform.WatchOS,
+ Triple = "armv7k-apple-darwin",
+ Build = "targetwatch",
+ Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
+ });
+
+ foreach (var target in DarwinTargets) {
+ target.Defines.AddRange (new string[] { "PLATFORM_DARWIN",
+ "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX",
+ "_XOPEN_SOURCE"
+ });
+ }
+ }
+
+ static bool GetParentSubDirectoryPath(string parent, out string subdir)
+ {
+ var directory = Directory.GetParent(Directory.GetCurrentDirectory());
+
+ while (directory != null) {
+ var path = Path.Combine(directory.FullName, parent);
+
+ if (Directory.Exists (path)) {
+ subdir = path;
+ return true;
+ }
+
+ directory = directory.Parent;
+ }
+
+ subdir = null;
+ return false;
+ }
+
+ public static void Main(string[] args)
+ {
+ ParseCommandLineArgs(args);
+
+ string monodroidDir;
+ if (!Directory.Exists (MonodroidDir) &&
+ GetParentSubDirectoryPath ("monodroid", out monodroidDir)) {
+ MonodroidDir = Path.Combine (monodroidDir);
+ }
+
+ if (Directory.Exists (MonodroidDir))
+ SetupAndroidTargets();
+
+ string maccoreDir;
+ if (!Directory.Exists (MaccoreDir) &&
+ GetParentSubDirectoryPath ("maccore", out maccoreDir)) {
+ MaccoreDir = Path.Combine (maccoreDir);
+ }
+
+ if (Directory.Exists(MaccoreDir))
+ SetupiOSTargets();
+
+ foreach (var target in Targets)
+ {
+ if (Abis.Any() && !Abis.Any (target.Triple.Contains))
+ continue;
+
+ Console.WriteLine();
+ Console.WriteLine("Processing triple: {0}", target.Triple);
+
+ var options = new DriverOptions();
+
+ var log = new TextDiagnosticPrinter();
+ var driver = new Driver(options, log);
+
+ Setup(driver, target);
+ driver.Setup();
+
+ BuildParseOptions(driver, target);
+ if (!driver.ParseCode())
+ return;
+
+ Dump(driver.ASTContext, driver.TargetInfo, target);
+ }
+ }
+
+ static void BuildParseOptions(Driver driver, Target target)
+ {
+ foreach (var header in driver.Options.Headers)
+ {
+ var source = driver.Project.AddFile(header);
+ source.Options = driver.BuildParseOptions(source);
+
+ if (header.Contains ("mini"))
+ continue;
+
+ source.Options.addDefines ("HAVE_SGEN_GC");
+ source.Options.addDefines ("HAVE_MOVING_COLLECTOR");
+ }
+ }
+
+ static string GetAndroidNdkPath()
+ {
+ // Find the Android NDK's path from Monodroid's config.
+ var configFile = Path.Combine(MonodroidDir, "env.config");
+ if (!File.Exists(configFile))
+ throw new Exception("Expected a valid Monodroid environment config file at " + configFile);
+
+ var config = File.ReadAllText(configFile);
+ var match = Regex.Match(config, @"ANDROID_NDK_PATH\s*:=\s(.*)");
+ return match.Groups[1].Value.Trim();
+ }
+
+ static void ParseCommandLineArgs(string[] args)
+ {
+ var showHelp = false;
+
+ var options = new Mono.Options.OptionSet () {
+ { "abi=", "ABI triple to generate", v => Abis.Add(v) },
+ { "o|out=", "output directory", v => OutputDir = v },
+ { "maccore=", "include directory", v => MaccoreDir = v },
+ { "monodroid=", "include directory", v => MonodroidDir = v },
+ { "mono=", "include directory", v => MonoDir = v },
+ { "h|help", "show this message and exit", v => showHelp = v != null },
+ };
+
+ try {
+ options.Parse (args);
+ }
+ catch (Mono.Options.OptionException e) {
+ Console.WriteLine (e.Message);
+ Environment.Exit(0);
+ }
+
+ if (showHelp)
+ {
+ // Print usage and exit.
+ Console.WriteLine("{0} [--abi=triple] [--out=dir] "
+ + "[--monodroid/maccore=dir] [--mono=dir]",
+ AppDomain.CurrentDomain.FriendlyName);
+ Environment.Exit(0);
+ }
+ }
+
+ static void Setup(Driver driver, Target target)
+ {
+ var options = driver.Options;
+ options.DryRun = true;
+ options.Verbose = false;
+ options.LibraryName = "Mono";
+ options.MicrosoftMode = false;
+ options.addArguments("-xc");
+ options.addArguments("-std=gnu99");
+ options.addDefines("CPPSHARP");
+
+ foreach (var define in target.Defines)
+ options.addDefines(define);
+
+ SetupToolchainPaths(driver, target);
+
+ SetupMono(options, target);
+ }
+
+ static void SetupMono(DriverOptions options, Target target)
+ {
+ string targetPath;
+ switch (target.Platform) {
+ case TargetPlatform.Android:
+ targetPath = Path.Combine (MonodroidDir, "builds");
+ break;
+ case TargetPlatform.WatchOS:
+ case TargetPlatform.iOS:
+ targetPath = Path.Combine (MaccoreDir, "builds");
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+
+ if (!Directory.Exists (MonoDir)) {
+ MonoDir = Path.GetFullPath (Path.Combine (targetPath, "../../mono"));
+ }
+
+ var targetBuild = Path.Combine(targetPath, target.Build);
+
+ if (!Directory.Exists(targetBuild))
+ throw new Exception(string.Format("Could not find the target build directory: {0}", targetBuild));
+
+ var includeDirs = new[]
+ {
+ targetBuild,
+ Path.Combine(targetBuild, "eglib", "src"),
+ MonoDir,
+ Path.Combine(MonoDir, "mono"),
+ Path.Combine(MonoDir, "mono", "mini"),
+ Path.Combine(MonoDir, "eglib", "src")
+ };
+
+ foreach (var inc in includeDirs)
+ options.addIncludeDirs(inc);
+
+ var filesToParse = new[]
+ {
+ Path.Combine(MonoDir, "mono", "metadata", "metadata-cross-helpers.c"),
+ Path.Combine(MonoDir, "mono", "mini", "mini-cross-helpers.c"),
+ };
+
+ foreach (var file in filesToParse)
+ options.Headers.Add(file);
+ }
+
+ static void SetupMSVC(Driver driver, string triple)
+ {
+ var options = driver.Options;
+
+ options.Abi = Parser.AST.CppAbi.Microsoft;
+ options.MicrosoftMode = true;
+
+ var systemIncludeDirs = new[]
+ {
+ @"C:\Program Files (x86)\Windows Kits\8.1\Include\um",
+ @"C:\Program Files (x86)\Windows Kits\8.1\Include\shared"
+ };
+
+ foreach (var inc in systemIncludeDirs)
+ options.addSystemIncludeDirs(inc);
+
+ options.addDefines("HOST_WIN32");
+ }
+
+ static void SetupToolchainPaths(Driver driver, Target target)
+ {
+ switch (target.Platform) {
+ case TargetPlatform.Android:
+ SetupAndroidNDK(driver, target);
+ break;
+ case TargetPlatform.iOS:
+ case TargetPlatform.WatchOS:
+ SetupXcode(driver, target);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
+
+ static string GetArchFromTriple(string triple)
+ {
+ if (triple.Contains("mips"))
+ return "mips";
+
+ if (triple.Contains("arm64") || triple.Contains("aarch64"))
+ return "arm64";
+
+ if (triple.Contains("arm"))
+ return "arm";
+
+ if (triple.Contains("i686"))
+ return "x86";
+
+ if (triple.Contains("x86_64"))
+ return "x86_64";
+
+ throw new Exception("Unknown architecture from triple: " + triple);
+ }
+
+ static string GetXcodeToolchainPath()
+ {
+ var toolchains = Directory.EnumerateDirectories("/Applications", "Xcode*")
+ .ToList();
+ toolchains.Sort();
+
+ var toolchainPath = toolchains.LastOrDefault();
+ if (toolchainPath == null)
+ throw new Exception("Could not find a valid Xcode SDK");
+
+ return toolchainPath;
+ }
+
+ static string GetXcodeBuiltinIncludesFolder()
+ {
+ var toolchainPath = GetXcodeToolchainPath();
+
+ var toolchains = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
+ "Contents/Developer/Toolchains")).ToList();
+ toolchains.Sort();
+
+ toolchainPath = toolchains.LastOrDefault();
+ if (toolchainPath == null)
+ throw new Exception("Could not find a valid Xcode toolchain");
+
+ var includePaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
+ "usr/lib/clang")).ToList();
+ var includePath = includePaths.LastOrDefault();
+
+ if (includePath == null)
+ throw new Exception("Could not find a valid Clang include folder");
+
+ return Path.Combine(includePath, "include");
+ }
+
+ static string GetXcodeiOSIncludesFolder()
+ {
+ var toolchainPath = GetXcodeToolchainPath();
+
+ var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
+ "Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs")).ToList();
+ var sdkPath = sdkPaths.LastOrDefault();
+
+ if (sdkPath == null)
+ throw new Exception("Could not find a valid iPhone SDK");
+
+ return Path.Combine(sdkPath, "usr/include");
+ }
+
+ static string GetXcodeWatchOSIncludesFolder()
+ {
+ var toolchainPath = GetXcodeToolchainPath();
+
+ var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
+ "Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs")).ToList();
+ var sdkPath = sdkPaths.LastOrDefault();
+
+ if (sdkPath == null)
+ throw new Exception("Could not find a valid WatchOS SDK");
+
+ return Path.Combine(sdkPath, "usr/include");
+ }
+
+ static void SetupXcode(Driver driver, Target target)
+ {
+ var options = driver.Options;
+
+ var builtinsPath = GetXcodeBuiltinIncludesFolder();
+ string includePath;
+
+ switch (target.Platform) {
+ case TargetPlatform.iOS:
+ includePath = GetXcodeiOSIncludesFolder();
+ break;
+ case TargetPlatform.WatchOS:
+ includePath = GetXcodeWatchOSIncludesFolder();
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+
+ options.addSystemIncludeDirs(builtinsPath);
+ options.addSystemIncludeDirs(includePath);
+
+ options.NoBuiltinIncludes = true;
+ options.NoStandardIncludes = true;
+ options.TargetTriple = target.Triple;
+ }
+
+ static string GetAndroidHostToolchainPath()
+ {
+ var androidNdkPath = GetAndroidNdkPath ();
+ var toolchains = Directory.EnumerateDirectories(
+ Path.Combine(androidNdkPath, "toolchains"), "llvm*").ToList();
+ toolchains.Sort();
+
+ var toolchainPath = toolchains.LastOrDefault();
+ if (toolchainPath == null)
+ throw new Exception("Could not find a valid NDK host toolchain");
+
+ toolchains = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
+ "prebuilt")).ToList();
+ toolchains.Sort();
+
+ toolchainPath = toolchains.LastOrDefault();
+ if (toolchainPath == null)
+ throw new Exception("Could not find a valid NDK host toolchain");
+
+ return toolchainPath;
+ }
+
+ static string GetAndroidBuiltinIncludesFolder()
+ {
+ var toolchainPath = GetAndroidHostToolchainPath();
+
+ string clangToolchainPath = Path.Combine(toolchainPath, "lib64", "clang");
+ if (!Directory.Exists (clangToolchainPath))
+ clangToolchainPath = Path.Combine(toolchainPath, "lib", "clang");
+
+ string includePath = null;
+ if (Directory.Exists (clangToolchainPath)) {
+ var includePaths = Directory.EnumerateDirectories(clangToolchainPath).ToList();
+ includePath = includePaths.LastOrDefault();
+ }
+ if (includePath == null)
+ throw new Exception("Could not find a valid Clang include folder");
+
+ return Path.Combine(includePath, "include");
+ }
+
+ static void SetupAndroidNDK(Driver driver, Target target)
+ {
+ var options = driver.Options;
+
+ var builtinsPath = GetAndroidBuiltinIncludesFolder();
+ options.addSystemIncludeDirs(builtinsPath);
+
+ var androidNdkRoot = GetAndroidNdkPath ();
+ const int androidNdkApiLevel = 21;
+
+ var toolchainPath = Path.Combine(androidNdkRoot, "platforms",
+ "android-" + androidNdkApiLevel, "arch-" + GetArchFromTriple(target.Triple),
+ "usr", "include");
+ options.addSystemIncludeDirs(toolchainPath);
+
+ options.NoBuiltinIncludes = true;
+ options.NoStandardIncludes = true;
+ options.TargetTriple = target.Triple;
+ }
+
+ static uint GetTypeAlign(ParserTargetInfo target, ParserIntType type)
+ {
+ switch (type)
+ {
+ case ParserIntType.SignedChar:
+ case ParserIntType.UnsignedChar:
+ return target.CharAlign;
+ case ParserIntType.SignedShort:
+ case ParserIntType.UnsignedShort:
+ return target.ShortAlign;
+ case ParserIntType.SignedInt:
+ case ParserIntType.UnsignedInt:
+ return target.IntAlign;
+ case ParserIntType.SignedLong:
+ case ParserIntType.UnsignedLong:
+ return target.LongAlign;
+ case ParserIntType.SignedLongLong:
+ case ParserIntType.UnsignedLongLong:
+ return target.LongLongAlign;
+ default:
+ throw new Exception("Type has no alignment");
+ }
+ }
+
+ static uint GetTypeSize(ParserTargetInfo target, ParserIntType type)
+ {
+ switch (type)
+ {
+ case ParserIntType.SignedChar:
+ case ParserIntType.UnsignedChar:
+ return target.CharWidth;
+ case ParserIntType.SignedShort:
+ case ParserIntType.UnsignedShort:
+ return target.ShortWidth;
+ case ParserIntType.SignedInt:
+ case ParserIntType.UnsignedInt:
+ return target.IntWidth;
+ case ParserIntType.SignedLong:
+ case ParserIntType.UnsignedLong:
+ return target.LongWidth;
+ case ParserIntType.SignedLongLong:
+ case ParserIntType.UnsignedLongLong:
+ return target.LongLongWidth;
+ default:
+ throw new Exception("Type has no size");
+ }
+ }
+
+ static string GetTargetPlatformDefine(TargetPlatform target)
+ {
+ switch (target) {
+ case TargetPlatform.Android:
+ return "TARGET_ANDROID";
+ case TargetPlatform.iOS:
+ return "TARGET_IOS";
+ case TargetPlatform.WatchOS:
+ return "TARGET_WATCHOS";
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
+
+ static void Dump(ASTContext ctx, ParserTargetInfo targetInfo, Target target)
+ {
+ var targetFile = target.Triple;
+
+ if (!string.IsNullOrEmpty (OutputDir))
+ targetFile = Path.Combine (OutputDir, targetFile);
+
+ targetFile += ".h";
+
+ using (var writer = new StreamWriter(targetFile))
+ //using (var writer = Console.Out)
+ {
+ writer.WriteLine("#ifndef USED_CROSS_COMPILER_OFFSETS");
+ writer.WriteLine("#ifdef {0}", target.Defines[0]);
+ writer.WriteLine ("#ifdef {0}", GetTargetPlatformDefine (target.Platform));
+ writer.WriteLine("#ifndef HAVE_BOEHM_GC");
+ writer.WriteLine("#define HAS_CROSS_COMPILER_OFFSETS");
+ writer.WriteLine("#if defined (USE_CROSS_COMPILE_OFFSETS) || defined (MONO_CROSS_COMPILE)");
+ writer.WriteLine("#if !defined (DISABLE_METADATA_OFFSETS)");
+ writer.WriteLine("#define USED_CROSS_COMPILER_OFFSETS");
+
+ DumpAligns(writer, targetInfo);
+ DumpSizes(writer, targetInfo);
+ DumpMetadataOffsets(writer, ctx, target);
+
+ writer.WriteLine("#endif //disable metadata check");
+
+ DumpJITOffsets(writer, ctx);
+
+ writer.WriteLine("#endif //cross compiler checks");
+ writer.WriteLine("#endif //gc check");
+ writer.WriteLine("#endif //os check");
+ writer.WriteLine("#endif //arch check");
+ writer.WriteLine("#endif //USED_CROSS_COMPILER_OFFSETS check");
+ }
+
+ Console.WriteLine("Generated offsets file: {0}", targetFile);
+ }
+
+ static void DumpAligns(TextWriter writer, ParserTargetInfo target)
+ {
+ var aligns = new[]
+ {
+ new { Name = "gint8", Align = target.CharAlign},
+ new { Name = "gint16", Align = target.ShortAlign},
+ new { Name = "gint32", Align = target.IntAlign},
+ new { Name = "gint64", Align = GetTypeAlign(target, target.Int64Type)},
+ new { Name = "float", Align = target.FloatAlign},
+ new { Name = "double", Align = target.DoubleAlign},
+ new { Name = "gpointer", Align = GetTypeAlign(target, target.IntPtrType)},
+ };
+
+ // Write the alignment info for the basic types.
+ foreach (var align in aligns)
+ writer.WriteLine("DECL_ALIGN2({0},{1})", align.Name, align.Align / 8);
+ }
+
+ static void DumpSizes(TextWriter writer, ParserTargetInfo target)
+ {
+ var sizes = new[]
+ {
+ new { Name = "gint8", Size = target.CharWidth},
+ new { Name = "gint16", Size = target.ShortWidth},
+ new { Name = "gint32", Size = target.IntWidth},
+ new { Name = "gint64", Size = GetTypeSize(target, target.Int64Type)},
+ new { Name = "float", Size = target.FloatWidth},
+ new { Name = "double", Size = target.DoubleWidth},
+ new { Name = "gpointer", Size = GetTypeSize(target, target.IntPtrType)},
+ };
+
+ // Write the size info for the basic types.
+ foreach (var size in sizes)
+ writer.WriteLine("DECL_SIZE2({0},{1})", size.Name, size.Size / 8);
+ }
+
+ static Class GetClassFromTypedef(ITypedDecl typedef)
+ {
+ var type = typedef.Type.Desugar() as TagType;
+ if (type == null)
+ return null;
+
+ var @class = type.Declaration as Class;
+
+ return @class.IsIncomplete ?
+ (@class.CompleteDeclaration as Class) : @class;
+ }
+
+ static void DumpClasses(TextWriter writer, ASTContext ctx, IEnumerable<string> types,
+ bool optional = false)
+ {
+ foreach (var @struct in types)
+ {
+ var @class = ctx.FindCompleteClass(@struct);
+ if (@class == null)
+ @class = ctx.FindCompleteClass("_" + @struct);
+
+ if (@class == null)
+ {
+ var typedef = ctx.FindTypedef(@struct).FirstOrDefault(
+ decl => !decl.IsIncomplete);
+
+ if (typedef != null)
+ @class = GetClassFromTypedef(typedef);
+ }
+
+ if (@class == null && optional)
+ continue;
+
+ if (@class == null)
+ throw new Exception("Expected to find struct definition for " + @struct);
+
+ DumpStruct(writer, @class);
+ }
+ }
+
+ static void DumpMetadataOffsets(TextWriter writer, ASTContext ctx, Target target)
+ {
+ var types = new List<string>
+ {
+ "MonoObject",
+ "MonoClass",
+ "MonoVTable",
+ "MonoDelegate",
+ "MonoInternalThread",
+ "MonoMulticastDelegate",
+ "MonoTransparentProxy",
+ "MonoRealProxy",
+ "MonoRemoteClass",
+ "MonoArray",
+ "MonoArrayBounds",
+ "MonoSafeHandle",
+ "MonoHandleRef",
+ "MonoComInteropProxy",
+ "MonoString",
+ "MonoException",
+ "MonoTypedRef",
+ "MonoThreadsSync",
+ "SgenThreadInfo"
+ };
+
+ DumpClasses(writer, ctx, types);
+ }
+
+ static void DumpJITOffsets(TextWriter writer, ASTContext ctx)
+ {
+ writer.WriteLine("#ifndef DISABLE_JIT_OFFSETS");
+ writer.WriteLine("#define USED_CROSS_COMPILER_OFFSETS");
+
+ var types = new[]
+ {
+ "MonoLMF",
+ "MonoMethodRuntimeGenericContext",
+ "MonoJitTlsData",
+ "MonoGSharedVtMethodRuntimeInfo",
+ "MonoContinuation",
+ "MonoContext",
+ "MonoDelegateTrampInfo",
+ };
+
+ DumpClasses(writer, ctx, types);
+
+ var optionalTypes = new[]
+ {
+ "GSharedVtCallInfo",
+ "SeqPointInfo",
+ "DynCallArgs",
+ "MonoLMFTramp",
+ };
+
+ DumpClasses(writer, ctx, optionalTypes, optional: true);
+
+ writer.WriteLine("#endif //disable jit check");
+ }
+
+ static void DumpStruct(TextWriter writer, Class @class)
+ {
+ var name = @class.Name;
+ if (name.StartsWith ("_", StringComparison.Ordinal))
+ name = name.Substring (1);
+
+ foreach (var field in @class.Fields)
+ {
+ if (field.IsBitField) continue;
+
+ if (name == "SgenThreadInfo" && field.Name == "regs")
+ continue;
+
+ writer.WriteLine("DECL_OFFSET2({0},{1},{2})", name, field.Name,
+ field.Offset / 8);
+ }
+ }
+ }
+}