1 // -*- indent-tabs-mode:nil -*-
3 using System
.Collections
.Generic
;
6 using System
.Text
.RegularExpressions
;
8 using CppSharp
.AST
.Extensions
;
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
= @"";
30 static bool GenAndroid
;
32 public enum TargetPlatform
45 Defines
= new List
<string>();
46 Arguments
= new List
<string>();
49 public Target(Target target
)
51 Platform
= target
.Platform
;
52 Triple
= target
.Triple
;
54 Defines
= target
.Defines
;
55 Arguments
= target
.Arguments
;
58 public TargetPlatform Platform
;
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
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
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" }
99 Targets
.Add (new Target
{
100 Platform
= TargetPlatform
.Android
,
101 Triple
= "x86_64-none-linux-android",
102 Defines
= { "TARGET_AMD64" }
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",
119 Targets
.Add (new Target
{
120 Platform
= TargetPlatform
.Android
,
121 Triple
= "aarch64-v8a-linux-android",
122 Defines
= { "TARGET_ARM64" }
125 /*Targets.Add(new Target {
126 Platform = TargetPlatform.Android,
127 Triple = "mipsel-none-linux-android",
128 Defines = { "TARGET_MIPS", "__mips__" }
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",
144 Defines
= { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
147 Targets
.Add(new Target
{
148 Platform
= TargetPlatform
.iOS
,
149 Triple
= "aarch64-apple-darwin10",
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",
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",
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",
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",
202 Defines
= { "TARGET_WASM" }
,
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
)) {
222 directory
= directory
.Parent
;
229 public static int Main(string[] args
)
231 ParseCommandLineArgs(args
);
234 SetupAndroidTargets();
239 if (Targets
.Count
== 0)
240 SetupOtherTargets ();
242 foreach (var target
in Targets
)
244 if (Abis
.Any() && !Abis
.Contains (target
.Triple
))
248 Console
.WriteLine("Processing triple: {0}", target
.Triple
);
250 var options
= new DriverOptions();
252 var driver
= new Driver(options
);
254 Setup(driver
, target
);
257 BuildParseOptions(driver
, target
);
258 if (!driver
.ParseCode())
261 Dump(driver
.Context
.ASTContext
, driver
.Context
.TargetInfo
, target
);
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"))
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 }
,
300 options
.Parse (args
);
302 catch (Mono
.Options
.OptionException e
) {
303 Console
.WriteLine (e
.Message
);
309 // Print usage and exit.
310 Console
.WriteLine("{0} <options>",
311 AppDomain
.CurrentDomain
.FriendlyName
);
312 options
.WriteOptionDescriptions (Console
.Out
);
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
)
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
;
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
;
375 case TargetPlatform
.OSX
:
376 case TargetPlatform
.WASM
:
378 Console
.Error
.WriteLine ("The --mono= option is required when targeting osx.");
379 Environment
.Exit (1);
381 if (!string.IsNullOrEmpty (TargetDir
)) {
382 targetBuild
= TargetDir
;
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[]
397 Path
.Combine(targetBuild
, "mono", "eglib"),
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
);
442 case TargetPlatform
.iOS
:
443 case TargetPlatform
.WatchOS
:
444 case TargetPlatform
.OSX
:
445 SetupXcode(driver
, target
);
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
);
464 throw new ArgumentOutOfRangeException ();
468 static string GetArchFromTriple(string triple
)
470 if (triple
.Contains("mips"))
473 if (triple
.Contains("arm64") || triple
.Contains("aarch64"))
476 if (triple
.Contains("arm"))
479 if (triple
.Contains("i686"))
482 if (triple
.Contains("x86_64"))
485 throw new Exception("Unknown architecture from triple: " + triple
);
488 static string GetXcodeToolchainPath()
490 var toolchains
= Directory
.EnumerateDirectories("/Applications", "Xcode*")
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();
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();
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();
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();
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();
572 switch (target
.Platform
) {
573 case TargetPlatform
.iOS
:
574 includePath
= GetXcodeiOSIncludesFolder();
576 case TargetPlatform
.WatchOS
:
577 includePath
= GetXcodeWatchOSIncludesFolder();
579 case TargetPlatform
.OSX
:
580 includePath
= GetXcodeOSXIncludesFolder();
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();
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();
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
,
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
662 asmTriple
= "aarch64-linux-android";
666 asmTriple
= "arm-linux-androideabi";
670 asmTriple
= "i686-linux-android";
674 asmTriple
= "x86_64-linux-android";
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
)
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
;
711 throw new Exception("Type has no alignment");
715 static uint GetTypeSize(ParserTargetInfo target
, ParserIntType 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
;
735 throw new Exception("Type has no size");
739 static string GetTargetPlatformDefine(TargetPlatform target
)
742 case TargetPlatform
.Android
:
743 return "TARGET_ANDROID";
744 case TargetPlatform
.iOS
:
746 case TargetPlatform
.WatchOS
:
747 return "TARGET_WATCHOS";
748 case TargetPlatform
.OSX
:
750 case TargetPlatform
.WASM
:
751 return "TARGET_WASM";
753 throw new ArgumentOutOfRangeException ();
757 static void Dump(ASTContext ctx
, ParserTargetInfo targetInfo
, Target target
)
761 if (!string.IsNullOrEmpty (OutputFile
)) {
762 targetFile
= OutputFile
;
764 targetFile
= target
.Triple
;
766 if (!string.IsNullOrEmpty (OutputDir
))
767 targetFile
= Path
.Combine (OutputDir
, targetFile
);
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
)
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
)
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
;
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);
857 @class = ctx
.FindCompleteClass("_" + @struct);
861 var typedef
= ctx
.FindTypedef(@struct).FirstOrDefault(
862 decl
=> !decl
.IsIncomplete
);
865 @class = GetClassFromTypedef(typedef
);
868 if (@class == null && optional
)
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>
886 "MonoInternalThread",
887 "MonoMulticastDelegate",
888 "MonoTransparentProxy",
895 "MonoComInteropProxy",
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");
916 "MonoMethodRuntimeGenericContext",
918 "MonoGSharedVtMethodRuntimeInfo",
921 "MonoDelegateTrampInfo",
924 DumpClasses(writer
, ctx
, types
);
926 var optionalTypes
= new[]
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")
956 var layout
= @class.Layout
.Fields
.First(f
=> f
.FieldPtr
== field
.OriginalPtr
);
958 writer
.WriteLine("DECL_OFFSET2({0},{1},{2})", name
, field
.Name
,