2 using System
.Collections
.Generic
;
5 using System
.Text
.RegularExpressions
;
7 using CppSharp
.AST
.Extensions
;
13 * This tool dumps the offsets of structures used in the Mono VM needed
14 * by the AOT compiler for cross-compiling code to target platforms
15 * different than the host the compiler is being invoked on.
17 * It takes two arguments: the path to your clone of the Mono repo and
18 * the path to the root of Android NDK.
20 static class MonoAotOffsetsDumper
22 static string MonoDir
= @"";
24 static List
<string> Abis
= new List
<string> ();
25 static string OutputDir
;
27 static bool XamarinAndroid
;
28 static string MonodroidDir
= @"";
29 static string AndroidNdkPath
= @"";
30 static string MaccoreDir
= @"";
32 public enum TargetPlatform
43 Defines
= new List
<string>();
44 Arguments
= new List
<string>();
47 public Target(Target target
)
49 Platform
= target
.Platform
;
50 Triple
= target
.Triple
;
52 Defines
= target
.Defines
;
53 Arguments
= target
.Arguments
;
56 public TargetPlatform Platform
;
59 public List
<string> Defines
;
60 public List
<string> Arguments
;
63 public static List
<Target
> Targets
= new List
<Target
>();
65 public static IEnumerable
<Target
> AndroidTargets
67 get { return Targets.Where ((t) => t.Platform == TargetPlatform.Android); }
70 public static IEnumerable
<Target
> DarwinTargets
74 return Targets
.Where ((t
) => t
.Platform
== TargetPlatform
.iOS
||
75 t
.Platform
== TargetPlatform
.WatchOS
);
79 public static IEnumerable
<Target
> iOSTargets
83 return Targets
.Where ((t
) => t
.Platform
== TargetPlatform
.iOS
);
87 public static void SetupAndroidTargets()
89 Targets
.Add (new Target
{
90 Platform
= TargetPlatform
.Android
,
91 Triple
= "i686-none-linux-android",
92 Build
= XamarinAndroid
? "x86" : "mono-x86",
93 Defines
= { "TARGET_X86" }
96 Targets
.Add (new Target
{
97 Platform
= TargetPlatform
.Android
,
98 Triple
= "x86_64-none-linux-android",
99 Build
= XamarinAndroid
? "x86_64" : "mono-x86_64",
100 Defines
= { "TARGET_AMD64" }
103 Targets
.Add (new Target
{
104 Platform
= TargetPlatform
.Android
,
105 Triple
= "armv5-none-linux-androideabi",
106 Build
= XamarinAndroid
? "armeabi" : "mono-armv6",
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 Build
= XamarinAndroid
? "armeabi-v7a" : "mono-armv7",
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 Build
= XamarinAndroid
? "arm64-v8a" : "mono-aarch64",
123 Defines
= { "TARGET_ARM64" }
126 /*Targets.Add(new Target {
127 Platform = TargetPlatform.Android,
128 Triple = "mipsel-none-linux-android",
130 Defines = { "TARGET_MIPS", "__mips__" }
133 foreach (var target
in AndroidTargets
)
134 target
.Defines
.AddRange (new string[] { "PLATFORM_ANDROID",
135 "TARGET_ANDROID", "MONO_CROSS_COMPILE", "USE_MONO_CTX"
139 public static void SetupiOSTargets()
141 Targets
.Add(new Target
{
142 Platform
= TargetPlatform
.iOS
,
143 Triple
= "arm-apple-darwin10",
145 Defines
= { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
148 Targets
.Add(new Target
{
149 Platform
= TargetPlatform
.iOS
,
150 Triple
= "aarch64-apple-darwin10",
152 Defines
= { "TARGET_ARM64" }
155 foreach (var target
in iOSTargets
) {
156 target
.Defines
.AddRange (new string[] { "PLATFORM_DARWIN",
157 "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX",
162 Targets
.Add(new Target
{
163 Platform
= TargetPlatform
.WatchOS
,
164 Triple
= "armv7k-apple-darwin",
165 Build
= "targetwatch",
166 Defines
= { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" }
169 foreach (var target
in DarwinTargets
) {
170 target
.Defines
.AddRange (new string[] { "PLATFORM_DARWIN",
171 "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX",
177 static bool GetParentSubDirectoryPath(string parent
, out string subdir
)
179 var directory
= Directory
.GetParent(Directory
.GetCurrentDirectory());
181 while (directory
!= null) {
182 var path
= Path
.Combine(directory
.FullName
, parent
);
184 if (Directory
.Exists (path
)) {
189 directory
= directory
.Parent
;
196 public static void Main(string[] args
)
198 ParseCommandLineArgs(args
);
201 if (!Directory
.Exists (MonodroidDir
) &&
202 GetParentSubDirectoryPath ("monodroid", out monodroidDir
)) {
203 MonodroidDir
= Path
.Combine (monodroidDir
);
206 if (Directory
.Exists (MonodroidDir
))
207 SetupAndroidTargets();
210 if (!Directory
.Exists (MaccoreDir
) &&
211 GetParentSubDirectoryPath ("maccore", out maccoreDir
)) {
212 MaccoreDir
= Path
.Combine (maccoreDir
);
215 if (Directory
.Exists(MaccoreDir
))
218 foreach (var target
in Targets
)
220 if (Abis
.Any() && !Abis
.Any (target
.Triple
.Contains
))
224 Console
.WriteLine("Processing triple: {0}", target
.Triple
);
226 var options
= new DriverOptions();
228 var log
= new TextDiagnosticPrinter();
229 var driver
= new Driver(options
, log
);
231 Setup(driver
, target
);
234 BuildParseOptions(driver
, target
);
235 if (!driver
.ParseCode())
238 Dump(driver
.Context
.ASTContext
, driver
.Context
.TargetInfo
, target
);
242 static void BuildParseOptions(Driver driver
, Target target
)
244 foreach (var header
in driver
.Options
.Headers
)
246 var source
= driver
.Project
.AddFile(header
);
247 source
.Options
= driver
.BuildParserOptions(source
);
249 if (header
.Contains ("mini"))
252 source
.Options
.AddDefines ("HAVE_SGEN_GC");
253 source
.Options
.AddDefines ("HAVE_MOVING_COLLECTOR");
257 static string GetAndroidNdkPath()
259 if (!String
.IsNullOrEmpty (AndroidNdkPath
))
260 return AndroidNdkPath
;
262 // Find the Android NDK's path from Monodroid's config.
263 var configFile
= Path
.Combine(MonodroidDir
, "env.config");
264 if (!File
.Exists(configFile
))
265 throw new Exception("Expected a valid Monodroid environment config file at " + configFile
);
267 var config
= File
.ReadAllText(configFile
);
268 var match
= Regex
.Match(config
, @"ANDROID_NDK_PATH\s*:=\s(.*)");
269 return match
.Groups
[1].Value
.Trim();
272 static void ParseCommandLineArgs(string[] args
)
274 var showHelp
= false;
276 var options
= new Mono
.Options
.OptionSet () {
277 { "abi=", "ABI triple to generate", v => Abis.Add(v) }
,
278 { "o|out=", "output directory", v => OutputDir = v }
,
279 { "maccore=", "include directory", v => MaccoreDir = v }
,
280 { "monodroid=", "top monodroid directory", v => MonodroidDir = v }
,
281 { "android-ndk=", "Path to Android NDK", v => AndroidNdkPath = v }
,
282 { "xamarin-android", "Generate for Xamarin.Android instead of monodroid", v => XamarinAndroid = true }
,
283 { "mono=", "include directory", v => MonoDir = v }
,
284 { "h|help", "show this message and exit", v => showHelp = v != null }
,
288 options
.Parse (args
);
290 catch (Mono
.Options
.OptionException e
) {
291 Console
.WriteLine (e
.Message
);
297 // Print usage and exit.
298 Console
.WriteLine("{0} [--abi=triple] [--out=dir] "
299 + "[--monodroid/maccore=dir] [--mono=dir]",
300 AppDomain
.CurrentDomain
.FriendlyName
);
305 static void Setup(Driver driver
, Target target
)
307 var options
= driver
.Options
;
308 options
.DryRun
= true;
309 options
.LibraryName
= "Mono";
311 var parserOptions
= driver
.ParserOptions
;
312 parserOptions
.Verbose
= false;
313 parserOptions
.MicrosoftMode
= false;
314 parserOptions
.AddArguments("-xc");
315 parserOptions
.AddArguments("-std=gnu99");
316 parserOptions
.AddDefines("CPPSHARP");
318 foreach (var define
in target
.Defines
)
319 parserOptions
.AddDefines(define
);
321 SetupToolchainPaths(driver
, target
);
323 SetupMono(driver
, target
);
326 static void SetupMono(Driver driver
, Target target
)
329 switch (target
.Platform
) {
330 case TargetPlatform
.Android
:
331 targetPath
= Path
.Combine (MonodroidDir
, XamarinAndroid
? "build-tools/mono-runtimes/obj/Debug" : "builds");
333 case TargetPlatform
.WatchOS
:
334 case TargetPlatform
.iOS
:
335 targetPath
= Path
.Combine (MaccoreDir
, "builds");
338 throw new ArgumentOutOfRangeException ();
341 if (!Directory
.Exists (MonoDir
)) {
342 MonoDir
= Path
.GetFullPath (Path
.Combine (targetPath
, "../../mono"));
345 var targetBuild
= Path
.Combine(targetPath
, target
.Build
);
347 if (!Directory
.Exists(targetBuild
))
348 throw new Exception(string.Format("Could not find the target build directory: {0}", targetBuild
));
350 var includeDirs
= new[]
353 Path
.Combine(targetBuild
, "eglib", "src"),
355 Path
.Combine(MonoDir
, "mono"),
356 Path
.Combine(MonoDir
, "mono", "mini"),
357 Path
.Combine(MonoDir
, "eglib", "src")
360 foreach (var inc
in includeDirs
)
361 driver
.ParserOptions
.AddIncludeDirs(inc
);
363 var filesToParse
= new[]
365 Path
.Combine(MonoDir
, "mono", "metadata", "metadata-cross-helpers.c"),
366 Path
.Combine(MonoDir
, "mono", "mini", "mini-cross-helpers.c"),
369 foreach (var file
in filesToParse
)
370 driver
.Options
.Headers
.Add(file
);
373 static void SetupMSVC(Driver driver
, string triple
)
375 var parserOptions
= driver
.ParserOptions
;
377 parserOptions
.Abi
= Parser
.AST
.CppAbi
.Microsoft
;
378 parserOptions
.MicrosoftMode
= true;
380 var systemIncludeDirs
= new[]
382 @"C:\Program Files (x86)\Windows Kits\8.1\Include\um",
383 @"C:\Program Files (x86)\Windows Kits\8.1\Include\shared"
386 foreach (var inc
in systemIncludeDirs
)
387 parserOptions
.AddSystemIncludeDirs(inc
);
389 parserOptions
.AddDefines("HOST_WIN32");
392 static void SetupToolchainPaths(Driver driver
, Target target
)
394 switch (target
.Platform
) {
395 case TargetPlatform
.Android
:
396 SetupAndroidNDK(driver
, target
);
398 case TargetPlatform
.iOS
:
399 case TargetPlatform
.WatchOS
:
400 SetupXcode(driver
, target
);
403 throw new ArgumentOutOfRangeException ();
407 static string GetArchFromTriple(string triple
)
409 if (triple
.Contains("mips"))
412 if (triple
.Contains("arm64") || triple
.Contains("aarch64"))
415 if (triple
.Contains("arm"))
418 if (triple
.Contains("i686"))
421 if (triple
.Contains("x86_64"))
424 throw new Exception("Unknown architecture from triple: " + triple
);
427 static string GetXcodeToolchainPath()
429 var toolchains
= Directory
.EnumerateDirectories("/Applications", "Xcode*")
433 var toolchainPath
= toolchains
.LastOrDefault();
434 if (toolchainPath
== null)
435 throw new Exception("Could not find a valid Xcode SDK");
437 return toolchainPath
;
440 static string GetXcodeBuiltinIncludesFolder()
442 var toolchainPath
= GetXcodeToolchainPath();
444 var toolchains
= Directory
.EnumerateDirectories(Path
.Combine(toolchainPath
,
445 "Contents/Developer/Toolchains")).ToList();
448 toolchainPath
= toolchains
.LastOrDefault();
449 if (toolchainPath
== null)
450 throw new Exception("Could not find a valid Xcode toolchain");
452 var includePaths
= Directory
.EnumerateDirectories(Path
.Combine(toolchainPath
,
453 "usr/lib/clang")).ToList();
454 var includePath
= includePaths
.LastOrDefault();
456 if (includePath
== null)
457 throw new Exception("Could not find a valid Clang include folder");
459 return Path
.Combine(includePath
, "include");
462 static string GetXcodeiOSIncludesFolder()
464 var toolchainPath
= GetXcodeToolchainPath();
466 var sdkPaths
= Directory
.EnumerateDirectories(Path
.Combine(toolchainPath
,
467 "Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs")).ToList();
468 var sdkPath
= sdkPaths
.LastOrDefault();
471 throw new Exception("Could not find a valid iPhone SDK");
473 return Path
.Combine(sdkPath
, "usr/include");
476 static string GetXcodeWatchOSIncludesFolder()
478 var toolchainPath
= GetXcodeToolchainPath();
480 var sdkPaths
= Directory
.EnumerateDirectories(Path
.Combine(toolchainPath
,
481 "Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs")).ToList();
482 var sdkPath
= sdkPaths
.LastOrDefault();
485 throw new Exception("Could not find a valid WatchOS SDK");
487 return Path
.Combine(sdkPath
, "usr/include");
490 static void SetupXcode(Driver driver
, Target target
)
492 var parserOptions
= driver
.ParserOptions
;
494 var builtinsPath
= GetXcodeBuiltinIncludesFolder();
497 switch (target
.Platform
) {
498 case TargetPlatform
.iOS
:
499 includePath
= GetXcodeiOSIncludesFolder();
501 case TargetPlatform
.WatchOS
:
502 includePath
= GetXcodeWatchOSIncludesFolder();
505 throw new ArgumentOutOfRangeException ();
508 parserOptions
.AddSystemIncludeDirs(builtinsPath
);
509 parserOptions
.AddSystemIncludeDirs(includePath
);
511 parserOptions
.NoBuiltinIncludes
= true;
512 parserOptions
.NoStandardIncludes
= true;
513 parserOptions
.TargetTriple
= target
.Triple
;
516 static string GetAndroidHostToolchainPath()
518 var androidNdkPath
= GetAndroidNdkPath ();
519 var toolchains
= Directory
.EnumerateDirectories(
520 Path
.Combine(androidNdkPath
, "toolchains"), "llvm*").ToList();
523 var toolchainPath
= toolchains
.LastOrDefault();
524 if (toolchainPath
== null)
525 throw new Exception("Could not find a valid NDK host toolchain");
527 toolchains
= Directory
.EnumerateDirectories(Path
.Combine(toolchainPath
,
528 "prebuilt")).ToList();
531 toolchainPath
= toolchains
.LastOrDefault();
532 if (toolchainPath
== null)
533 throw new Exception("Could not find a valid NDK host toolchain");
535 return toolchainPath
;
538 static string GetAndroidBuiltinIncludesFolder()
540 var toolchainPath
= GetAndroidHostToolchainPath();
542 string clangToolchainPath
= Path
.Combine(toolchainPath
, "lib64", "clang");
543 if (!Directory
.Exists (clangToolchainPath
))
544 clangToolchainPath
= Path
.Combine(toolchainPath
, "lib", "clang");
546 string includePath
= null;
547 if (Directory
.Exists (clangToolchainPath
)) {
548 var includePaths
= Directory
.EnumerateDirectories(clangToolchainPath
).ToList();
549 includePath
= includePaths
.LastOrDefault();
551 if (includePath
== null)
552 throw new Exception("Could not find a valid Clang include folder");
554 return Path
.Combine(includePath
, "include");
557 static void SetupAndroidNDK(Driver driver
, Target target
)
559 var options
= driver
.Options
;
560 var parserOptions
= driver
.ParserOptions
;
562 var builtinsPath
= GetAndroidBuiltinIncludesFolder();
563 parserOptions
.AddSystemIncludeDirs(builtinsPath
);
565 var androidNdkRoot
= GetAndroidNdkPath ();
566 const int androidNdkApiLevel
= 21;
568 var toolchainPath
= Path
.Combine(androidNdkRoot
, "platforms",
569 "android-" + androidNdkApiLevel
, "arch-" + GetArchFromTriple(target
.Triple
),
571 parserOptions
.AddSystemIncludeDirs(toolchainPath
);
573 parserOptions
.NoBuiltinIncludes
= true;
574 parserOptions
.NoStandardIncludes
= true;
575 parserOptions
.TargetTriple
= target
.Triple
;
578 static uint GetTypeAlign(ParserTargetInfo target
, ParserIntType type
)
582 case ParserIntType
.SignedChar
:
583 case ParserIntType
.UnsignedChar
:
584 return target
.CharAlign
;
585 case ParserIntType
.SignedShort
:
586 case ParserIntType
.UnsignedShort
:
587 return target
.ShortAlign
;
588 case ParserIntType
.SignedInt
:
589 case ParserIntType
.UnsignedInt
:
590 return target
.IntAlign
;
591 case ParserIntType
.SignedLong
:
592 case ParserIntType
.UnsignedLong
:
593 return target
.LongAlign
;
594 case ParserIntType
.SignedLongLong
:
595 case ParserIntType
.UnsignedLongLong
:
596 return target
.LongLongAlign
;
598 throw new Exception("Type has no alignment");
602 static uint GetTypeSize(ParserTargetInfo target
, ParserIntType type
)
606 case ParserIntType
.SignedChar
:
607 case ParserIntType
.UnsignedChar
:
608 return target
.CharWidth
;
609 case ParserIntType
.SignedShort
:
610 case ParserIntType
.UnsignedShort
:
611 return target
.ShortWidth
;
612 case ParserIntType
.SignedInt
:
613 case ParserIntType
.UnsignedInt
:
614 return target
.IntWidth
;
615 case ParserIntType
.SignedLong
:
616 case ParserIntType
.UnsignedLong
:
617 return target
.LongWidth
;
618 case ParserIntType
.SignedLongLong
:
619 case ParserIntType
.UnsignedLongLong
:
620 return target
.LongLongWidth
;
622 throw new Exception("Type has no size");
626 static string GetTargetPlatformDefine(TargetPlatform target
)
629 case TargetPlatform
.Android
:
630 return "TARGET_ANDROID";
631 case TargetPlatform
.iOS
:
633 case TargetPlatform
.WatchOS
:
634 return "TARGET_WATCHOS";
636 throw new ArgumentOutOfRangeException ();
640 static void Dump(ASTContext ctx
, ParserTargetInfo targetInfo
, Target target
)
642 var targetFile
= target
.Triple
;
644 if (!string.IsNullOrEmpty (OutputDir
))
645 targetFile
= Path
.Combine (OutputDir
, targetFile
);
649 using (var writer
= new StreamWriter(targetFile
))
650 //using (var writer = Console.Out)
652 writer
.WriteLine("#ifndef USED_CROSS_COMPILER_OFFSETS");
653 writer
.WriteLine("#ifdef {0}", target
.Defines
[0]);
654 writer
.WriteLine ("#ifdef {0}", GetTargetPlatformDefine (target
.Platform
));
655 writer
.WriteLine("#ifndef HAVE_BOEHM_GC");
656 writer
.WriteLine("#define HAS_CROSS_COMPILER_OFFSETS");
657 writer
.WriteLine("#if defined (USE_CROSS_COMPILE_OFFSETS) || defined (MONO_CROSS_COMPILE)");
658 writer
.WriteLine("#if !defined (DISABLE_METADATA_OFFSETS)");
659 writer
.WriteLine("#define USED_CROSS_COMPILER_OFFSETS");
661 DumpAligns(writer
, targetInfo
);
662 DumpSizes(writer
, targetInfo
);
663 DumpMetadataOffsets(writer
, ctx
, target
);
665 writer
.WriteLine("#endif //disable metadata check");
667 DumpJITOffsets(writer
, ctx
);
669 writer
.WriteLine("#endif //cross compiler checks");
670 writer
.WriteLine("#endif //gc check");
671 writer
.WriteLine("#endif //os check");
672 writer
.WriteLine("#endif //arch check");
673 writer
.WriteLine("#endif //USED_CROSS_COMPILER_OFFSETS check");
676 Console
.WriteLine("Generated offsets file: {0}", targetFile
);
679 static void DumpAligns(TextWriter writer
, ParserTargetInfo target
)
683 new { Name = "gint8", Align = target.CharAlign}
,
684 new { Name = "gint16", Align = target.ShortAlign}
,
685 new { Name = "gint32", Align = target.IntAlign}
,
686 new { Name = "gint64", Align = GetTypeAlign(target, target.Int64Type)}
,
687 new { Name = "float", Align = target.FloatAlign}
,
688 new { Name = "double", Align = target.DoubleAlign}
,
689 new { Name = "gpointer", Align = GetTypeAlign(target, target.IntPtrType)}
,
692 // Write the alignment info for the basic types.
693 foreach (var align
in aligns
)
694 writer
.WriteLine("DECL_ALIGN2({0},{1})", align
.Name
, align
.Align
/ 8);
697 static void DumpSizes(TextWriter writer
, ParserTargetInfo target
)
701 new { Name = "gint8", Size = target.CharWidth}
,
702 new { Name = "gint16", Size = target.ShortWidth}
,
703 new { Name = "gint32", Size = target.IntWidth}
,
704 new { Name = "gint64", Size = GetTypeSize(target, target.Int64Type)}
,
705 new { Name = "float", Size = target.FloatWidth}
,
706 new { Name = "double", Size = target.DoubleWidth}
,
707 new { Name = "gpointer", Size = GetTypeSize(target, target.IntPtrType)}
,
710 // Write the size info for the basic types.
711 foreach (var size
in sizes
)
712 writer
.WriteLine("DECL_SIZE2({0},{1})", size
.Name
, size
.Size
/ 8);
715 static Class
GetClassFromTypedef(ITypedDecl typedef
)
717 var type
= typedef
.Type
.Desugar() as TagType
;
721 var @class = type
.Declaration
as Class
;
723 return @class.IsIncomplete
?
724 (@class.CompleteDeclaration
as Class
) : @class;
727 static void DumpClasses(TextWriter writer
, ASTContext ctx
, IEnumerable
<string> types
,
728 bool optional
= false)
730 foreach (var @struct in types
)
732 var @class = ctx
.FindCompleteClass(@struct);
734 @class = ctx
.FindCompleteClass("_" + @struct);
738 var typedef
= ctx
.FindTypedef(@struct).FirstOrDefault(
739 decl
=> !decl
.IsIncomplete
);
742 @class = GetClassFromTypedef(typedef
);
745 if (@class == null && optional
)
749 throw new Exception("Expected to find struct definition for " + @struct);
751 DumpStruct(writer
, @class);
755 static void DumpMetadataOffsets(TextWriter writer
, ASTContext ctx
, Target target
)
757 var types
= new List
<string>
760 "MonoObjectHandlePayload",
764 "MonoInternalThread",
765 "MonoMulticastDelegate",
766 "MonoTransparentProxy",
773 "MonoComInteropProxy",
779 "SgenClientThreadInfo"
782 DumpClasses(writer
, ctx
, types
);
785 static void DumpJITOffsets(TextWriter writer
, ASTContext ctx
)
787 writer
.WriteLine("#ifndef DISABLE_JIT_OFFSETS");
788 writer
.WriteLine("#define USED_CROSS_COMPILER_OFFSETS");
793 "MonoMethodRuntimeGenericContext",
795 "MonoGSharedVtMethodRuntimeInfo",
798 "MonoDelegateTrampInfo",
801 DumpClasses(writer
, ctx
, types
);
803 var optionalTypes
= new[]
811 DumpClasses(writer
, ctx
, optionalTypes
, optional
: true);
813 writer
.WriteLine("#endif //disable jit check");
816 static void DumpStruct(TextWriter writer
, Class
@class)
818 var name
= @class.Name
;
819 if (name
.StartsWith ("_", StringComparison
.Ordinal
))
820 name
= name
.Substring (1);
822 foreach (var field
in @class.Fields
)
824 if (field
.IsBitField
) continue;
826 if (name
== "SgenThreadInfo" && field
.Name
== "regs")
829 var layout
= @class.Layout
.Fields
.First(f
=> f
.FieldPtr
== field
.OriginalPtr
);
831 writer
.WriteLine("DECL_OFFSET2({0},{1},{2})", name
, field
.Name
,