1 //===--- SPIRV.cpp - SPIR-V Tool Implementations ----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "SPIRV.h"
9 #include "CommonArgs.h"
10 #include "clang/Basic/Version.h"
11 #include "clang/Driver/Compilation.h"
12 #include "clang/Driver/Driver.h"
13 #include "clang/Driver/InputInfo.h"
14 #include "clang/Driver/Options.h"
15
16 using namespace clang::driver;
17 using namespace clang::driver::toolchains;
18 using namespace clang::driver::tools;
19 using namespace llvm::opt;
20
constructTranslateCommand(Compilation & C,const Tool & T,const JobAction & JA,const InputInfo & Output,const InputInfo & Input,const llvm::opt::ArgStringList & Args)21 void SPIRV::constructTranslateCommand(Compilation &C, const Tool &T,
22 const JobAction &JA,
23 const InputInfo &Output,
24 const InputInfo &Input,
25 const llvm::opt::ArgStringList &Args) {
26 llvm::opt::ArgStringList CmdArgs(Args);
27 CmdArgs.push_back(Input.getFilename());
28
29 if (Input.getType() == types::TY_PP_Asm)
30 CmdArgs.push_back("-to-binary");
31 if (Output.getType() == types::TY_PP_Asm)
32 CmdArgs.push_back("--spirv-tools-dis");
33
34 CmdArgs.append({"-o", Output.getFilename()});
35
36 // Try to find "llvm-spirv-<LLVM_VERSION_MAJOR>". Otherwise, fall back to
37 // plain "llvm-spirv".
38 using namespace std::string_literals;
39 auto VersionedTool = "llvm-spirv-"s + std::to_string(LLVM_VERSION_MAJOR);
40 std::string ExeCand = T.getToolChain().GetProgramPath(VersionedTool.c_str());
41 if (!llvm::sys::fs::can_execute(ExeCand))
42 ExeCand = T.getToolChain().GetProgramPath("llvm-spirv");
43
44 const char *Exec = C.getArgs().MakeArgString(ExeCand);
45 C.addCommand(std::make_unique<Command>(JA, T, ResponseFileSupport::None(),
46 Exec, CmdArgs, Input, Output));
47 }
48
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const49 void SPIRV::Translator::ConstructJob(Compilation &C, const JobAction &JA,
50 const InputInfo &Output,
51 const InputInfoList &Inputs,
52 const ArgList &Args,
53 const char *LinkingOutput) const {
54 claimNoWarnArgs(Args);
55 if (Inputs.size() != 1)
56 llvm_unreachable("Invalid number of input files.");
57 constructTranslateCommand(C, *this, JA, Output, Inputs[0], {});
58 }
59
getTranslator() const60 clang::driver::Tool *SPIRVToolChain::getTranslator() const {
61 if (!Translator)
62 Translator = std::make_unique<SPIRV::Translator>(*this);
63 return Translator.get();
64 }
65
SelectTool(const JobAction & JA) const66 clang::driver::Tool *SPIRVToolChain::SelectTool(const JobAction &JA) const {
67 Action::ActionClass AC = JA.getKind();
68 return SPIRVToolChain::getTool(AC);
69 }
70
getTool(Action::ActionClass AC) const71 clang::driver::Tool *SPIRVToolChain::getTool(Action::ActionClass AC) const {
72 switch (AC) {
73 default:
74 break;
75 case Action::BackendJobClass:
76 case Action::AssembleJobClass:
77 return SPIRVToolChain::getTranslator();
78 }
79 return ToolChain::getTool(AC);
80 }
buildLinker() const81 clang::driver::Tool *SPIRVToolChain::buildLinker() const {
82 return new tools::SPIRV::Linker(*this);
83 }
84
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const85 void SPIRV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
86 const InputInfo &Output,
87 const InputInfoList &Inputs,
88 const ArgList &Args,
89 const char *LinkingOutput) const {
90 const ToolChain &ToolChain = getToolChain();
91 std::string Linker = ToolChain.GetProgramPath(getShortName());
92 ArgStringList CmdArgs;
93 AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
94
95 CmdArgs.push_back("-o");
96 CmdArgs.push_back(Output.getFilename());
97
98 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
99 Args.MakeArgString(Linker), CmdArgs,
100 Inputs, Output));
101 }
102