for "build" config, import corlib common sources at unix instead (#11989)
[mono-project.git] / tools / offsets-tool / MonoAotOffsetsDumper.cs
blob6ce95af034d0a12b6b28cafbe90120fa16107dbe
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) => t.Platform == TargetPlatform.iOS ||
77 t.Platform == TargetPlatform.WatchOS ||
78 t.Platform == TargetPlatform.OSX);
82 public static IEnumerable<Target> iOSTargets
84 get
86 return Targets.Where ((t) => t.Platform == TargetPlatform.iOS);
90 public static void SetupAndroidTargets()
92 Targets.Add (new Target {
93 Platform = TargetPlatform.Android,
94 Triple = "i686-none-linux-android",
95 Defines = { "TARGET_X86" }
96 });
98 Targets.Add (new Target {
99 Platform = TargetPlatform.Android,
100 Triple = "x86_64-none-linux-android",
101 Defines = { "TARGET_AMD64" }
102 });
104 Targets.Add (new Target {
105 Platform = TargetPlatform.Android,
106 Triple = "armv5-none-linux-androideabi",
107 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
110 Targets.Add (new Target {
111 Platform = TargetPlatform.Android,
112 Triple = "armv7-none-linux-androideabi",
113 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5", "HAVE_ARMV6",
114 "HAVE_ARMV7"
118 Targets.Add (new Target {
119 Platform = TargetPlatform.Android,
120 Triple = "aarch64-v8a-linux-android",
121 Defines = { "TARGET_ARM64" }
122 });
124 /*Targets.Add(new Target {
125 Platform = TargetPlatform.Android,
126 Triple = "mipsel-none-linux-android",
127 Defines = { "TARGET_MIPS", "__mips__" }
128 });*/
130 foreach (var target in AndroidTargets)
131 target.Defines.AddRange (new string[] { "HOST_ANDROID",
132 "TARGET_ANDROID", "MONO_CROSS_COMPILE", "USE_MONO_CTX"
136 public static void SetupiOSTargets()
138 Targets.Add(new Target {
139 Platform = TargetPlatform.iOS,
140 Triple = "arm-apple-darwin10",
141 Build = "target7",
142 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
145 Targets.Add(new Target {
146 Platform = TargetPlatform.iOS,
147 Triple = "aarch64-apple-darwin10",
148 Build = "target64",
149 Defines = { "TARGET_ARM64" }
152 foreach (var target in iOSTargets) {
153 target.Defines.AddRange (new string[] { "HOST_DARWIN",
154 "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX",
155 "_XOPEN_SOURCE"
159 Targets.Add(new Target {
160 Platform = TargetPlatform.WatchOS,
161 Triple = "armv7k-apple-darwin",
162 Build = "targetwatch",
163 Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
166 foreach (var target in DarwinTargets) {
167 target.Defines.AddRange (new string[] { "HOST_DARWIN",
168 "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX",
169 "_XOPEN_SOURCE"
174 public static void SetupOtherTargets()
176 if (Abis.Count != 1) {
177 Console.WriteLine ("Exactly --abi= argument is required.");
178 Environment.Exit (1);
180 string abi = Abis [0];
181 if (abi == "i386-apple-darwin13.0.0") {
182 Targets.Add(new Target {
183 Platform = TargetPlatform.OSX,
184 Triple = "i386-apple-darwin13.0.0",
185 Build = "",
186 Defines = { "TARGET_X86" },
188 } else if (abi == "wasm32-unknown-unknown") {
189 Targets.Add(new Target {
190 Platform = TargetPlatform.WASM,
191 Triple = "wasm32-wasm32-unknown-unknown",
192 Build = "",
193 Defines = { "TARGET_WASM" },
195 } else {
196 Console.WriteLine ($"Unsupported abi: {abi}.");
197 Environment.Exit (1);
201 static bool GetParentSubDirectoryPath(string parent, out string subdir)
203 var directory = Directory.GetParent(Directory.GetCurrentDirectory());
205 while (directory != null) {
206 var path = Path.Combine(directory.FullName, parent);
208 if (Directory.Exists (path)) {
209 subdir = path;
210 return true;
213 directory = directory.Parent;
216 subdir = null;
217 return false;
220 public static int Main(string[] args)
222 ParseCommandLineArgs(args);
224 if (GenAndroid)
225 SetupAndroidTargets();
227 if (GenIOS)
228 SetupiOSTargets();
230 if (Targets.Count == 0)
231 SetupOtherTargets ();
233 foreach (var target in Targets)
235 if (Abis.Any() && !Abis.Any (target.Triple.Contains))
236 continue;
238 Console.WriteLine();
239 Console.WriteLine("Processing triple: {0}", target.Triple);
241 var options = new DriverOptions();
243 var driver = new Driver(options);
245 Setup(driver, target);
246 driver.Setup();
248 BuildParseOptions(driver, target);
249 if (!driver.ParseCode())
250 return 1;
252 Dump(driver.Context.ASTContext, driver.Context.TargetInfo, target);
254 return 0;
257 static void BuildParseOptions(Driver driver, Target target)
259 foreach (var header in driver.Options.Headers)
261 var source = driver.Project.AddFile(header);
262 source.Options = driver.BuildParserOptions(source);
264 if (header.Contains ("mini"))
265 continue;
267 source.Options.AddDefines ("HAVE_SGEN_GC");
268 source.Options.AddDefines ("HAVE_MOVING_COLLECTOR");
269 source.Options.AddDefines("MONO_GENERATING_OFFSETS");
273 static void ParseCommandLineArgs(string[] args)
275 var showHelp = false;
277 var options = new Mono.Options.OptionSet () {
278 { "abi=", "ABI triple to generate", v => Abis.Add(v) },
279 { "o|out=", "output directory", v => OutputDir = v },
280 { "outfile=", "output directory", v => OutputFile = v },
281 { "android-ndk=", "Path to Android NDK", v => AndroidNdkPath = v },
282 { "emscripten-sdk=", "Path to emscripten sdk", v => EmscriptenSdkPath = v },
283 { "targetdir=", "Path to the directory containing the mono build", v =>TargetDir = v },
284 { "mono=", "include directory", v => MonoDir = v },
285 { "gen-ios", "generate iOS offsets", v => GenIOS = v != null },
286 { "gen-android", "generate Android offsets", v => GenAndroid = v != null },
287 { "h|help", "show this message and exit", v => showHelp = v != null },
290 try {
291 options.Parse (args);
293 catch (Mono.Options.OptionException e) {
294 Console.WriteLine (e.Message);
295 Environment.Exit(0);
298 if (showHelp)
300 // Print usage and exit.
301 Console.WriteLine("{0} <options>",
302 AppDomain.CurrentDomain.FriendlyName);
303 options.WriteOptionDescriptions (Console.Out);
304 Environment.Exit(0);
308 static void Setup(Driver driver, Target target)
310 var options = driver.Options;
311 options.DryRun = true;
312 options.LibraryName = "Mono";
314 var parserOptions = driver.ParserOptions;
315 parserOptions.Verbose = false;
316 parserOptions.MicrosoftMode = false;
317 parserOptions.AddArguments("-xc");
318 parserOptions.AddArguments("-std=gnu99");
319 parserOptions.AddDefines("CPPSHARP");
320 parserOptions.AddDefines("MONO_GENERATING_OFFSETS");
322 foreach (var define in target.Defines)
323 parserOptions.AddDefines(define);
325 SetupToolchainPaths(driver, target);
327 SetupMono(driver, target);
330 static void SetupMono(Driver driver, Target target)
332 string targetBuild;
333 switch (target.Platform) {
334 case TargetPlatform.Android:
335 if (string.IsNullOrEmpty (TargetDir)) {
336 Console.Error.WriteLine ("The --targetdir= option is required when targeting android.");
337 Environment.Exit (1);
339 if (string.IsNullOrEmpty (MonoDir)) {
340 Console.Error.WriteLine ("The --mono= option is required when targeting android.");
341 Environment.Exit (1);
343 if (string.IsNullOrEmpty(AndroidNdkPath)) {
344 Console.WriteLine("The --android-ndk= option is required when targeting android");
345 Environment.Exit (1);
347 if (Abis.Count != 1) {
348 Console.Error.WriteLine ("Exactly one --abi= argument is required when targeting android.");
349 Environment.Exit (1);
351 targetBuild = TargetDir;
352 break;
353 case TargetPlatform.WatchOS:
354 case TargetPlatform.iOS: {
355 if (string.IsNullOrEmpty (TargetDir)) {
356 Console.Error.WriteLine ("The --targetdir= option is required when targeting ios.");
357 Environment.Exit (1);
359 if (string.IsNullOrEmpty (MonoDir)) {
360 Console.Error.WriteLine ("The --mono= option is required when targeting ios.");
361 Environment.Exit (1);
363 targetBuild = TargetDir;
364 break;
366 case TargetPlatform.OSX:
367 case TargetPlatform.WASM:
368 if (MonoDir == "") {
369 Console.Error.WriteLine ("The --mono= option is required when targeting osx.");
370 Environment.Exit (1);
372 if (!string.IsNullOrEmpty (TargetDir)) {
373 targetBuild = TargetDir;
374 } else {
375 targetBuild = ".";
377 break;
378 default:
379 throw new ArgumentOutOfRangeException ();
382 if (!Directory.Exists(targetBuild))
383 throw new Exception(string.Format("Could not find the target build directory: {0}", targetBuild));
385 var includeDirs = new[]
387 targetBuild,
388 Path.Combine(targetBuild, "mono", "eglib"),
389 MonoDir,
390 Path.Combine(MonoDir, "mono"),
391 Path.Combine(MonoDir, "mono", "mini"),
392 Path.Combine(MonoDir, "mono", "eglib")
395 foreach (var inc in includeDirs)
396 driver.ParserOptions.AddIncludeDirs(inc);
398 var filesToParse = new[]
400 Path.Combine(MonoDir, "mono", "metadata", "metadata-cross-helpers.c"),
401 Path.Combine(MonoDir, "mono", "mini", "mini-cross-helpers.c"),
404 foreach (var file in filesToParse)
405 driver.Options.Headers.Add(file);
408 static void SetupMSVC(Driver driver, string triple)
410 var parserOptions = driver.ParserOptions;
412 parserOptions.Abi = Parser.AST.CppAbi.Microsoft;
413 parserOptions.MicrosoftMode = true;
415 var systemIncludeDirs = new[]
417 @"C:\Program Files (x86)\Windows Kits\8.1\Include\um",
418 @"C:\Program Files (x86)\Windows Kits\8.1\Include\shared"
421 foreach (var inc in systemIncludeDirs)
422 parserOptions.AddSystemIncludeDirs(inc);
424 parserOptions.AddDefines("HOST_WIN32");
427 static void SetupToolchainPaths(Driver driver, Target target)
429 switch (target.Platform) {
430 case TargetPlatform.Android:
431 SetupAndroidNDK(driver, target);
432 break;
433 case TargetPlatform.iOS:
434 case TargetPlatform.WatchOS:
435 case TargetPlatform.OSX:
436 SetupXcode(driver, target);
437 break;
438 case TargetPlatform.WASM:
439 if (EmscriptenSdkPath == "") {
440 Console.Error.WriteLine ("The --emscripten-sdk= option is required when targeting wasm.");
441 Environment.Exit (1);
443 string include_dir = Path.Combine (EmscriptenSdkPath, "system", "include", "libc");
444 if (!Directory.Exists (include_dir)) {
445 Console.Error.WriteLine ($"emscripten include directory {include_dir} does not exist.");
446 Environment.Exit (1);
448 var parserOptions = driver.ParserOptions;
449 parserOptions.NoBuiltinIncludes = true;
450 parserOptions.NoStandardIncludes = true;
451 parserOptions.TargetTriple = target.Triple;
452 parserOptions.AddSystemIncludeDirs(include_dir);
453 break;
454 default:
455 throw new ArgumentOutOfRangeException ();
459 static string GetArchFromTriple(string triple)
461 if (triple.Contains("mips"))
462 return "mips";
464 if (triple.Contains("arm64") || triple.Contains("aarch64"))
465 return "arm64";
467 if (triple.Contains("arm"))
468 return "arm";
470 if (triple.Contains("i686"))
471 return "x86";
473 if (triple.Contains("x86_64"))
474 return "x86_64";
476 throw new Exception("Unknown architecture from triple: " + triple);
479 static string GetXcodeToolchainPath()
481 var toolchains = Directory.EnumerateDirectories("/Applications", "Xcode*")
482 .ToList();
483 toolchains.Sort();
485 var toolchainPath = toolchains.LastOrDefault();
486 if (toolchainPath == null)
487 throw new Exception("Could not find a valid Xcode SDK");
489 return toolchainPath;
492 static string GetXcodeBuiltinIncludesFolder()
494 var toolchainPath = GetXcodeToolchainPath();
496 var toolchains = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
497 "Contents/Developer/Toolchains")).ToList();
498 toolchains.Sort();
500 toolchainPath = toolchains.LastOrDefault();
501 if (toolchainPath == null)
502 throw new Exception("Could not find a valid Xcode toolchain");
504 var includePaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
505 "usr/lib/clang")).ToList();
506 var includePath = includePaths.LastOrDefault();
508 if (includePath == null)
509 throw new Exception("Could not find a valid Clang include folder");
511 return Path.Combine(includePath, "include");
514 static string GetXcodeiOSIncludesFolder()
516 var toolchainPath = GetXcodeToolchainPath();
518 var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
519 "Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs")).ToList();
520 var sdkPath = sdkPaths.LastOrDefault();
522 if (sdkPath == null)
523 throw new Exception("Could not find a valid iPhone SDK");
525 return Path.Combine(sdkPath, "usr/include");
528 static string GetXcodeOSXIncludesFolder()
530 var toolchainPath = GetXcodeToolchainPath();
532 var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
533 "Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs")).ToList();
534 var sdkPath = sdkPaths.LastOrDefault();
536 if (sdkPath == null)
537 throw new Exception("Could not find a valid OSX SDK");
539 return Path.Combine(sdkPath, "usr/include");
542 static string GetXcodeWatchOSIncludesFolder()
544 var toolchainPath = GetXcodeToolchainPath();
546 var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
547 "Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs")).ToList();
548 var sdkPath = sdkPaths.LastOrDefault();
550 if (sdkPath == null)
551 throw new Exception("Could not find a valid WatchOS SDK");
553 return Path.Combine(sdkPath, "usr/include");
556 static void SetupXcode(Driver driver, Target target)
558 var parserOptions = driver.ParserOptions;
560 var builtinsPath = GetXcodeBuiltinIncludesFolder();
561 string includePath;
563 switch (target.Platform) {
564 case TargetPlatform.iOS:
565 includePath = GetXcodeiOSIncludesFolder();
566 break;
567 case TargetPlatform.WatchOS:
568 includePath = GetXcodeWatchOSIncludesFolder();
569 break;
570 case TargetPlatform.OSX:
571 includePath = GetXcodeOSXIncludesFolder();
572 break;
573 default:
574 throw new ArgumentOutOfRangeException ();
577 parserOptions.AddSystemIncludeDirs(builtinsPath);
578 parserOptions.AddSystemIncludeDirs(includePath);
580 parserOptions.NoBuiltinIncludes = true;
581 parserOptions.NoStandardIncludes = true;
582 parserOptions.TargetTriple = target.Triple;
585 static string GetAndroidHostToolchainPath()
587 var toolchains = Directory.EnumerateDirectories(
588 Path.Combine(AndroidNdkPath, "toolchains"), "llvm*").ToList();
589 toolchains.Sort();
591 var toolchainPath = toolchains.LastOrDefault();
592 if (toolchainPath == null)
593 throw new Exception("Could not find a valid NDK host toolchain");
595 toolchains = Directory.EnumerateDirectories(Path.Combine(toolchainPath,
596 "prebuilt")).ToList();
597 toolchains.Sort();
599 toolchainPath = toolchains.LastOrDefault();
600 if (toolchainPath == null)
601 throw new Exception("Could not find a valid NDK host toolchain");
603 return toolchainPath;
606 static string GetAndroidBuiltinIncludesFolder()
608 var toolchainPath = GetAndroidHostToolchainPath();
610 string clangToolchainPath = Path.Combine(toolchainPath, "lib64", "clang");
611 if (!Directory.Exists (clangToolchainPath))
612 clangToolchainPath = Path.Combine(toolchainPath, "lib", "clang");
614 string includePath = null;
615 if (Directory.Exists (clangToolchainPath)) {
616 var includePaths = Directory.EnumerateDirectories(clangToolchainPath).ToList();
617 includePath = includePaths.LastOrDefault();
619 if (includePath == null)
620 throw new Exception("Could not find a valid Clang include folder");
622 return Path.Combine(includePath, "include");
625 static void SetupAndroidNDK(Driver driver, Target target)
627 var options = driver.Options;
628 var parserOptions = driver.ParserOptions;
630 var builtinsPath = GetAndroidBuiltinIncludesFolder();
631 parserOptions.AddSystemIncludeDirs(builtinsPath);
633 const int androidNdkApiLevel = 21;
635 var toolchainPath = Path.Combine(AndroidNdkPath, "platforms",
636 "android-" + androidNdkApiLevel, "arch-" + GetArchFromTriple(target.Triple),
637 "usr", "include");
638 parserOptions.AddSystemIncludeDirs(toolchainPath);
640 parserOptions.NoBuiltinIncludes = true;
641 parserOptions.NoStandardIncludes = true;
642 parserOptions.TargetTriple = target.Triple;
645 static uint GetTypeAlign(ParserTargetInfo target, ParserIntType type)
647 switch (type)
649 case ParserIntType.SignedChar:
650 case ParserIntType.UnsignedChar:
651 return target.CharAlign;
652 case ParserIntType.SignedShort:
653 case ParserIntType.UnsignedShort:
654 return target.ShortAlign;
655 case ParserIntType.SignedInt:
656 case ParserIntType.UnsignedInt:
657 return target.IntAlign;
658 case ParserIntType.SignedLong:
659 case ParserIntType.UnsignedLong:
660 return target.LongAlign;
661 case ParserIntType.SignedLongLong:
662 case ParserIntType.UnsignedLongLong:
663 return target.LongLongAlign;
664 default:
665 throw new Exception("Type has no alignment");
669 static uint GetTypeSize(ParserTargetInfo target, ParserIntType type)
671 switch (type)
673 case ParserIntType.SignedChar:
674 case ParserIntType.UnsignedChar:
675 return target.CharWidth;
676 case ParserIntType.SignedShort:
677 case ParserIntType.UnsignedShort:
678 return target.ShortWidth;
679 case ParserIntType.SignedInt:
680 case ParserIntType.UnsignedInt:
681 return target.IntWidth;
682 case ParserIntType.SignedLong:
683 case ParserIntType.UnsignedLong:
684 return target.LongWidth;
685 case ParserIntType.SignedLongLong:
686 case ParserIntType.UnsignedLongLong:
687 return target.LongLongWidth;
688 default:
689 throw new Exception("Type has no size");
693 static string GetTargetPlatformDefine(TargetPlatform target)
695 switch (target) {
696 case TargetPlatform.Android:
697 return "TARGET_ANDROID";
698 case TargetPlatform.iOS:
699 return "TARGET_IOS";
700 case TargetPlatform.WatchOS:
701 return "TARGET_WATCHOS";
702 case TargetPlatform.OSX:
703 return "TARGET_OSX";
704 case TargetPlatform.WASM:
705 return "TARGET_WASM";
706 default:
707 throw new ArgumentOutOfRangeException ();
711 static void Dump(ASTContext ctx, ParserTargetInfo targetInfo, Target target)
713 string targetFile;
715 if (!string.IsNullOrEmpty (OutputFile)) {
716 targetFile = OutputFile;
717 } else {
718 targetFile = target.Triple;
720 if (!string.IsNullOrEmpty (OutputDir))
721 targetFile = Path.Combine (OutputDir, targetFile);
723 targetFile += ".h";
726 using (var writer = new StreamWriter(targetFile))
727 //using (var writer = Console.Out)
729 writer.WriteLine("#ifndef USED_CROSS_COMPILER_OFFSETS");
730 writer.WriteLine("#ifdef {0}", target.Defines[0]);
731 writer.WriteLine ("#ifdef {0}", GetTargetPlatformDefine (target.Platform));
732 writer.WriteLine("#ifndef HAVE_BOEHM_GC");
733 writer.WriteLine("#define HAS_CROSS_COMPILER_OFFSETS");
734 writer.WriteLine("#if defined (USE_CROSS_COMPILE_OFFSETS) || defined (MONO_CROSS_COMPILE)");
735 writer.WriteLine("#if !defined (DISABLE_METADATA_OFFSETS)");
736 writer.WriteLine("#define USED_CROSS_COMPILER_OFFSETS");
738 DumpAligns(writer, targetInfo);
739 DumpSizes(writer, targetInfo);
740 DumpMetadataOffsets(writer, ctx, target);
742 writer.WriteLine("#endif //disable metadata check");
744 DumpJITOffsets(writer, ctx);
746 writer.WriteLine("#endif //cross compiler checks");
747 writer.WriteLine("#endif //gc check");
748 writer.WriteLine("#endif //os check");
749 writer.WriteLine("#endif //arch check");
750 writer.WriteLine("#endif //USED_CROSS_COMPILER_OFFSETS check");
753 Console.WriteLine("Generated offsets file: {0}", targetFile);
756 static void DumpAligns(TextWriter writer, ParserTargetInfo target)
758 var aligns = new[]
760 new { Name = "gint8", Align = target.CharAlign},
761 new { Name = "gint16", Align = target.ShortAlign},
762 new { Name = "gint32", Align = target.IntAlign},
763 new { Name = "gint64", Align = GetTypeAlign(target, target.Int64Type)},
764 new { Name = "float", Align = target.FloatAlign},
765 new { Name = "double", Align = target.DoubleAlign},
766 new { Name = "gpointer", Align = GetTypeAlign(target, target.IntPtrType)},
769 // Write the alignment info for the basic types.
770 foreach (var align in aligns)
771 writer.WriteLine("DECL_ALIGN2({0},{1})", align.Name, align.Align / 8);
774 static void DumpSizes(TextWriter writer, ParserTargetInfo target)
776 var sizes = new[]
778 new { Name = "gint8", Size = target.CharWidth},
779 new { Name = "gint16", Size = target.ShortWidth},
780 new { Name = "gint32", Size = target.IntWidth},
781 new { Name = "gint64", Size = GetTypeSize(target, target.Int64Type)},
782 new { Name = "float", Size = target.FloatWidth},
783 new { Name = "double", Size = target.DoubleWidth},
784 new { Name = "gpointer", Size = GetTypeSize(target, target.IntPtrType)},
787 // Write the size info for the basic types.
788 foreach (var size in sizes)
789 writer.WriteLine("DECL_SIZE2({0},{1})", size.Name, size.Size / 8);
792 static Class GetClassFromTypedef(ITypedDecl typedef)
794 var type = typedef.Type.Desugar() as TagType;
795 if (type == null)
796 return null;
798 var @class = type.Declaration as Class;
800 return @class.IsIncomplete ?
801 (@class.CompleteDeclaration as Class) : @class;
804 static void DumpClasses(TextWriter writer, ASTContext ctx, IEnumerable<string> types,
805 bool optional = false)
807 foreach (var @struct in types)
809 var @class = ctx.FindCompleteClass(@struct);
810 if (@class == null)
811 @class = ctx.FindCompleteClass("_" + @struct);
813 if (@class == null)
815 var typedef = ctx.FindTypedef(@struct).FirstOrDefault(
816 decl => !decl.IsIncomplete);
818 if (typedef != null)
819 @class = GetClassFromTypedef(typedef);
822 if (@class == null && optional)
823 continue;
825 if (@class == null)
826 throw new Exception("Expected to find struct definition for " + @struct);
828 DumpStruct(writer, @class);
832 static void DumpMetadataOffsets(TextWriter writer, ASTContext ctx, Target target)
834 var types = new List<string>
836 "MonoObject",
837 "MonoClass",
838 "MonoVTable",
839 "MonoDelegate",
840 "MonoInternalThread",
841 "MonoMulticastDelegate",
842 "MonoTransparentProxy",
843 "MonoRealProxy",
844 "MonoRemoteClass",
845 "MonoArray",
846 "MonoArrayBounds",
847 "MonoSafeHandle",
848 "MonoHandleRef",
849 "MonoComInteropProxy",
850 "MonoString",
851 "MonoException",
852 "MonoTypedRef",
853 "MonoThreadsSync",
854 "SgenThreadInfo",
855 "SgenClientThreadInfo",
856 "MonoProfilerCallContext"
859 DumpClasses(writer, ctx, types);
862 static void DumpJITOffsets(TextWriter writer, ASTContext ctx)
864 writer.WriteLine("#ifndef DISABLE_JIT_OFFSETS");
865 writer.WriteLine("#define USED_CROSS_COMPILER_OFFSETS");
867 var types = new[]
869 "MonoLMF",
870 "MonoMethodRuntimeGenericContext",
871 "MonoJitTlsData",
872 "MonoGSharedVtMethodRuntimeInfo",
873 "MonoContinuation",
874 "MonoContext",
875 "MonoDelegateTrampInfo",
878 DumpClasses(writer, ctx, types);
880 var optionalTypes = new[]
882 "GSharedVtCallInfo",
883 "SeqPointInfo",
884 "DynCallArgs",
885 "MonoLMFTramp",
886 "CallContext",
887 "MonoFtnDesc"
890 DumpClasses(writer, ctx, optionalTypes, optional: true);
892 writer.WriteLine("#endif //disable jit check");
895 static void DumpStruct(TextWriter writer, Class @class)
897 var name = @class.Name;
898 if (name.StartsWith ("_", StringComparison.Ordinal))
899 name = name.Substring (1);
901 writer.WriteLine ("DECL_SIZE2({0},{1})", name, @class.Layout.Size);
903 foreach (var field in @class.Fields)
905 if (field.IsBitField) continue;
907 if (name == "SgenThreadInfo" && field.Name == "regs")
908 continue;
910 var layout = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr);
912 writer.WriteLine("DECL_OFFSET2({0},{1},{2})", name, field.Name,
913 layout.Offset);