Fix http framework module that errors using SDK 2.1.801 (#15844)
[mono-project.git] / tools / offsets-tool / MonoAotOffsetsDumper.cs
blobe20df920f78baa401fde4db2e2ae08d2d28eec2f
1 // -*- indent-tabs-mode:nil -*-
2 using System;
3 using System.Collections.Generic;
4 using System.IO;
5 using System.Linq;
6 using System.Text.RegularExpressions;
7 using CppSharp.AST;
8 using CppSharp.AST.Extensions;
9 using CppSharp.Parser;
11 namespace CppSharp
13 /**
14 * This tool dumps the offsets of structures used in the Mono VM needed
15 * by the AOT compiler for cross-compiling code to target platforms
16 * different than the host the compiler is being invoked on.
18 static class MonoAotOffsetsDumper
20 static string MonoDir = @"";
22 static List<string> Abis = new List<string> ();
23 static string OutputDir;
24 static string OutputFile;
26 static string AndroidNdkPath = @"";
27 static string EmscriptenSdkPath = @"";
28 static string TargetDir = @"";
29 static bool GenIOS;
30 static bool GenAndroid;
32 public enum TargetPlatform
34 Android,
35 iOS,
36 WatchOS,
37 OSX,
38 WASM
41 public class Target
43 public Target()
45 Defines = new List<string>();
46 Arguments = new List<string>();
49 public Target(Target target)
51 Platform = target.Platform;
52 Triple = target.Triple;
53 Build = target.Build;
54 Defines = target.Defines;
55 Arguments = target.Arguments;
58 public TargetPlatform Platform;
59 public string Triple;
60 public string Build;
61 public List<string> Defines;
62 public List<string> Arguments;
65 public static List<Target> Targets = new List<Target>();
67 public static IEnumerable<Target> AndroidTargets
69 get { return Targets.Where ((t) => t.Platform == TargetPlatform.Android); }
72 public static IEnumerable<Target> DarwinTargets
74 get
76 return Targets.Where ((t) =>
77 t.Platform == TargetPlatform.iOS ||
78 t.Platform == TargetPlatform.WatchOS ||
79 t.Platform == TargetPlatform.OSX);
83 public static IEnumerable<Target> iOSTargets
85 get
87 return Targets.Where ((t) => t.Platform == TargetPlatform.iOS);
91 public static void SetupAndroidTargets()
93 Targets.Add (new Target {
94 Platform = TargetPlatform.Android,
95 Triple = "i686-none-linux-android",
96 Defines = { "TARGET_X86" }
97 });
99 Targets.Add (new Target {
100 Platform = TargetPlatform.Android,
101 Triple = "x86_64-none-linux-android",
102 Defines = { "TARGET_AMD64" }
103 });
105 Targets.Add (new Target {
106 Platform = TargetPlatform.Android,
107 Triple = "armv5-none-linux-androideabi",
108 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
111 Targets.Add (new Target {
112 Platform = TargetPlatform.Android,
113 Triple = "armv7-none-linux-androideabi",
114 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5", "HAVE_ARMV6",
115 "HAVE_ARMV7"
119 Targets.Add (new Target {
120 Platform = TargetPlatform.Android,
121 Triple = "aarch64-v8a-linux-android",
122 Defines = { "TARGET_ARM64" }
123 });
125 /*Targets.Add(new Target {
126 Platform = TargetPlatform.Android,
127 Triple = "mipsel-none-linux-android",
128 Defines = { "TARGET_MIPS", "__mips__" }
129 });*/
131 foreach (var target in AndroidTargets)
132 target.Defines.AddRange (new string[] { "HOST_ANDROID",
133 "TARGET_ANDROID", "MONO_CROSS_COMPILE", "USE_MONO_CTX",
134 "BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD"
138 public static void SetupiOSTargets()
140 Targets.Add(new Target {
141 Platform = TargetPlatform.iOS,
142 Triple = "arm-apple-darwin10",
143 Build = "target7",
144 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
147 Targets.Add(new Target {
148 Platform = TargetPlatform.iOS,
149 Triple = "aarch64-apple-darwin10",
150 Build = "target64",
151 Defines = { "TARGET_ARM64" }
154 foreach (var target in iOSTargets) {
155 target.Defines.AddRange (new string[] { "HOST_DARWIN",
156 "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX",
157 "_XOPEN_SOURCE"
161 Targets.Add(new Target {
162 Platform = TargetPlatform.WatchOS,
163 Triple = "armv7k-apple-darwin",
164 Build = "targetwatch",
165 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
168 Targets.Add(new Target {
169 Platform = TargetPlatform.WatchOS,
170 Triple = "armv7k-apple-darwin_ilp32", /* fake triple, aarch64-apple-darwin_ilp32 isn't recognized correctly */
171 Build = "targetwatch64_32",
172 Defines = { "TARGET_ARM64", "MONO_ARCH_ILP32", "MONO_CPPSHARP_HACK" }
175 foreach (var target in DarwinTargets) {
176 target.Defines.AddRange (new string[] { "HOST_DARWIN",
177 "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX",
178 "_XOPEN_SOURCE"
183 public static void SetupOtherTargets()
185 if (Abis.Count != 1) {
186 Console.WriteLine ("Exactly --abi= argument is required.");
187 Environment.Exit (1);
189 string abi = Abis [0];
190 if (abi == "i386-apple-darwin13.0.0") {
191 Targets.Add(new Target {
192 Platform = TargetPlatform.OSX,
193 Triple = "i386-apple-darwin13.0.0",
194 Build = "",
195 Defines = { "TARGET_X86" },
197 } else if (abi == "wasm32-unknown-unknown") {
198 Targets.Add(new Target {
199 Platform = TargetPlatform.WASM,
200 Triple = "wasm32-unknown-unknown",
201 Build = "",
202 Defines = { "TARGET_WASM" },
204 } else {
205 Console.WriteLine ($"Unsupported abi: {abi}.");
206 Environment.Exit (1);
210 static bool GetParentSubDirectoryPath(string parent, out string subdir)
212 var directory = Directory.GetParent(Directory.GetCurrentDirectory());
214 while (directory != null) {
215 var path = Path.Combine(directory.FullName, parent);
217 if (Directory.Exists (path)) {
218 subdir = path;
219 return true;
222 directory = directory.Parent;
225 subdir = null;
226 return false;
229 public static int Main(string[] args)
231 ParseCommandLineArgs(args);
233 if (GenAndroid)
234 SetupAndroidTargets();
236 if (GenIOS)
237 SetupiOSTargets();
239 if (Targets.Count == 0)
240 SetupOtherTargets ();
242 foreach (var target in Targets)
244 if (Abis.Any() && !Abis.Contains (target.Triple))
245 continue;
247 Console.WriteLine();
248 Console.WriteLine("Processing triple: {0}", target.Triple);
250 var options = new DriverOptions();
252 var driver = new Driver(options);
254 Setup(driver, target);
255 driver.Setup();
257 BuildParseOptions(driver, target);
258 if (!driver.ParseCode())
259 return 1;
261 Dump(driver.Context.ASTContext, driver.Context.TargetInfo, target);
263 return 0;
266 static void BuildParseOptions(Driver driver, Target target)
268 foreach (var header in driver.Options.Headers)
270 var source = driver.Project.AddFile(header);
271 source.Options = driver.BuildParserOptions(source);
273 if (header.Contains ("mini"))
274 continue;
276 source.Options.AddDefines ("HAVE_SGEN_GC");
277 source.Options.AddDefines ("HAVE_MOVING_COLLECTOR");
278 source.Options.AddDefines("MONO_GENERATING_OFFSETS");
282 static void ParseCommandLineArgs(string[] args)
284 var showHelp = false;
286 var options = new Mono.Options.OptionSet () {
287 { "abi=", "ABI triple to generate", v => Abis.Add(v) },
288 { "o|out=", "output directory", v => OutputDir = v },
289 { "outfile=", "output directory", v => OutputFile = v },
290 { "android-ndk=", "Path to Android NDK", v => AndroidNdkPath = v },
291 { "emscripten-sdk=", "Path to emscripten sdk", v => EmscriptenSdkPath = v },
292 { "targetdir=", "Path to the directory containing the mono build", v =>TargetDir = v },
293 { "mono=", "include directory", v => MonoDir = v },
294 { "gen-ios", "generate iOS offsets", v => GenIOS = v != null },
295 { "gen-android", "generate Android offsets", v => GenAndroid = v != null },
296 { "h|help", "show this message and exit", v => showHelp = v != null },
299 try {
300 options.Parse (args);
302 catch (Mono.Options.OptionException e) {
303 Console.WriteLine (e.Message);
304 Environment.Exit(0);
307 if (showHelp)
309 // Print usage and exit.
310 Console.WriteLine("{0} <options>",
311 AppDomain.CurrentDomain.FriendlyName);
312 options.WriteOptionDescriptions (Console.Out);
313 Environment.Exit(0);
317 static void Setup(Driver driver, Target target)
319 var options = driver.Options;
320 options.DryRun = true;
321 options.LibraryName = "Mono";
323 var parserOptions = driver.ParserOptions;
324 parserOptions.Verbose = false;
325 parserOptions.MicrosoftMode = false;
326 parserOptions.AddArguments("-xc");
327 parserOptions.AddArguments("-std=gnu99");
328 parserOptions.AddDefines("CPPSHARP");
329 parserOptions.AddDefines("MONO_GENERATING_OFFSETS");
331 foreach (var define in target.Defines)
332 parserOptions.AddDefines(define);
334 SetupToolchainPaths(driver, target);
336 SetupMono(driver, target);
339 static void SetupMono(Driver driver, Target target)
341 string targetBuild;
342 switch (target.Platform) {
343 case TargetPlatform.Android:
344 if (string.IsNullOrEmpty (TargetDir)) {
345 Console.Error.WriteLine ("The --targetdir= option is required when targeting android.");
346 Environment.Exit (1);
348 if (string.IsNullOrEmpty (MonoDir)) {
349 Console.Error.WriteLine ("The --mono= option is required when targeting android.");
350 Environment.Exit (1);
352 if (string.IsNullOrEmpty(AndroidNdkPath)) {
353 Console.WriteLine("The --android-ndk= option is required when targeting android");
354 Environment.Exit (1);
356 if (Abis.Count != 1) {
357 Console.Error.WriteLine ("Exactly one --abi= argument is required when targeting android.");
358 Environment.Exit (1);
360 targetBuild = TargetDir;
361 break;
362 case TargetPlatform.WatchOS:
363 case TargetPlatform.iOS: {
364 if (string.IsNullOrEmpty (TargetDir)) {
365 Console.Error.WriteLine ("The --targetdir= option is required when targeting ios.");
366 Environment.Exit (1);
368 if (string.IsNullOrEmpty (MonoDir)) {
369 Console.Error.WriteLine ("The --mono= option is required when targeting ios.");
370 Environment.Exit (1);
372 targetBuild = TargetDir;
373 break;
375 case TargetPlatform.OSX:
376 case TargetPlatform.WASM:
377 if (MonoDir == "") {
378 Console.Error.WriteLine ("The --mono= option is required when targeting osx.");
379 Environment.Exit (1);
381 if (!string.IsNullOrEmpty (TargetDir)) {
382 targetBuild = TargetDir;
383 } else {
384 targetBuild = ".";
386 break;
387 default:
388 throw new ArgumentOutOfRangeException ();
391 if (!Directory.Exists(targetBuild))
392 throw new Exception(string.Format("Could not find the target build directory: {0}", targetBuild));
394 var includeDirs = new[]
396 targetBuild,
397 Path.Combine(targetBuild, "mono", "eglib"),
398 MonoDir,
399 Path.Combine(MonoDir, "mono"),
400 Path.Combine(MonoDir, "mono", "mini"),
401 Path.Combine(MonoDir, "mono", "eglib")
404 foreach (var inc in includeDirs)
405 driver.ParserOptions.AddIncludeDirs(inc);
407 var filesToParse = new[]
409 Path.Combine(MonoDir, "mono", "metadata", "metadata-cross-helpers.c"),
410 Path.Combine(MonoDir, "mono", "mini", "mini-cross-helpers.c"),
413 foreach (var file in filesToParse)
414 driver.Options.Headers.Add(file);
417 static void SetupMSVC(Driver driver, string triple)
419 var parserOptions = driver.ParserOptions;
421 parserOptions.Abi = Parser.AST.CppAbi.Microsoft;
422 parserOptions.MicrosoftMode = true;
424 var systemIncludeDirs = new[]
426 @"C:\Program Files (x86)\Windows Kits\8.1\Include\um",
427 @"C:\Program Files (x86)\Windows Kits\8.1\Include\shared"
430 foreach (var inc in systemIncludeDirs)
431 parserOptions.AddSystemIncludeDirs(inc);
433 parserOptions.AddDefines("HOST_WIN32");
436 static void SetupToolchainPaths(Driver driver, Target target)
438 switch (target.Platform) {
439 case TargetPlatform.Android:
440 SetupAndroidNDK(driver, target);
441 break;
442 case TargetPlatform.iOS:
443 case TargetPlatform.WatchOS:
444 case TargetPlatform.OSX:
445 SetupXcode(driver, target);
446 break;
447 case TargetPlatform.WASM:
448 if (EmscriptenSdkPath == "") {
449 Console.Error.WriteLine ("The --emscripten-sdk= option is required when targeting wasm.");
450 Environment.Exit (1);
452 string include_dir = Path.Combine (EmscriptenSdkPath, "system", "include", "libc");
453 if (!Directory.Exists (include_dir)) {
454 Console.Error.WriteLine ($"emscripten include directory {include_dir} does not exist.");
455 Environment.Exit (1);
457 var parserOptions = driver.ParserOptions;
458 parserOptions.NoBuiltinIncludes = true;
459 parserOptions.NoStandardIncludes = true;
460 parserOptions.TargetTriple = target.Triple;
461 parserOptions.AddSystemIncludeDirs(include_dir);
462 break;
463 default:
464 throw new ArgumentOutOfRangeException ();
468 static string GetArchFromTriple(string triple)
470 if (triple.Contains("mips"))
471 return "mips";
473 if (triple.Contains("arm64") || triple.Contains("aarch64"))
474 return "arm64";
476 if (triple.Contains("arm"))
477 return "arm";
479 if (triple.Contains("i686"))
480 return "x86";
482 if (triple.Contains("x86_64"))
483 return "x86_64";
485 throw new Exception("Unknown architecture from triple: " + triple);
488 static string GetXcodeToolchainPath()
490 var toolchains = Directory.EnumerateDirectories("/Applications", "Xcode*")
491 .ToList();
492 toolchains.Sort();
494 var toolchainPath = toolchains.LastOrDefault();
495 if (toolchainPath == null)
496 throw new Exception("Could not find a valid Xcode SDK");
498 return toolchainPath;
501 static string GetXcodeBuiltinIncludesFolder()
503 var toolchainPath = GetXcodeToolchainPath();
505 var toolchains = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
506 "Contents/Developer/Toolchains")).ToList();
507 toolchains.Sort();
509 toolchainPath = toolchains.LastOrDefault();
510 if (toolchainPath == null)
511 throw new Exception("Could not find a valid Xcode toolchain");
513 var includePaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
514 "usr/lib/clang")).ToList();
515 var includePath = includePaths.LastOrDefault();
517 if (includePath == null)
518 throw new Exception("Could not find a valid Clang include folder");
520 return Path.Combine(includePath, "include");
523 static string GetXcodeiOSIncludesFolder()
525 var toolchainPath = GetXcodeToolchainPath();
527 var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
528 "Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs")).ToList();
529 var sdkPath = sdkPaths.LastOrDefault();
531 if (sdkPath == null)
532 throw new Exception("Could not find a valid iPhone SDK");
534 return Path.Combine(sdkPath, "usr/include");
537 static string GetXcodeOSXIncludesFolder()
539 var toolchainPath = GetXcodeToolchainPath();
541 var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
542 "Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs")).ToList();
543 var sdkPath = sdkPaths.LastOrDefault();
545 if (sdkPath == null)
546 throw new Exception("Could not find a valid OSX SDK");
548 return Path.Combine(sdkPath, "usr/include");
551 static string GetXcodeWatchOSIncludesFolder()
553 var toolchainPath = GetXcodeToolchainPath();
555 var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
556 "Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs")).ToList();
557 var sdkPath = sdkPaths.LastOrDefault();
559 if (sdkPath == null)
560 throw new Exception("Could not find a valid WatchOS SDK");
562 return Path.Combine(sdkPath, "usr/include");
565 static void SetupXcode(Driver driver, Target target)
567 var parserOptions = driver.ParserOptions;
569 var builtinsPath = GetXcodeBuiltinIncludesFolder();
570 string includePath;
572 switch (target.Platform) {
573 case TargetPlatform.iOS:
574 includePath = GetXcodeiOSIncludesFolder();
575 break;
576 case TargetPlatform.WatchOS:
577 includePath = GetXcodeWatchOSIncludesFolder();
578 break;
579 case TargetPlatform.OSX:
580 includePath = GetXcodeOSXIncludesFolder();
581 break;
582 default:
583 throw new ArgumentOutOfRangeException ();
586 parserOptions.AddSystemIncludeDirs(builtinsPath);
587 parserOptions.AddSystemIncludeDirs(includePath);
589 parserOptions.NoBuiltinIncludes = true;
590 parserOptions.NoStandardIncludes = true;
591 parserOptions.TargetTriple = target.Triple;
594 static string GetAndroidHostToolchainPath()
596 var toolchains = Directory.EnumerateDirectories(
597 Path.Combine(AndroidNdkPath, "toolchains"), "llvm*").ToList();
598 toolchains.Sort();
600 var toolchainPath = toolchains.LastOrDefault();
601 if (toolchainPath == null)
602 throw new Exception("Could not find a valid NDK host toolchain");
604 toolchains = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
605 "prebuilt")).ToList();
606 toolchains.Sort();
608 toolchainPath = toolchains.LastOrDefault();
609 if (toolchainPath == null)
610 throw new Exception("Could not find a valid NDK host toolchain");
612 return toolchainPath;
615 static string GetAndroidBuiltinIncludesFolder()
617 var toolchainPath = GetAndroidHostToolchainPath();
619 string clangToolchainPath = Path.Combine(toolchainPath, "lib64", "clang");
620 if (!Directory.Exists (clangToolchainPath))
621 clangToolchainPath = Path.Combine(toolchainPath, "lib", "clang");
623 string includePath = null;
624 if (Directory.Exists (clangToolchainPath)) {
625 var includePaths = Directory.EnumerateDirectories(clangToolchainPath).ToList();
626 includePath = includePaths.LastOrDefault();
628 if (includePath == null)
629 throw new Exception("Could not find a valid Clang include folder");
631 return Path.Combine(includePath, "include");
634 static void SetupAndroidNDK(Driver driver, Target target)
636 var options = driver.Options;
637 var parserOptions = driver.ParserOptions;
639 var builtinsPath = GetAndroidBuiltinIncludesFolder();
640 parserOptions.AddSystemIncludeDirs(builtinsPath);
642 const int androidNdkApiLevel = 21;
644 string arch = GetArchFromTriple(target.Triple);
645 var toolchainPath = Path.Combine(AndroidNdkPath, "platforms",
646 "android-" + androidNdkApiLevel, "arch-" + arch,
647 "usr", "include");
649 if (!Directory.Exists (toolchainPath)) {
650 // Android NDK r17 and newer no longer have per-platform include directories, they instead use a
651 // unified set of headers
652 toolchainPath = Path.Combine (AndroidNdkPath, "sysroot", "usr", "include");
654 // The unified headers require that the target API level is defined as a macro - that's how they
655 // differentiate between native APIs available for the given API level
656 parserOptions.AddDefines ($"__ANDROID_API__={androidNdkApiLevel}");
658 // And they also need to point to the per-arch `asm` directory
659 string asmTriple;
660 switch (arch) {
661 case "arm64":
662 asmTriple = "aarch64-linux-android";
663 break;
665 case "arm":
666 asmTriple = "arm-linux-androideabi";
667 break;
669 case "x86":
670 asmTriple = "i686-linux-android";
671 break;
673 case "x86_64":
674 asmTriple = "x86_64-linux-android";
675 break;
677 default:
678 throw new Exception ($"Unsupported architecture {arch}");
681 parserOptions.AddSystemIncludeDirs (Path.Combine (toolchainPath, asmTriple));
684 parserOptions.AddSystemIncludeDirs(toolchainPath);
686 parserOptions.NoBuiltinIncludes = true;
687 parserOptions.NoStandardIncludes = true;
688 parserOptions.TargetTriple = target.Triple;
691 static uint GetTypeAlign(ParserTargetInfo target, ParserIntType type)
693 switch (type)
695 case ParserIntType.SignedChar:
696 case ParserIntType.UnsignedChar:
697 return target.CharAlign;
698 case ParserIntType.SignedShort:
699 case ParserIntType.UnsignedShort:
700 return target.ShortAlign;
701 case ParserIntType.SignedInt:
702 case ParserIntType.UnsignedInt:
703 return target.IntAlign;
704 case ParserIntType.SignedLong:
705 case ParserIntType.UnsignedLong:
706 return target.LongAlign;
707 case ParserIntType.SignedLongLong:
708 case ParserIntType.UnsignedLongLong:
709 return target.LongLongAlign;
710 default:
711 throw new Exception("Type has no alignment");
715 static uint GetTypeSize(ParserTargetInfo target, ParserIntType type)
717 switch (type)
719 case ParserIntType.SignedChar:
720 case ParserIntType.UnsignedChar:
721 return target.CharWidth;
722 case ParserIntType.SignedShort:
723 case ParserIntType.UnsignedShort:
724 return target.ShortWidth;
725 case ParserIntType.SignedInt:
726 case ParserIntType.UnsignedInt:
727 return target.IntWidth;
728 case ParserIntType.SignedLong:
729 case ParserIntType.UnsignedLong:
730 return target.LongWidth;
731 case ParserIntType.SignedLongLong:
732 case ParserIntType.UnsignedLongLong:
733 return target.LongLongWidth;
734 default:
735 throw new Exception("Type has no size");
739 static string GetTargetPlatformDefine(TargetPlatform target)
741 switch (target) {
742 case TargetPlatform.Android:
743 return "TARGET_ANDROID";
744 case TargetPlatform.iOS:
745 return "TARGET_IOS";
746 case TargetPlatform.WatchOS:
747 return "TARGET_WATCHOS";
748 case TargetPlatform.OSX:
749 return "TARGET_OSX";
750 case TargetPlatform.WASM:
751 return "TARGET_WASM";
752 default:
753 throw new ArgumentOutOfRangeException ();
757 static void Dump(ASTContext ctx, ParserTargetInfo targetInfo, Target target)
759 string targetFile;
761 if (!string.IsNullOrEmpty (OutputFile)) {
762 targetFile = OutputFile;
763 } else {
764 targetFile = target.Triple;
766 if (!string.IsNullOrEmpty (OutputDir))
767 targetFile = Path.Combine (OutputDir, targetFile);
769 targetFile += ".h";
772 using (var writer = new StreamWriter(targetFile))
773 //using (var writer = Console.Out)
775 writer.WriteLine("#ifndef USED_CROSS_COMPILER_OFFSETS");
776 writer.WriteLine("#ifdef {0}", target.Defines[0]);
777 writer.WriteLine ("#ifdef {0}", GetTargetPlatformDefine (target.Platform));
778 writer.WriteLine("#ifndef HAVE_BOEHM_GC");
779 writer.WriteLine("#define HAS_CROSS_COMPILER_OFFSETS");
780 writer.WriteLine("#if defined (USE_CROSS_COMPILE_OFFSETS) || defined (MONO_CROSS_COMPILE)");
781 writer.WriteLine("#if !defined (DISABLE_METADATA_OFFSETS)");
782 writer.WriteLine("#define USED_CROSS_COMPILER_OFFSETS");
784 DumpAligns(writer, targetInfo);
785 DumpSizes(writer, targetInfo);
786 DumpMetadataOffsets(writer, ctx, target);
788 writer.WriteLine("#endif //disable metadata check");
790 DumpJITOffsets(writer, ctx);
792 writer.WriteLine("#endif //cross compiler checks");
793 writer.WriteLine("#endif //gc check");
794 writer.WriteLine("#endif //os check");
795 writer.WriteLine("#endif //arch check");
796 writer.WriteLine("#endif //USED_CROSS_COMPILER_OFFSETS check");
799 Console.WriteLine("Generated offsets file: {0}", targetFile);
802 static void DumpAligns(TextWriter writer, ParserTargetInfo target)
804 var aligns = new[]
806 new { Name = "gint8", Align = target.CharAlign},
807 new { Name = "gint16", Align = target.ShortAlign},
808 new { Name = "gint32", Align = target.IntAlign},
809 new { Name = "gint64", Align = GetTypeAlign(target, target.Int64Type)},
810 new { Name = "float", Align = target.FloatAlign},
811 new { Name = "double", Align = target.DoubleAlign},
812 new { Name = "gpointer", Align = GetTypeAlign(target, target.IntPtrType)},
815 // Write the alignment info for the basic types.
816 foreach (var align in aligns)
817 writer.WriteLine("DECL_ALIGN2({0},{1})", align.Name, align.Align / 8);
820 static void DumpSizes(TextWriter writer, ParserTargetInfo target)
822 var sizes = new[]
824 new { Name = "gint8", Size = target.CharWidth},
825 new { Name = "gint16", Size = target.ShortWidth},
826 new { Name = "gint32", Size = target.IntWidth},
827 new { Name = "gint64", Size = GetTypeSize(target, target.Int64Type)},
828 new { Name = "float", Size = target.FloatWidth},
829 new { Name = "double", Size = target.DoubleWidth},
830 new { Name = "gpointer", Size = GetTypeSize(target, target.IntPtrType)},
833 // Write the size info for the basic types.
834 foreach (var size in sizes)
835 writer.WriteLine("DECL_SIZE2({0},{1})", size.Name, size.Size / 8);
838 static Class GetClassFromTypedef(ITypedDecl typedef)
840 var type = typedef.Type.Desugar() as TagType;
841 if (type == null)
842 return null;
844 var @class = type.Declaration as Class;
846 return @class.IsIncomplete ?
847 (@class.CompleteDeclaration as Class) : @class;
850 static void DumpClasses(TextWriter writer, ASTContext ctx, IEnumerable<string> types,
851 bool optional = false)
853 foreach (var @struct in types)
855 var @class = ctx.FindCompleteClass(@struct);
856 if (@class == null)
857 @class = ctx.FindCompleteClass("_" + @struct);
859 if (@class == null)
861 var typedef = ctx.FindTypedef(@struct).FirstOrDefault(
862 decl => !decl.IsIncomplete);
864 if (typedef != null)
865 @class = GetClassFromTypedef(typedef);
868 if (@class == null && optional)
869 continue;
871 if (@class == null)
872 throw new Exception("Expected to find struct definition for " + @struct);
874 DumpStruct(writer, @class);
878 static void DumpMetadataOffsets(TextWriter writer, ASTContext ctx, Target target)
880 var types = new List<string>
882 "MonoObject",
883 "MonoClass",
884 "MonoVTable",
885 "MonoDelegate",
886 "MonoInternalThread",
887 "MonoMulticastDelegate",
888 "MonoTransparentProxy",
889 "MonoRealProxy",
890 "MonoRemoteClass",
891 "MonoArray",
892 "MonoArrayBounds",
893 "MonoSafeHandle",
894 "MonoHandleRef",
895 "MonoComInteropProxy",
896 "MonoString",
897 "MonoException",
898 "MonoTypedRef",
899 "MonoThreadsSync",
900 "SgenThreadInfo",
901 "SgenClientThreadInfo",
902 "MonoProfilerCallContext"
905 DumpClasses(writer, ctx, types);
908 static void DumpJITOffsets(TextWriter writer, ASTContext ctx)
910 writer.WriteLine("#ifndef DISABLE_JIT_OFFSETS");
911 writer.WriteLine("#define USED_CROSS_COMPILER_OFFSETS");
913 var types = new[]
915 "MonoLMF",
916 "MonoMethodRuntimeGenericContext",
917 "MonoJitTlsData",
918 "MonoGSharedVtMethodRuntimeInfo",
919 "MonoContinuation",
920 "MonoContext",
921 "MonoDelegateTrampInfo",
924 DumpClasses(writer, ctx, types);
926 var optionalTypes = new[]
928 "GSharedVtCallInfo",
929 "SeqPointInfo",
930 "DynCallArgs",
931 "MonoLMFTramp",
932 "CallContext",
933 "MonoFtnDesc"
936 DumpClasses(writer, ctx, optionalTypes, optional: true);
938 writer.WriteLine("#endif //disable jit check");
941 static void DumpStruct(TextWriter writer, Class @class)
943 var name = @class.Name;
944 if (name.StartsWith ("_", StringComparison.Ordinal))
945 name = name.Substring (1);
947 writer.WriteLine ("DECL_SIZE2({0},{1})", name, @class.Layout.Size);
949 foreach (var field in @class.Fields)
951 if (field.IsBitField) continue;
953 if (name == "SgenThreadInfo" && field.Name == "regs")
954 continue;
956 var layout = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr);
958 writer.WriteLine("DECL_OFFSET2({0},{1},{2})", name, field.Name,
959 layout.Offset);