Merge pull request #4498 from kumpera/backport-android-fix
[mono-project.git] / tools / offsets-tool / MonoAotOffsetsDumper.cs
blobf167566eef3609d121bcb9ebcc3ac6cf0d860d85
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Linq;
5 using System.Text.RegularExpressions;
6 using CppSharp.AST;
7 using CppSharp.AST.Extensions;
8 using CppSharp.Parser;
10 namespace CppSharp
12 /**
13 * This tool dumps the offsets of structures used in the Mono VM needed
14 * by the AOT compiler for cross-compiling code to target platforms
15 * different than the host the compiler is being invoked on.
17 * It takes two arguments: the path to your clone of the Mono repo and
18 * the path to the root of Android NDK.
20 static class MonoAotOffsetsDumper
22 static string MonoDir = @"";
24 static List<string> Abis = new List<string> ();
25 static string OutputDir;
27 static string MonodroidDir = @"";
28 static string AndroidNdkPath = @"";
29 static string MaccoreDir = @"";
30 static string TargetDir = @"";
32 public enum TargetPlatform
34 Android,
35 iOS,
36 WatchOS,
39 public class Target
41 public Target()
43 Defines = new List<string>();
44 Arguments = new List<string>();
47 public Target(Target target)
49 Platform = target.Platform;
50 Triple = target.Triple;
51 Build = target.Build;
52 Defines = target.Defines;
53 Arguments = target.Arguments;
56 public TargetPlatform Platform;
57 public string Triple;
58 public string Build;
59 public List<string> Defines;
60 public List<string> Arguments;
63 public static List<Target> Targets = new List<Target>();
65 public static IEnumerable<Target> AndroidTargets
67 get { return Targets.Where ((t) => t.Platform == TargetPlatform.Android); }
70 public static IEnumerable<Target> DarwinTargets
72 get
74 return Targets.Where ((t) => t.Platform == TargetPlatform.iOS ||
75 t.Platform == TargetPlatform.WatchOS);
79 public static IEnumerable<Target> iOSTargets
81 get
83 return Targets.Where ((t) => t.Platform == TargetPlatform.iOS);
87 public static void SetupAndroidTargets()
89 Targets.Add (new Target {
90 Platform = TargetPlatform.Android,
91 Triple = "i686-none-linux-android",
92 Defines = { "TARGET_X86" }
93 });
95 Targets.Add (new Target {
96 Platform = TargetPlatform.Android,
97 Triple = "x86_64-none-linux-android",
98 Defines = { "TARGET_AMD64" }
99 });
101 Targets.Add (new Target {
102 Platform = TargetPlatform.Android,
103 Triple = "armv5-none-linux-androideabi",
104 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
107 Targets.Add (new Target {
108 Platform = TargetPlatform.Android,
109 Triple = "armv7-none-linux-androideabi",
110 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5", "HAVE_ARMV6",
111 "HAVE_ARMV7"
115 Targets.Add (new Target {
116 Platform = TargetPlatform.Android,
117 Triple = "aarch64-v8a-linux-android",
118 Defines = { "TARGET_ARM64" }
119 });
121 /*Targets.Add(new Target {
122 Platform = TargetPlatform.Android,
123 Triple = "mipsel-none-linux-android",
124 Defines = { "TARGET_MIPS", "__mips__" }
125 });*/
127 foreach (var target in AndroidTargets)
128 target.Defines.AddRange (new string[] { "PLATFORM_ANDROID",
129 "TARGET_ANDROID", "MONO_CROSS_COMPILE", "USE_MONO_CTX"
133 public static void SetupiOSTargets()
135 Targets.Add(new Target {
136 Platform = TargetPlatform.iOS,
137 Triple = "arm-apple-darwin10",
138 Build = "target7",
139 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
142 Targets.Add(new Target {
143 Platform = TargetPlatform.iOS,
144 Triple = "aarch64-apple-darwin10",
145 Build = "target64",
146 Defines = { "TARGET_ARM64" }
149 foreach (var target in iOSTargets) {
150 target.Defines.AddRange (new string[] { "PLATFORM_DARWIN",
151 "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX",
152 "_XOPEN_SOURCE"
156 Targets.Add(new Target {
157 Platform = TargetPlatform.WatchOS,
158 Triple = "armv7k-apple-darwin",
159 Build = "targetwatch",
160 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
163 foreach (var target in DarwinTargets) {
164 target.Defines.AddRange (new string[] { "PLATFORM_DARWIN",
165 "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX",
166 "_XOPEN_SOURCE"
171 static bool GetParentSubDirectoryPath(string parent, out string subdir)
173 var directory = Directory.GetParent(Directory.GetCurrentDirectory());
175 while (directory != null) {
176 var path = Path.Combine(directory.FullName, parent);
178 if (Directory.Exists (path)) {
179 subdir = path;
180 return true;
183 directory = directory.Parent;
186 subdir = null;
187 return false;
190 public static void Main(string[] args)
192 ParseCommandLineArgs(args);
194 string monodroidDir;
195 if (!Directory.Exists (MonodroidDir) &&
196 GetParentSubDirectoryPath ("monodroid", out monodroidDir)) {
197 MonodroidDir = Path.Combine (monodroidDir);
200 if (Directory.Exists (MonodroidDir))
201 SetupAndroidTargets();
203 string maccoreDir;
204 if (!Directory.Exists (MaccoreDir) &&
205 GetParentSubDirectoryPath ("maccore", out maccoreDir)) {
206 MaccoreDir = Path.Combine (maccoreDir);
209 if (Directory.Exists(MaccoreDir))
210 SetupiOSTargets();
212 foreach (var target in Targets)
214 if (Abis.Any() && !Abis.Any (target.Triple.Contains))
215 continue;
217 Console.WriteLine();
218 Console.WriteLine("Processing triple: {0}", target.Triple);
220 var options = new DriverOptions();
222 var log = new TextDiagnosticPrinter();
223 var driver = new Driver(options, log);
225 Setup(driver, target);
226 driver.Setup();
228 BuildParseOptions(driver, target);
229 if (!driver.ParseCode())
230 return;
232 Dump(driver.Context.ASTContext, driver.Context.TargetInfo, target);
236 static void BuildParseOptions(Driver driver, Target target)
238 foreach (var header in driver.Options.Headers)
240 var source = driver.Project.AddFile(header);
241 source.Options = driver.BuildParserOptions(source);
243 if (header.Contains ("mini"))
244 continue;
246 source.Options.AddDefines ("HAVE_SGEN_GC");
247 source.Options.AddDefines ("HAVE_MOVING_COLLECTOR");
251 static string GetAndroidNdkPath()
253 if (!String.IsNullOrEmpty (AndroidNdkPath))
254 return AndroidNdkPath;
256 // Find the Android NDK's path from Monodroid's config.
257 var configFile = Path.Combine(MonodroidDir, "env.config");
258 if (!File.Exists(configFile))
259 throw new Exception("Expected a valid Monodroid environment config file at " + configFile);
261 var config = File.ReadAllText(configFile);
262 var match = Regex.Match(config, @"ANDROID_NDK_PATH\s*:=\s(.*)");
263 return match.Groups[1].Value.Trim();
266 static void ParseCommandLineArgs(string[] args)
268 var showHelp = false;
270 var options = new Mono.Options.OptionSet () {
271 { "abi=", "ABI triple to generate", v => Abis.Add(v) },
272 { "o|out=", "output directory", v => OutputDir = v },
273 { "maccore=", "include directory", v => MaccoreDir = v },
274 { "monodroid=", "top monodroid directory", v => MonodroidDir = v },
275 { "android-ndk=", "Path to Android NDK", v => AndroidNdkPath = v },
276 { "targetdir=", "Path to the directory containing the mono build", v =>TargetDir = v },
277 { "mono=", "include directory", v => MonoDir = v },
278 { "h|help", "show this message and exit", v => showHelp = v != null },
281 try {
282 options.Parse (args);
284 catch (Mono.Options.OptionException e) {
285 Console.WriteLine (e.Message);
286 Environment.Exit(0);
289 if (showHelp)
291 // Print usage and exit.
292 Console.WriteLine("{0} <options>",
293 AppDomain.CurrentDomain.FriendlyName);
294 options.WriteOptionDescriptions (Console.Out);
295 Environment.Exit(0);
299 static void Setup(Driver driver, Target target)
301 var options = driver.Options;
302 options.DryRun = true;
303 options.LibraryName = "Mono";
305 var parserOptions = driver.ParserOptions;
306 parserOptions.Verbose = false;
307 parserOptions.MicrosoftMode = false;
308 parserOptions.AddArguments("-xc");
309 parserOptions.AddArguments("-std=gnu99");
310 parserOptions.AddDefines("CPPSHARP");
312 foreach (var define in target.Defines)
313 parserOptions.AddDefines(define);
315 SetupToolchainPaths(driver, target);
317 SetupMono(driver, target);
320 static void SetupMono(Driver driver, Target target)
322 string targetBuild;
323 switch (target.Platform) {
324 case TargetPlatform.Android:
325 if (TargetDir == "") {
326 Console.Error.WriteLine ("The --targetdir= option is required when targeting android.");
327 Environment.Exit (1);
329 if (MonoDir == "") {
330 Console.Error.WriteLine ("The --mono= option is required when targeting android.");
331 Environment.Exit (1);
333 if (Abis.Count != 1) {
334 Console.Error.WriteLine ("Exactly one --abi= argument is required when targeting android.");
335 Environment.Exit (1);
337 targetBuild = TargetDir;
338 break;
339 case TargetPlatform.WatchOS:
340 case TargetPlatform.iOS: {
341 string targetPath = Path.Combine (MaccoreDir, "builds");
342 if (!Directory.Exists (MonoDir))
343 MonoDir = Path.GetFullPath (Path.Combine (targetPath, "../../mono"));
344 targetBuild = Path.Combine(targetPath, target.Build);
345 break;
347 default:
348 throw new ArgumentOutOfRangeException ();
351 if (!Directory.Exists(targetBuild))
352 throw new Exception(string.Format("Could not find the target build directory: {0}", targetBuild));
354 var includeDirs = new[]
356 targetBuild,
357 Path.Combine(targetBuild, "eglib", "src"),
358 MonoDir,
359 Path.Combine(MonoDir, "mono"),
360 Path.Combine(MonoDir, "mono", "mini"),
361 Path.Combine(MonoDir, "eglib", "src")
364 foreach (var inc in includeDirs)
365 driver.ParserOptions.AddIncludeDirs(inc);
367 var filesToParse = new[]
369 Path.Combine(MonoDir, "mono", "metadata", "metadata-cross-helpers.c"),
370 Path.Combine(MonoDir, "mono", "mini", "mini-cross-helpers.c"),
373 foreach (var file in filesToParse)
374 driver.Options.Headers.Add(file);
377 static void SetupMSVC(Driver driver, string triple)
379 var parserOptions = driver.ParserOptions;
381 parserOptions.Abi = Parser.AST.CppAbi.Microsoft;
382 parserOptions.MicrosoftMode = true;
384 var systemIncludeDirs = new[]
386 @"C:\Program Files (x86)\Windows Kits\8.1\Include\um",
387 @"C:\Program Files (x86)\Windows Kits\8.1\Include\shared"
390 foreach (var inc in systemIncludeDirs)
391 parserOptions.AddSystemIncludeDirs(inc);
393 parserOptions.AddDefines("HOST_WIN32");
396 static void SetupToolchainPaths(Driver driver, Target target)
398 switch (target.Platform) {
399 case TargetPlatform.Android:
400 SetupAndroidNDK(driver, target);
401 break;
402 case TargetPlatform.iOS:
403 case TargetPlatform.WatchOS:
404 SetupXcode(driver, target);
405 break;
406 default:
407 throw new ArgumentOutOfRangeException ();
411 static string GetArchFromTriple(string triple)
413 if (triple.Contains("mips"))
414 return "mips";
416 if (triple.Contains("arm64") || triple.Contains("aarch64"))
417 return "arm64";
419 if (triple.Contains("arm"))
420 return "arm";
422 if (triple.Contains("i686"))
423 return "x86";
425 if (triple.Contains("x86_64"))
426 return "x86_64";
428 throw new Exception("Unknown architecture from triple: " + triple);
431 static string GetXcodeToolchainPath()
433 var toolchains = Directory.EnumerateDirectories("/Applications", "Xcode*")
434 .ToList();
435 toolchains.Sort();
437 var toolchainPath = toolchains.LastOrDefault();
438 if (toolchainPath == null)
439 throw new Exception("Could not find a valid Xcode SDK");
441 return toolchainPath;
444 static string GetXcodeBuiltinIncludesFolder()
446 var toolchainPath = GetXcodeToolchainPath();
448 var toolchains = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
449 "Contents/Developer/Toolchains")).ToList();
450 toolchains.Sort();
452 toolchainPath = toolchains.LastOrDefault();
453 if (toolchainPath == null)
454 throw new Exception("Could not find a valid Xcode toolchain");
456 var includePaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
457 "usr/lib/clang")).ToList();
458 var includePath = includePaths.LastOrDefault();
460 if (includePath == null)
461 throw new Exception("Could not find a valid Clang include folder");
463 return Path.Combine(includePath, "include");
466 static string GetXcodeiOSIncludesFolder()
468 var toolchainPath = GetXcodeToolchainPath();
470 var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
471 "Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs")).ToList();
472 var sdkPath = sdkPaths.LastOrDefault();
474 if (sdkPath == null)
475 throw new Exception("Could not find a valid iPhone SDK");
477 return Path.Combine(sdkPath, "usr/include");
480 static string GetXcodeWatchOSIncludesFolder()
482 var toolchainPath = GetXcodeToolchainPath();
484 var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
485 "Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs")).ToList();
486 var sdkPath = sdkPaths.LastOrDefault();
488 if (sdkPath == null)
489 throw new Exception("Could not find a valid WatchOS SDK");
491 return Path.Combine(sdkPath, "usr/include");
494 static void SetupXcode(Driver driver, Target target)
496 var parserOptions = driver.ParserOptions;
498 var builtinsPath = GetXcodeBuiltinIncludesFolder();
499 string includePath;
501 switch (target.Platform) {
502 case TargetPlatform.iOS:
503 includePath = GetXcodeiOSIncludesFolder();
504 break;
505 case TargetPlatform.WatchOS:
506 includePath = GetXcodeWatchOSIncludesFolder();
507 break;
508 default:
509 throw new ArgumentOutOfRangeException ();
512 parserOptions.AddSystemIncludeDirs(builtinsPath);
513 parserOptions.AddSystemIncludeDirs(includePath);
515 parserOptions.NoBuiltinIncludes = true;
516 parserOptions.NoStandardIncludes = true;
517 parserOptions.TargetTriple = target.Triple;
520 static string GetAndroidHostToolchainPath()
522 var androidNdkPath = GetAndroidNdkPath ();
523 var toolchains = Directory.EnumerateDirectories(
524 Path.Combine(androidNdkPath, "toolchains"), "llvm*").ToList();
525 toolchains.Sort();
527 var toolchainPath = toolchains.LastOrDefault();
528 if (toolchainPath == null)
529 throw new Exception("Could not find a valid NDK host toolchain");
531 toolchains = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
532 "prebuilt")).ToList();
533 toolchains.Sort();
535 toolchainPath = toolchains.LastOrDefault();
536 if (toolchainPath == null)
537 throw new Exception("Could not find a valid NDK host toolchain");
539 return toolchainPath;
542 static string GetAndroidBuiltinIncludesFolder()
544 var toolchainPath = GetAndroidHostToolchainPath();
546 string clangToolchainPath = Path.Combine(toolchainPath, "lib64", "clang");
547 if (!Directory.Exists (clangToolchainPath))
548 clangToolchainPath = Path.Combine(toolchainPath, "lib", "clang");
550 string includePath = null;
551 if (Directory.Exists (clangToolchainPath)) {
552 var includePaths = Directory.EnumerateDirectories(clangToolchainPath).ToList();
553 includePath = includePaths.LastOrDefault();
555 if (includePath == null)
556 throw new Exception("Could not find a valid Clang include folder");
558 return Path.Combine(includePath, "include");
561 static void SetupAndroidNDK(Driver driver, Target target)
563 var options = driver.Options;
564 var parserOptions = driver.ParserOptions;
566 var builtinsPath = GetAndroidBuiltinIncludesFolder();
567 parserOptions.AddSystemIncludeDirs(builtinsPath);
569 var androidNdkRoot = GetAndroidNdkPath ();
570 const int androidNdkApiLevel = 21;
572 var toolchainPath = Path.Combine(androidNdkRoot, "platforms",
573 "android-" + androidNdkApiLevel, "arch-" + GetArchFromTriple(target.Triple),
574 "usr", "include");
575 parserOptions.AddSystemIncludeDirs(toolchainPath);
577 parserOptions.NoBuiltinIncludes = true;
578 parserOptions.NoStandardIncludes = true;
579 parserOptions.TargetTriple = target.Triple;
582 static uint GetTypeAlign(ParserTargetInfo target, ParserIntType type)
584 switch (type)
586 case ParserIntType.SignedChar:
587 case ParserIntType.UnsignedChar:
588 return target.CharAlign;
589 case ParserIntType.SignedShort:
590 case ParserIntType.UnsignedShort:
591 return target.ShortAlign;
592 case ParserIntType.SignedInt:
593 case ParserIntType.UnsignedInt:
594 return target.IntAlign;
595 case ParserIntType.SignedLong:
596 case ParserIntType.UnsignedLong:
597 return target.LongAlign;
598 case ParserIntType.SignedLongLong:
599 case ParserIntType.UnsignedLongLong:
600 return target.LongLongAlign;
601 default:
602 throw new Exception("Type has no alignment");
606 static uint GetTypeSize(ParserTargetInfo target, ParserIntType type)
608 switch (type)
610 case ParserIntType.SignedChar:
611 case ParserIntType.UnsignedChar:
612 return target.CharWidth;
613 case ParserIntType.SignedShort:
614 case ParserIntType.UnsignedShort:
615 return target.ShortWidth;
616 case ParserIntType.SignedInt:
617 case ParserIntType.UnsignedInt:
618 return target.IntWidth;
619 case ParserIntType.SignedLong:
620 case ParserIntType.UnsignedLong:
621 return target.LongWidth;
622 case ParserIntType.SignedLongLong:
623 case ParserIntType.UnsignedLongLong:
624 return target.LongLongWidth;
625 default:
626 throw new Exception("Type has no size");
630 static string GetTargetPlatformDefine(TargetPlatform target)
632 switch (target) {
633 case TargetPlatform.Android:
634 return "TARGET_ANDROID";
635 case TargetPlatform.iOS:
636 return "TARGET_IOS";
637 case TargetPlatform.WatchOS:
638 return "TARGET_WATCHOS";
639 default:
640 throw new ArgumentOutOfRangeException ();
644 static void Dump(ASTContext ctx, ParserTargetInfo targetInfo, Target target)
646 var targetFile = target.Triple;
648 if (!string.IsNullOrEmpty (OutputDir))
649 targetFile = Path.Combine (OutputDir, targetFile);
651 targetFile += ".h";
653 using (var writer = new StreamWriter(targetFile))
654 //using (var writer = Console.Out)
656 writer.WriteLine("#ifndef USED_CROSS_COMPILER_OFFSETS");
657 writer.WriteLine("#ifdef {0}", target.Defines[0]);
658 writer.WriteLine ("#ifdef {0}", GetTargetPlatformDefine (target.Platform));
659 writer.WriteLine("#ifndef HAVE_BOEHM_GC");
660 writer.WriteLine("#define HAS_CROSS_COMPILER_OFFSETS");
661 writer.WriteLine("#if defined (USE_CROSS_COMPILE_OFFSETS) || defined (MONO_CROSS_COMPILE)");
662 writer.WriteLine("#if !defined (DISABLE_METADATA_OFFSETS)");
663 writer.WriteLine("#define USED_CROSS_COMPILER_OFFSETS");
665 DumpAligns(writer, targetInfo);
666 DumpSizes(writer, targetInfo);
667 DumpMetadataOffsets(writer, ctx, target);
669 writer.WriteLine("#endif //disable metadata check");
671 DumpJITOffsets(writer, ctx);
673 writer.WriteLine("#endif //cross compiler checks");
674 writer.WriteLine("#endif //gc check");
675 writer.WriteLine("#endif //os check");
676 writer.WriteLine("#endif //arch check");
677 writer.WriteLine("#endif //USED_CROSS_COMPILER_OFFSETS check");
680 Console.WriteLine("Generated offsets file: {0}", targetFile);
683 static void DumpAligns(TextWriter writer, ParserTargetInfo target)
685 var aligns = new[]
687 new { Name = "gint8", Align = target.CharAlign},
688 new { Name = "gint16", Align = target.ShortAlign},
689 new { Name = "gint32", Align = target.IntAlign},
690 new { Name = "gint64", Align = GetTypeAlign(target, target.Int64Type)},
691 new { Name = "float", Align = target.FloatAlign},
692 new { Name = "double", Align = target.DoubleAlign},
693 new { Name = "gpointer", Align = GetTypeAlign(target, target.IntPtrType)},
696 // Write the alignment info for the basic types.
697 foreach (var align in aligns)
698 writer.WriteLine("DECL_ALIGN2({0},{1})", align.Name, align.Align / 8);
701 static void DumpSizes(TextWriter writer, ParserTargetInfo target)
703 var sizes = new[]
705 new { Name = "gint8", Size = target.CharWidth},
706 new { Name = "gint16", Size = target.ShortWidth},
707 new { Name = "gint32", Size = target.IntWidth},
708 new { Name = "gint64", Size = GetTypeSize(target, target.Int64Type)},
709 new { Name = "float", Size = target.FloatWidth},
710 new { Name = "double", Size = target.DoubleWidth},
711 new { Name = "gpointer", Size = GetTypeSize(target, target.IntPtrType)},
714 // Write the size info for the basic types.
715 foreach (var size in sizes)
716 writer.WriteLine("DECL_SIZE2({0},{1})", size.Name, size.Size / 8);
719 static Class GetClassFromTypedef(ITypedDecl typedef)
721 var type = typedef.Type.Desugar() as TagType;
722 if (type == null)
723 return null;
725 var @class = type.Declaration as Class;
727 return @class.IsIncomplete ?
728 (@class.CompleteDeclaration as Class) : @class;
731 static void DumpClasses(TextWriter writer, ASTContext ctx, IEnumerable<string> types,
732 bool optional = false)
734 foreach (var @struct in types)
736 var @class = ctx.FindCompleteClass(@struct);
737 if (@class == null)
738 @class = ctx.FindCompleteClass("_" + @struct);
740 if (@class == null)
742 var typedef = ctx.FindTypedef(@struct).FirstOrDefault(
743 decl => !decl.IsIncomplete);
745 if (typedef != null)
746 @class = GetClassFromTypedef(typedef);
749 if (@class == null && optional)
750 continue;
752 if (@class == null)
753 throw new Exception("Expected to find struct definition for " + @struct);
755 DumpStruct(writer, @class);
759 static void DumpMetadataOffsets(TextWriter writer, ASTContext ctx, Target target)
761 var types = new List<string>
763 "MonoObject",
764 "MonoObjectHandlePayload",
765 "MonoClass",
766 "MonoVTable",
767 "MonoDelegate",
768 "MonoInternalThread",
769 "MonoMulticastDelegate",
770 "MonoTransparentProxy",
771 "MonoRealProxy",
772 "MonoRemoteClass",
773 "MonoArray",
774 "MonoArrayBounds",
775 "MonoSafeHandle",
776 "MonoHandleRef",
777 "MonoComInteropProxy",
778 "MonoString",
779 "MonoException",
780 "MonoTypedRef",
781 "MonoThreadsSync",
782 "SgenThreadInfo",
783 "SgenClientThreadInfo"
786 DumpClasses(writer, ctx, types);
789 static void DumpJITOffsets(TextWriter writer, ASTContext ctx)
791 writer.WriteLine("#ifndef DISABLE_JIT_OFFSETS");
792 writer.WriteLine("#define USED_CROSS_COMPILER_OFFSETS");
794 var types = new[]
796 "MonoLMF",
797 "MonoMethodRuntimeGenericContext",
798 "MonoJitTlsData",
799 "MonoGSharedVtMethodRuntimeInfo",
800 "MonoContinuation",
801 "MonoContext",
802 "MonoDelegateTrampInfo",
805 DumpClasses(writer, ctx, types);
807 var optionalTypes = new[]
809 "GSharedVtCallInfo",
810 "SeqPointInfo",
811 "DynCallArgs",
812 "MonoLMFTramp",
815 DumpClasses(writer, ctx, optionalTypes, optional: true);
817 writer.WriteLine("#endif //disable jit check");
820 static void DumpStruct(TextWriter writer, Class @class)
822 var name = @class.Name;
823 if (name.StartsWith ("_", StringComparison.Ordinal))
824 name = name.Substring (1);
826 foreach (var field in @class.Fields)
828 if (field.IsBitField) continue;
830 if (name == "SgenThreadInfo" && field.Name == "regs")
831 continue;
833 var layout = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr);
835 writer.WriteLine("DECL_OFFSET2({0},{1},{2})", name, field.Name,
836 layout.Offset);