Singularity/Library/PackageCache/com.unity.burst@1.8.4/Runtime/bee~/Burst.bee.cs
2024-05-06 11:45:45 -07:00

369 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Bee.Core;
using Bee.DotNet;
using JetBrains.Annotations;
using NiceIO;
#if NEW_BEE_NAMESPACES_REMOVE
using Bee.NativeProgramSupport;
using Bee.Tools;
#else
using Unity.BuildSystem.NativeProgramSupport;
using Unity.BuildTools;
#endif
/*
// Activate this part once we have found a workaround for compiling against a custom Unity.Burst.Unsafe
// compatible with Tiny. See issue #1490
[UsedImplicitly]
class CustomizerForUnityBurst : AsmDefCSharpProgramCustomizer
{
public override string CustomizerFor => "Unity.Burst";
// not exactly right, but good enough for now
public override void CustomizeSelf(AsmDefCSharpProgram program)
{
var path = program.AsmDefDescription.Path.Parent.Parent.Combine("Unity.Burst.Unsafe.dll");
program.References.Add(new DotNetAssembly(path, Framework.NetStandard20));
}
}
*/
/*
* This file exists as an interface to programs that want to invoke bcl.exe from a bee buildprogram.
* The idea is that when bcl.exe command line options change, this file should change, and then programs using
* burst will pick up the changes for free, without depending on specific command line options of bcl.exe.
*
* How well that works, is another question.
*/
public abstract class BurstCompiler
{
public static NPath BurstExecutable { get; set; }
public abstract string TargetPlatform { get; set; }
// TODO: This should become a list of target architectures to add.
public abstract string TargetArchitecture { get; set; }
public abstract string ObjectFormat { get; set; }
public abstract string ObjectFileExtension { get; set; }
public abstract bool UseOwnToolchain { get; set; }
public virtual bool OnlyStaticMethods { get; set; } = false;
public virtual string BurstBackend { get; set; }
// Options
public virtual bool SafetyChecks { get; set; } = false;
public virtual bool DisableVectors { get; set; } = false;
public virtual bool Link { get; set; } = true;
public virtual bool Verbose { get; set; } = false;
public abstract string FloatPrecision { get; set; }
public virtual int Threads { get; set; } = 9;
public virtual bool DisableOpt { get; set; } = false;
public virtual bool EnableGuard { get; set; } = false;
public virtual string ExecuteMethodName { get; set; } = "ProducerExecuteFn_Gen";
public virtual bool EnableStaticLinkage { get; set; } = false;
public virtual bool EnableJobMarshalling { get; set; } = false;
public virtual bool EnableDirectExternalLinking { get; set; } = false;
public virtual string DisableWarnings { get; set; } = ""; // ; seperated list of ids, e.g. BC1370;BC1322
public virtual bool EmitLlvmObjects { get; set; } = false; // Added because burst now compiles/links wasm code as native objects by default
static string[] GetBurstCommandLineArgs(
BurstCompiler compiler,
NPath outputPrefixForObjectFile,
NPath outputDirForPatchedAssemblies,
string pinvokeName,
DotNetAssembly[] inputAssemblies)
{
var commandLineArguments = new[]
{
$"--platform={compiler.TargetPlatform}",
$"--target={compiler.TargetArchitecture}",
$"--format={compiler.ObjectFormat}",
compiler.SafetyChecks ? "--safety-checks" : "",
$"--dump=None",
compiler.DisableVectors ? "--disable-vectors" : "",
compiler.Link ? "" : "--nolink",
$"--float-precision={compiler.FloatPrecision}",
$"--keep-intermediate-files",
compiler.EmitLlvmObjects?"--emit-llvm-objects":"",
compiler.Verbose ? "--verbose" : "",
$"--patch-assemblies-into={outputDirForPatchedAssemblies}",
$"--output={outputPrefixForObjectFile}",
compiler.OnlyStaticMethods ? "--only-static-methods" : "",
"--method-prefix=burstedmethod_",
$"--pinvoke-name={pinvokeName}",
(compiler.BurstBackend == null) ? "" : $"--backend={compiler.BurstBackend}",
$"--execute-method-name={compiler.ExecuteMethodName}",
"--debug=Full",
compiler.EnableDirectExternalLinking ? "--enable-direct-external-linking" : "",
compiler.DisableOpt ? "--disable-opt" : "",
$"--threads={compiler.Threads}",
compiler.EnableGuard ? "--enable-guard" : "",
!String.IsNullOrEmpty(compiler.DisableWarnings) ? $"--disable-warnings={compiler.DisableWarnings}" : ""
}.Concat(inputAssemblies.Select(asm => $"--root-assembly={asm.Path}"));
if (!compiler.UseOwnToolchain)
commandLineArguments = commandLineArguments.Concat(new[] {"--no-native-toolchain"});
if (!HostPlatform.IsWindows)
commandLineArguments = new[] {BurstExecutable.ToString(SlashMode.Native)}.Concat(commandLineArguments);
if (compiler.EnableStaticLinkage)
commandLineArguments = commandLineArguments.Concat(new[] {"--generate-static-linkage-methods"});
if (compiler.EnableJobMarshalling)
commandLineArguments = commandLineArguments.Concat(new[] { "--generate-job-marshalling-methods" });
return commandLineArguments.ToArray();
}
static IEnumerable<NPath> AddDebugSymbolPaths(DotNetAssembly[] assemblies)
{
return assemblies.SelectMany(
asm =>
{
var ret = new List<NPath> {asm.Path};
if (asm.DebugSymbolPath != null)
ret.Add(asm.DebugSymbolPath);
return ret;
});
}
static string[] ArgumentsToResponseFile(bool usesMono, NPath targetDir, string[] commandLineArgs, out NPath responseFile)
{
var remainingArgs = usesMono? commandLineArgs.Skip(1) : commandLineArgs;
var joinedArgs = String.Join(Environment.NewLine, remainingArgs.Where(s => !String.IsNullOrEmpty(s)));
KnuthHash hash = new KnuthHash();
hash.Add(joinedArgs);
responseFile = targetDir.Combine($"{hash.Value}.rsp");
Backend.Current.AddWriteTextAction(
responseFile,
joinedArgs,
"BurstResponseFile");
if (usesMono)
{
return new [] { commandLineArgs[0], $"@{responseFile}"};
}
return new [] {$"@{responseFile}"};
}
public static BagOfObjectFilesLibrary SetupBurstCompilationForAssemblies(
BurstCompiler compiler,
DotNetAssembly unpatchedInputAssembly,
NPath outputDirForObjectFile,
NPath outputDirForPatchedAssemblies,
string pinvokeName,
out DotNetAssembly patchedAssembly)
{
/*
* Note that you can have Link be true and still use this, because on iOS for example if you
* DON'T pass --no-link, it will NOT link, but it WILL correctly override the llvm backend.
*
* if you DO pass --no-link, it will also not link, but then incorrectly use llvm 9.
*/
patchedAssembly = unpatchedInputAssembly.ApplyDotNetAssembliesPostProcessor(
outputDirForPatchedAssemblies,
(inputAssemblies, targetDir) =>
{
var usesMono = HostPlatform.IsWindows ? false : true;
var executableStringFor = !usesMono ? BurstExecutable.ToString(SlashMode.Native) : "mono";
var commandLineArgs = GetBurstCommandLineArgs(
compiler,
outputDirForObjectFile.Combine(pinvokeName),
outputDirForPatchedAssemblies,
pinvokeName,
inputAssemblies);
var inputPaths = AddDebugSymbolPaths(inputAssemblies);
var targetFiles = inputPaths.Select(p => targetDir.Combine(p.FileName));
var finalArguments = ArgumentsToResponseFile(usesMono, targetDir, commandLineArgs, out var responseFile);
Backend.Current.AddAction(
"Burst",
//todo: make burst process pdbs
targetFiles.ToArray(),
inputPaths.Concat(new[] {BurstExecutable, responseFile}).ToArray(),
executableStringFor,
finalArguments,
targetDirectories: new[] {outputDirForObjectFile}
);
});
var needFake = true;
NPath[] objectFileList = null;
if (outputDirForObjectFile.Exists())
{
objectFileList = outputDirForObjectFile.Files($"*{compiler.ObjectFileExtension}");
if (objectFileList.Length > 0)
needFake = false;
}
if (needFake)
objectFileList = new[] {outputDirForObjectFile.Combine($"fake{compiler.ObjectFileExtension}")};
return new BagOfObjectFilesLibrary(objectFileList);
}
public static DynamicLibrary SetupBurstCompilationAndLinkForAssemblies(
BurstCompiler compiler,
DotNetAssembly unpatchedInputAssembly,
NPath targetNativeLibrary,
NPath outputDirForPatchedAssemblies,
out DotNetAssembly patchedAssembly)
{
if (!compiler.Link)
{
throw new ArgumentException("BurstCompiler.Link must be true for SetupBurstCompilationAndLinkForAssemblies");
}
patchedAssembly = unpatchedInputAssembly.ApplyDotNetAssembliesPostProcessor(
outputDirForPatchedAssemblies,
(inputAssemblies, targetDir) =>
{
var usesMono = HostPlatform.IsWindows ? false : true;
var executableStringFor = !usesMono ? BurstExecutable.ToString(SlashMode.Native) : "mono";
var pinvokeName = HostPlatform.IsWindows
? targetNativeLibrary.FileNameWithoutExtension
: targetNativeLibrary.FileName;
var commandLineArgs = GetBurstCommandLineArgs(
compiler,
targetNativeLibrary.ChangeExtension(""),
outputDirForPatchedAssemblies,
pinvokeName,
inputAssemblies);
var inputPaths = AddDebugSymbolPaths(inputAssemblies);
var targetFiles = inputPaths.Select(p => targetDir.Combine(p.FileName))
.Concat(new[] {targetNativeLibrary});
var finalArguments = ArgumentsToResponseFile(usesMono, targetDir, commandLineArgs, out var responseFile);
Backend.Current.AddAction(
"Burst",
//todo: make burst process pdbs
targetFiles.ToArray(),
inputPaths.Concat(new[] {BurstExecutable, responseFile}).ToArray(),
executableStringFor,
finalArguments
);
});
return new DynamicLibrary(targetNativeLibrary, symbolFiles: null);
}
}
public class BurstCompilerForEmscripten : BurstCompiler
{
public override string TargetPlatform { get; set; } = "Wasm";
public override string TargetArchitecture { get; set; } = "WASM32";
public override string ObjectFormat { get; set; } = "Wasm";
public override string FloatPrecision { get; set; } = "High";
public override bool SafetyChecks { get; set; } = true;
public override bool DisableVectors { get; set; } = true;
public override bool Link { get; set; } = false;
public override string ObjectFileExtension { get; set; } = ".bc";
public override bool UseOwnToolchain { get; set; } = false;
public override bool EnableStaticLinkage { get; set; } = true;
public override bool EnableJobMarshalling { get; set; } = false;
public override bool EnableDirectExternalLinking { get; set; } = true;
public override bool EmitLlvmObjects { get; set; } = true; // Added because burst now compiles/links wasm code as native objects by default
}
public class BurstCompilerForWindows : BurstCompiler
{
public override string TargetPlatform { get; set; } = "Windows";
//--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
// SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
// AARCH64|THUMB2_NEON32> Default: Auto
public override string TargetArchitecture { get; set; } = "X64_SSE2";
public override string ObjectFormat { get; set; } = "Coff";
public override string FloatPrecision { get; set; } = "High";
public override bool SafetyChecks { get; set; } = true;
public override bool DisableVectors { get; set; } = false;
public override bool Link { get; set; } = false; //true;
public override string ObjectFileExtension { get; set; } = ".obj";
public override bool UseOwnToolchain { get; set; } = true;
public override bool EnableDirectExternalLinking { get; set; } = false;
//public override string BurstBackend { get; set; } = "burst-llvm-custom";
public override bool EnableJobMarshalling { get; set; } = true;
}
public class BurstCompilerForWindows64 : BurstCompilerForWindows
{
public override string TargetArchitecture { get; set; } = "X64_SSE4";
}
public class BurstCompilerForMac : BurstCompiler
{
public override string TargetPlatform { get; set; } = "macOS";
//--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
// SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
// AARCH64|THUMB2_NEON32> Default: Auto
public override string TargetArchitecture { get; set; } = "X64_SSE2";
public override string ObjectFormat { get; set; } = "MachO";
public override string FloatPrecision { get; set; } = "High";
public override bool SafetyChecks { get; set; } = true;
public override bool DisableVectors { get; set; } = false;
public override bool Link { get; set; } = false;
public override string ObjectFileExtension { get; set; } = ".o";
public override bool UseOwnToolchain { get; set; } = true;
}
public class BurstCompilerForLinux : BurstCompiler
{
public override string TargetPlatform { get; set; } = "Linux";
//--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
// SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
// AARCH64|THUMB2_NEON32> Default: Auto
public override string TargetArchitecture { get; set; } = "X64_SSE2";
public override string ObjectFormat { get; set; } = "Elf";
public override string FloatPrecision { get; set; } = "High";
public override bool SafetyChecks { get; set; } = true;
public override bool DisableVectors { get; set; } = false;
public override bool Link { get; set; } = false;
public override string ObjectFileExtension { get; set; } = ".o";
public override bool UseOwnToolchain { get; set; } = true;
}
public class BurstCompilerForAndroid : BurstCompiler
{
public override string TargetPlatform { get; set; } = "Android";
//--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
// SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
// AARCH64|THUMB2_NEON32> Default: Auto
public override string TargetArchitecture { get; set; } = "ARMV7A_NEON32";
public override string ObjectFormat { get; set; } = "Elf";
public override string FloatPrecision { get; set; } = "High";
public override bool SafetyChecks { get; set; } = true;
public override bool DisableVectors { get; set; } = false;
public override bool Link { get; set; } = false;
public override string ObjectFileExtension { get; set; } = ".o";
public override bool UseOwnToolchain { get; set; } = true;
public override bool EnableDirectExternalLinking { get; set; } = true;
}
public class BurstCompilerForiOS : BurstCompiler
{
public override string TargetPlatform { get; set; } = "iOS";
//--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
// SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
// AARCH64|THUMB2_NEON32> Default: Auto
public override string TargetArchitecture { get; set; } = "ARMV8A_AARCH64";
public override string ObjectFormat { get; set; } = "Elf";
public override bool SafetyChecks { get; set; } = true;
public override bool DisableVectors { get; set; } = false;
public override bool Link { get; set; } = true;
public override string FloatPrecision { get; set; } = "High";
public override string ObjectFileExtension { get; set; } = ".o";
public override bool UseOwnToolchain { get; set; } = true;
public override bool EnableDirectExternalLinking { get; set; } = true;
}