diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -3180,8 +3180,8 @@ .. code-block:: console - $ clang -target spirv32 test.cl - $ clang -target spirv64 test.cl + $ clang -target spirv32 -c test.cl + $ clang -target spirv64 -c test.cl More details can be found in :ref:`the SPIR-V support section `. @@ -3657,8 +3657,8 @@ .. code-block:: console - $ clang -target spirv32 test.cl - $ clang -target spirv64 test.cl + $ clang -target spirv32 -c test.cl + $ clang -target spirv64 -c test.cl Both invocations of Clang will result in the generation of a SPIR-V binary file `test.o` for 32 bit and 64 bit respectively. This file can be imported @@ -3669,6 +3669,18 @@ currently available as an experimental feature and it is not guaranteed to work in all cases. +Clang also supports integrated generation of SPIR-V without use of ``llvm-spirv`` +tool as an experimental feature when ``-fintegrated-objemitter`` flag is passed in +the command line. + + .. code-block:: console + + $ clang -target spirv32 -fintegrated-objemitter -c test.cl + +Note that only very basic functionality is supported at this point and therefore +it is not suitable for arbitrary use cases. This feature is only enabled when clang +build is configured with ``-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=SPIRV`` option. + Linking is done using ``spirv-link`` from `the SPIRV-Tools project `_. Similar to other external linkers, Clang will expect ``spirv-link`` to be installed separately and to be @@ -3676,6 +3688,10 @@ installation instructions `_. + .. code-block:: console + + $ clang -target spirv64 test1.cl test2.cl + .. _clang-cl: clang-cl diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4170,6 +4170,13 @@ Flags<[CoreOption, NoXarchOption]>, Group, HelpText<"Spawn a separate process for each cc1">; +def fintegrated_objemitter : Flag<["-"], "fintegrated-objemitter">, + Flags<[CoreOption, NoXarchOption]>, Group, + HelpText<"Use internal machine object code emitter.">; +def fno_integrated_objemitter : Flag<["-"], "fno-integrated-objemitter">, + Flags<[CoreOption, NoXarchOption]>, Group, + HelpText<"Use external machine object code emitter.">; + def : Flag<["-"], "integrated-as">, Alias, Flags<[NoXarchOption]>; def : Flag<["-"], "no-integrated-as">, Alias, Flags<[CC1Option, FlangOption, NoXarchOption]>; diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -385,11 +385,23 @@ /// by default. virtual bool IsIntegratedAssemblerDefault() const { return false; } + /// IsIntegratedBackendDefault - Does this tool chain enable + /// -fintegrated-objemitter by default. + virtual bool IsIntegratedBackendDefault() const { return true; } + + /// IsIntegratedBackendSupported - Does this tool chain support + /// -fintegrated-objemitter. + virtual bool IsIntegratedBackendSupported() const { return true; } + + /// IsNonIntegratedBackendSupported - Does this tool chain support + /// -fno-integrated-objemitter. + virtual bool IsNonIntegratedBackendSupported() const { return false; } + /// Check if the toolchain should use the integrated assembler. virtual bool useIntegratedAs() const; /// Check if the toolchain should use the integrated backend. - virtual bool useIntegratedBackend() const { return true; } + virtual bool useIntegratedBackend() const; /// Check if the toolchain should use AsmParser to parse inlineAsm when /// integrated assembler is not default. diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -106,6 +106,34 @@ IsIntegratedAssemblerDefault()); } +bool ToolChain::useIntegratedBackend() const { + assert( + ((IsIntegratedBackendDefault() && IsIntegratedBackendSupported()) || + (!IsIntegratedBackendDefault() || IsNonIntegratedBackendSupported())) && + "(Non-)integrated backend set incorrectly!"); + + bool IBackend = Args.hasFlag(options::OPT_fintegrated_objemitter, + options::OPT_fno_integrated_objemitter, + IsIntegratedBackendDefault()); + + // Diagnose when integrated-objemitter options are not supported by this + // toolchain. + unsigned DiagID; + if ((IBackend && !IsIntegratedBackendSupported()) || + (!IBackend && !IsNonIntegratedBackendSupported())) + DiagID = clang::diag::err_drv_unsupported_opt_for_target; + else + DiagID = clang::diag::warn_drv_unsupported_opt_for_target; + Arg *A = Args.getLastArg(options::OPT_fno_integrated_objemitter); + if (A && !IsNonIntegratedBackendSupported()) + D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple(); + A = Args.getLastArg(options::OPT_fintegrated_objemitter); + if (A && !IsIntegratedBackendSupported()) + D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple(); + + return IBackend; +} + bool ToolChain::useRelaxRelocations() const { return ENABLE_X86_RELAX_RELOCATIONS; } diff --git a/clang/lib/Driver/ToolChains/SPIRV.h b/clang/lib/Driver/ToolChains/SPIRV.h --- a/clang/lib/Driver/ToolChains/SPIRV.h +++ b/clang/lib/Driver/ToolChains/SPIRV.h @@ -64,8 +64,9 @@ : ToolChain(D, Triple, Args) {} bool useIntegratedAs() const override { return true; } - bool useIntegratedBackend() const override { return false; } + bool IsIntegratedBackendDefault() const override { return false; } + bool IsNonIntegratedBackendSupported() const override { return true; } bool IsMathErrnoDefault() const override { return false; } bool isCrossCompiling() const override { return true; } bool isPICDefault() const override { return false; } diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c --- a/clang/test/Driver/clang_f_opts.c +++ b/clang/test/Driver/clang_f_opts.c @@ -605,3 +605,8 @@ // CHECK_JMC_WARN_NOT_ELF: -fjmc works only for ELF; option ignored // CHECK_NOJMC-NOT: -fjmc // CHECK_JMC: -fjmc + +// RUN: %clang -### -fintegrated-objemitter -target x86_64 %s 2>&1 | FileCheck -check-prefix=CHECK-INT-OBJEMITTER %s +// CHECK-INT-OBJEMITTER-NOT: unsupported option '-fintegrated-objemitter' for target +// RUN: %clang -### -fno-integrated-objemitter -target x86_64 %s 2>&1 | FileCheck -check-prefix=CHECK-NOINT-OBJEMITTER %s +// CHECK-NOINT-OBJEMITTER: unsupported option '-fno-integrated-objemitter' for target diff --git a/clang/test/Driver/spirv-toolchain.cl b/clang/test/Driver/spirv-toolchain.cl --- a/clang/test/Driver/spirv-toolchain.cl +++ b/clang/test/Driver/spirv-toolchain.cl @@ -69,3 +69,11 @@ // SPLINK-SAME: "-o" [[BC:".*bc"]] // SPLINK: {{llvm-spirv.*"}} [[BC]] "-o" [[SPV2:".*o"]] // SPLINK: {{spirv-link.*"}} [[SPV1]] [[SPV2]] "-o" "a.out" + +//----------------------------------------------------------------------------- +// Check external vs internal object emission. +// RUN: %clang -### --target=spirv64 -fno-integrated-objemitter %s 2>&1 | FileCheck --check-prefix=XTOR %s +// RUN: %clang -### --target=spirv64 -fintegrated-objemitter %s 2>&1 | FileCheck --check-prefix=BACKEND %s + +// XTOR: {{llvm-spirv.*"}} +// BACKEND-NOT: {{llvm-spirv.*"}}