Brak opisu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Burst.bee.cs 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Bee.Core;
  5. using Bee.DotNet;
  6. using JetBrains.Annotations;
  7. using NiceIO;
  8. #if NEW_BEE_NAMESPACES_REMOVE
  9. using Bee.NativeProgramSupport;
  10. using Bee.Tools;
  11. #else
  12. using Unity.BuildSystem.NativeProgramSupport;
  13. using Unity.BuildTools;
  14. #endif
  15. /*
  16. // Activate this part once we have found a workaround for compiling against a custom Unity.Burst.Unsafe
  17. // compatible with Tiny. See issue #1490
  18. [UsedImplicitly]
  19. class CustomizerForUnityBurst : AsmDefCSharpProgramCustomizer
  20. {
  21. public override string CustomizerFor => "Unity.Burst";
  22. // not exactly right, but good enough for now
  23. public override void CustomizeSelf(AsmDefCSharpProgram program)
  24. {
  25. var path = program.AsmDefDescription.Path.Parent.Parent.Combine("Unity.Burst.Unsafe.dll");
  26. program.References.Add(new DotNetAssembly(path, Framework.NetStandard20));
  27. }
  28. }
  29. */
  30. /*
  31. * This file exists as an interface to programs that want to invoke bcl.exe from a bee buildprogram.
  32. * The idea is that when bcl.exe command line options change, this file should change, and then programs using
  33. * burst will pick up the changes for free, without depending on specific command line options of bcl.exe.
  34. *
  35. * How well that works, is another question.
  36. */
  37. public abstract class BurstCompiler
  38. {
  39. public static NPath BurstExecutable { get; set; }
  40. public abstract string TargetPlatform { get; set; }
  41. // TODO: This should become a list of target architectures to add.
  42. public abstract string TargetArchitecture { get; set; }
  43. public abstract string ObjectFormat { get; set; }
  44. public abstract string ObjectFileExtension { get; set; }
  45. public abstract bool UseOwnToolchain { get; set; }
  46. public virtual bool OnlyStaticMethods { get; set; } = false;
  47. public virtual string BurstBackend { get; set; } = "burst-llvm-10"; // Bumping this, but really should not be specifying by default, or when we bump llvm dots runtime gets left behind
  48. // Options
  49. public virtual bool SafetyChecks { get; set; } = false;
  50. public virtual bool DisableVectors { get; set; } = false;
  51. public virtual bool Link { get; set; } = true;
  52. public virtual bool Verbose { get; set; } = false;
  53. public abstract string FloatPrecision { get; set; }
  54. public virtual int Threads { get; set; } = 9;
  55. public virtual bool DisableOpt { get; set; } = false;
  56. public virtual bool EnableGuard { get; set; } = false;
  57. public virtual string ExecuteMethodName { get; set; } = "ProducerExecuteFn_Gen";
  58. public virtual bool EnableStaticLinkage { get; set; } = false;
  59. public virtual bool EnableJobMarshalling { get; set; } = false;
  60. public virtual bool EnableDirectExternalLinking { get; set; } = false;
  61. public virtual string DisableWarnings { get; set; } = ""; // ; seperated list of ids, e.g. BC1370;BC1322
  62. public virtual bool EmitLlvmObjects { get; set; } = false; // Added because burst now compiles/links wasm code as native objects by default
  63. static string[] GetBurstCommandLineArgs(
  64. BurstCompiler compiler,
  65. NPath outputPrefixForObjectFile,
  66. NPath outputDirForPatchedAssemblies,
  67. string pinvokeName,
  68. DotNetAssembly[] inputAssemblies)
  69. {
  70. var commandLineArguments = new[]
  71. {
  72. $"--platform={compiler.TargetPlatform}",
  73. $"--target={compiler.TargetArchitecture}",
  74. $"--format={compiler.ObjectFormat}",
  75. compiler.SafetyChecks ? "--safety-checks" : "",
  76. $"--dump=None",
  77. compiler.DisableVectors ? "--disable-vectors" : "",
  78. compiler.Link ? "" : "--nolink",
  79. $"--float-precision={compiler.FloatPrecision}",
  80. $"--keep-intermediate-files",
  81. compiler.EmitLlvmObjects?"--emit-llvm-objects":"",
  82. compiler.Verbose ? "--verbose" : "",
  83. $"--patch-assemblies-into={outputDirForPatchedAssemblies}",
  84. $"--output={outputPrefixForObjectFile}",
  85. compiler.OnlyStaticMethods ? "--only-static-methods" : "",
  86. "--method-prefix=burstedmethod_",
  87. $"--pinvoke-name={pinvokeName}",
  88. $"--backend={compiler.BurstBackend}",
  89. $"--execute-method-name={compiler.ExecuteMethodName}",
  90. "--debug=Full",
  91. compiler.EnableDirectExternalLinking ? "--enable-direct-external-linking" : "",
  92. compiler.DisableOpt ? "--disable-opt" : "",
  93. $"--threads={compiler.Threads}",
  94. compiler.EnableGuard ? "--enable-guard" : "",
  95. !String.IsNullOrEmpty(compiler.DisableWarnings) ? $"--disable-warnings={compiler.DisableWarnings}" : ""
  96. }.Concat(inputAssemblies.Select(asm => $"--root-assembly={asm.Path}"));
  97. if (!compiler.UseOwnToolchain)
  98. commandLineArguments = commandLineArguments.Concat(new[] {"--no-native-toolchain"});
  99. if (!HostPlatform.IsWindows)
  100. commandLineArguments = new[] {BurstExecutable.ToString(SlashMode.Native)}.Concat(commandLineArguments);
  101. if (compiler.EnableStaticLinkage)
  102. commandLineArguments = commandLineArguments.Concat(new[] {"--generate-static-linkage-methods"});
  103. if (compiler.EnableJobMarshalling)
  104. commandLineArguments = commandLineArguments.Concat(new[] { "--generate-job-marshalling-methods" });
  105. return commandLineArguments.ToArray();
  106. }
  107. static IEnumerable<NPath> AddDebugSymbolPaths(DotNetAssembly[] assemblies)
  108. {
  109. return assemblies.SelectMany(
  110. asm =>
  111. {
  112. var ret = new List<NPath> {asm.Path};
  113. if (asm.DebugSymbolPath != null)
  114. ret.Add(asm.DebugSymbolPath);
  115. return ret;
  116. });
  117. }
  118. static string[] ArgumentsToResponseFile(bool usesMono, NPath targetDir, string[] commandLineArgs, out NPath responseFile)
  119. {
  120. var remainingArgs = usesMono? commandLineArgs.Skip(1) : commandLineArgs;
  121. var joinedArgs = String.Join(Environment.NewLine, remainingArgs.Where(s => !String.IsNullOrEmpty(s)));
  122. KnuthHash hash = new KnuthHash();
  123. hash.Add(joinedArgs);
  124. responseFile = targetDir.Combine($"{hash.Value}.rsp");
  125. Backend.Current.AddWriteTextAction(
  126. responseFile,
  127. joinedArgs,
  128. "BurstResponseFile");
  129. if (usesMono)
  130. {
  131. return new [] { commandLineArgs[0], $"@{responseFile}"};
  132. }
  133. return new [] {$"@{responseFile}"};
  134. }
  135. public static BagOfObjectFilesLibrary SetupBurstCompilationForAssemblies(
  136. BurstCompiler compiler,
  137. DotNetAssembly unpatchedInputAssembly,
  138. NPath outputDirForObjectFile,
  139. NPath outputDirForPatchedAssemblies,
  140. string pinvokeName,
  141. out DotNetAssembly patchedAssembly)
  142. {
  143. /*
  144. * Note that you can have Link be true and still use this, because on iOS for example if you
  145. * DON'T pass --no-link, it will NOT link, but it WILL correctly override the llvm backend.
  146. *
  147. * if you DO pass --no-link, it will also not link, but then incorrectly use llvm 9.
  148. */
  149. patchedAssembly = unpatchedInputAssembly.ApplyDotNetAssembliesPostProcessor(
  150. outputDirForPatchedAssemblies,
  151. (inputAssemblies, targetDir) =>
  152. {
  153. var usesMono = HostPlatform.IsWindows ? false : true;
  154. var executableStringFor = !usesMono ? BurstExecutable.ToString(SlashMode.Native) : "mono";
  155. var commandLineArgs = GetBurstCommandLineArgs(
  156. compiler,
  157. outputDirForObjectFile.Combine(pinvokeName),
  158. outputDirForPatchedAssemblies,
  159. pinvokeName,
  160. inputAssemblies);
  161. var inputPaths = AddDebugSymbolPaths(inputAssemblies);
  162. var targetFiles = inputPaths.Select(p => targetDir.Combine(p.FileName));
  163. var finalArguments = ArgumentsToResponseFile(usesMono, targetDir, commandLineArgs, out var responseFile);
  164. Backend.Current.AddAction(
  165. "Burst",
  166. //todo: make burst process pdbs
  167. targetFiles.ToArray(),
  168. inputPaths.Concat(new[] {BurstExecutable, responseFile}).ToArray(),
  169. executableStringFor,
  170. finalArguments,
  171. targetDirectories: new[] {outputDirForObjectFile}
  172. );
  173. });
  174. var needFake = true;
  175. NPath[] objectFileList = null;
  176. if (outputDirForObjectFile.Exists())
  177. {
  178. objectFileList = outputDirForObjectFile.Files($"*{compiler.ObjectFileExtension}");
  179. if (objectFileList.Length > 0)
  180. needFake = false;
  181. }
  182. if (needFake)
  183. objectFileList = new[] {outputDirForObjectFile.Combine($"fake{compiler.ObjectFileExtension}")};
  184. return new BagOfObjectFilesLibrary(objectFileList);
  185. }
  186. public static DynamicLibrary SetupBurstCompilationAndLinkForAssemblies(
  187. BurstCompiler compiler,
  188. DotNetAssembly unpatchedInputAssembly,
  189. NPath targetNativeLibrary,
  190. NPath outputDirForPatchedAssemblies,
  191. out DotNetAssembly patchedAssembly)
  192. {
  193. if (!compiler.Link)
  194. {
  195. throw new ArgumentException("BurstCompiler.Link must be true for SetupBurstCompilationAndLinkForAssemblies");
  196. }
  197. patchedAssembly = unpatchedInputAssembly.ApplyDotNetAssembliesPostProcessor(
  198. outputDirForPatchedAssemblies,
  199. (inputAssemblies, targetDir) =>
  200. {
  201. var usesMono = HostPlatform.IsWindows ? false : true;
  202. var executableStringFor = !usesMono ? BurstExecutable.ToString(SlashMode.Native) : "mono";
  203. var pinvokeName = HostPlatform.IsWindows
  204. ? targetNativeLibrary.FileNameWithoutExtension
  205. : targetNativeLibrary.FileName;
  206. var commandLineArgs = GetBurstCommandLineArgs(
  207. compiler,
  208. targetNativeLibrary.ChangeExtension(""),
  209. outputDirForPatchedAssemblies,
  210. pinvokeName,
  211. inputAssemblies);
  212. var inputPaths = AddDebugSymbolPaths(inputAssemblies);
  213. var targetFiles = inputPaths.Select(p => targetDir.Combine(p.FileName))
  214. .Concat(new[] {targetNativeLibrary});
  215. var finalArguments = ArgumentsToResponseFile(usesMono, targetDir, commandLineArgs, out var responseFile);
  216. Backend.Current.AddAction(
  217. "Burst",
  218. //todo: make burst process pdbs
  219. targetFiles.ToArray(),
  220. inputPaths.Concat(new[] {BurstExecutable, responseFile}).ToArray(),
  221. executableStringFor,
  222. finalArguments
  223. );
  224. });
  225. return new DynamicLibrary(targetNativeLibrary, symbolFiles: null);
  226. }
  227. }
  228. public class BurstCompilerForEmscripten : BurstCompiler
  229. {
  230. public override string TargetPlatform { get; set; } = "Wasm";
  231. public override string TargetArchitecture { get; set; } = "WASM32";
  232. public override string ObjectFormat { get; set; } = "Wasm";
  233. public override string FloatPrecision { get; set; } = "High";
  234. public override bool SafetyChecks { get; set; } = true;
  235. public override bool DisableVectors { get; set; } = true;
  236. public override bool Link { get; set; } = false;
  237. public override string ObjectFileExtension { get; set; } = ".bc";
  238. public override bool UseOwnToolchain { get; set; } = false;
  239. public override bool EnableStaticLinkage { get; set; } = true;
  240. public override bool EnableJobMarshalling { get; set; } = false;
  241. public override bool EnableDirectExternalLinking { get; set; } = true;
  242. public override bool EmitLlvmObjects { get; set; } = true; // Added because burst now compiles/links wasm code as native objects by default
  243. }
  244. public class BurstCompilerForWindows : BurstCompiler
  245. {
  246. public override string TargetPlatform { get; set; } = "Windows";
  247. //--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
  248. // SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
  249. // AARCH64|THUMB2_NEON32> Default: Auto
  250. public override string TargetArchitecture { get; set; } = "X64_SSE2";
  251. public override string ObjectFormat { get; set; } = "Coff";
  252. public override string FloatPrecision { get; set; } = "High";
  253. public override bool SafetyChecks { get; set; } = true;
  254. public override bool DisableVectors { get; set; } = false;
  255. public override bool Link { get; set; } = false; //true;
  256. public override string ObjectFileExtension { get; set; } = ".obj";
  257. public override bool UseOwnToolchain { get; set; } = true;
  258. public override bool EnableDirectExternalLinking { get; set; } = false;
  259. //public override string BurstBackend { get; set; } = "burst-llvm-custom";
  260. public override bool EnableJobMarshalling { get; set; } = true;
  261. }
  262. public class BurstCompilerForWindows64 : BurstCompilerForWindows
  263. {
  264. public override string TargetArchitecture { get; set; } = "X64_SSE4";
  265. }
  266. public class BurstCompilerForMac : BurstCompiler
  267. {
  268. public override string TargetPlatform { get; set; } = "macOS";
  269. //--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
  270. // SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
  271. // AARCH64|THUMB2_NEON32> Default: Auto
  272. public override string TargetArchitecture { get; set; } = "X64_SSE2";
  273. public override string ObjectFormat { get; set; } = "MachO";
  274. public override string FloatPrecision { get; set; } = "High";
  275. public override bool SafetyChecks { get; set; } = true;
  276. public override bool DisableVectors { get; set; } = false;
  277. public override bool Link { get; set; } = false;
  278. public override string ObjectFileExtension { get; set; } = ".o";
  279. public override bool UseOwnToolchain { get; set; } = true;
  280. }
  281. public class BurstCompilerForAndroid : BurstCompiler
  282. {
  283. public override string TargetPlatform { get; set; } = "Android";
  284. //--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
  285. // SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
  286. // AARCH64|THUMB2_NEON32> Default: Auto
  287. public override string TargetArchitecture { get; set; } = "ARMV7A_NEON32";
  288. public override string ObjectFormat { get; set; } = "Elf";
  289. public override string FloatPrecision { get; set; } = "High";
  290. public override bool SafetyChecks { get; set; } = true;
  291. public override bool DisableVectors { get; set; } = false;
  292. public override bool Link { get; set; } = false;
  293. public override string ObjectFileExtension { get; set; } = ".o";
  294. public override bool UseOwnToolchain { get; set; } = true;
  295. public override bool EnableDirectExternalLinking { get; set; } = true;
  296. }
  297. public class BurstCompilerForiOS : BurstCompiler
  298. {
  299. public override string TargetPlatform { get; set; } = "iOS";
  300. //--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
  301. // SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
  302. // AARCH64|THUMB2_NEON32> Default: Auto
  303. public override string TargetArchitecture { get; set; } = "ARMV8A_AARCH64";
  304. public override string ObjectFormat { get; set; } = "Elf";
  305. public override bool SafetyChecks { get; set; } = true;
  306. public override bool DisableVectors { get; set; } = false;
  307. public override bool Link { get; set; } = true;
  308. public override string FloatPrecision { get; set; } = "High";
  309. public override string ObjectFileExtension { get; set; } = ".o";
  310. public override bool UseOwnToolchain { get; set; } = true;
  311. public override bool EnableDirectExternalLinking { get; set; } = true;
  312. }