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.
368 lines
16 KiB
368 lines
16 KiB
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; |
|
}
|
|
|