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
) => t
.Platform
== TargetPlatform
.iOS
||
77 t
.Platform
== TargetPlatform
.WatchOS
||
78 t
.Platform
== TargetPlatform
.OSX
);
82 public static IEnumerable
<Target
> iOSTargets
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" }
98 Targets
.Add (new Target
{
99 Platform
= TargetPlatform
.Android
,
100 Triple
= "x86_64-none-linux-android",
101 Defines
= { "TARGET_AMD64" }
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",
118 Targets
.Add (new Target
{
119 Platform
= TargetPlatform
.Android
,
120 Triple
= "aarch64-v8a-linux-android",
121 Defines
= { "TARGET_ARM64" }
124 /*Targets.Add(new Target {
125 Platform = TargetPlatform.Android,
126 Triple = "mipsel-none-linux-android",
127 Defines = { "TARGET_MIPS", "__mips__" }
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",
142 Defines
= { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
145 Targets
.Add(new Target
{
146 Platform
= TargetPlatform
.iOS
,
147 Triple
= "aarch64-apple-darwin10",
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",
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",
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",
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",
193 Defines
= { "TARGET_WASM" }
,
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
)) {
213 directory
= directory
.Parent
;
220 public static int Main(string[] args
)
222 ParseCommandLineArgs(args
);
225 SetupAndroidTargets();
230 if (Targets
.Count
== 0)
231 SetupOtherTargets ();
233 foreach (var target
in Targets
)
235 if (Abis
.Any() && !Abis
.Any (target
.Triple
.Contains
))
239 Console
.WriteLine("Processing triple: {0}", target
.Triple
);
241 var options
= new DriverOptions();
243 var driver
= new Driver(options
);
245 Setup(driver
, target
);
248 BuildParseOptions(driver
, target
);
249 if (!driver
.ParseCode())
252 Dump(driver
.Context
.ASTContext
, driver
.Context
.TargetInfo
, target
);
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"))
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 }
,
291 options
.Parse (args
);
293 catch (Mono
.Options
.OptionException e
) {
294 Console
.WriteLine (e
.Message
);
300 // Print usage and exit.
301 Console
.WriteLine("{0} <options>",
302 AppDomain
.CurrentDomain
.FriendlyName
);
303 options
.WriteOptionDescriptions (Console
.Out
);
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
)
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
;
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
;
366 case TargetPlatform
.OSX
:
367 case TargetPlatform
.WASM
:
369 Console
.Error
.WriteLine ("The --mono= option is required when targeting osx.");
370 Environment
.Exit (1);
372 if (!string.IsNullOrEmpty (TargetDir
)) {
373 targetBuild
= TargetDir
;
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[]
388 Path
.Combine(targetBuild
, "mono", "eglib"),
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
);
433 case TargetPlatform
.iOS
:
434 case TargetPlatform
.WatchOS
:
435 case TargetPlatform
.OSX
:
436 SetupXcode(driver
, target
);
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
);
455 throw new ArgumentOutOfRangeException ();
459 static string GetArchFromTriple(string triple
)
461 if (triple
.Contains("mips"))
464 if (triple
.Contains("arm64") || triple
.Contains("aarch64"))
467 if (triple
.Contains("arm"))
470 if (triple
.Contains("i686"))
473 if (triple
.Contains("x86_64"))
476 throw new Exception("Unknown architecture from triple: " + triple
);
479 static string GetXcodeToolchainPath()
481 var toolchains
= Directory
.EnumerateDirectories("/Applications", "Xcode*")
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();
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();
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();
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();
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();
563 switch (target
.Platform
) {
564 case TargetPlatform
.iOS
:
565 includePath
= GetXcodeiOSIncludesFolder();
567 case TargetPlatform
.WatchOS
:
568 includePath
= GetXcodeWatchOSIncludesFolder();
570 case TargetPlatform
.OSX
:
571 includePath
= GetXcodeOSXIncludesFolder();
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();
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();
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
),
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
)
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
;
665 throw new Exception("Type has no alignment");
669 static uint GetTypeSize(ParserTargetInfo target
, ParserIntType 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
;
689 throw new Exception("Type has no size");
693 static string GetTargetPlatformDefine(TargetPlatform target
)
696 case TargetPlatform
.Android
:
697 return "TARGET_ANDROID";
698 case TargetPlatform
.iOS
:
700 case TargetPlatform
.WatchOS
:
701 return "TARGET_WATCHOS";
702 case TargetPlatform
.OSX
:
704 case TargetPlatform
.WASM
:
705 return "TARGET_WASM";
707 throw new ArgumentOutOfRangeException ();
711 static void Dump(ASTContext ctx
, ParserTargetInfo targetInfo
, Target target
)
715 if (!string.IsNullOrEmpty (OutputFile
)) {
716 targetFile
= OutputFile
;
718 targetFile
= target
.Triple
;
720 if (!string.IsNullOrEmpty (OutputDir
))
721 targetFile
= Path
.Combine (OutputDir
, targetFile
);
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
)
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
)
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
;
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);
811 @class = ctx
.FindCompleteClass("_" + @struct);
815 var typedef
= ctx
.FindTypedef(@struct).FirstOrDefault(
816 decl
=> !decl
.IsIncomplete
);
819 @class = GetClassFromTypedef(typedef
);
822 if (@class == null && optional
)
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>
840 "MonoInternalThread",
841 "MonoMulticastDelegate",
842 "MonoTransparentProxy",
849 "MonoComInteropProxy",
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");
870 "MonoMethodRuntimeGenericContext",
872 "MonoGSharedVtMethodRuntimeInfo",
875 "MonoDelegateTrampInfo",
878 DumpClasses(writer
, ctx
, types
);
880 var optionalTypes
= new[]
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")
910 var layout
= @class.Layout
.Fields
.First(f
=> f
.FieldPtr
== field
.OriginalPtr
);
912 writer
.WriteLine("DECL_OFFSET2({0},{1},{2})", name
, field
.Name
,