1 //===-- tools/bugpoint/ToolRunner.h -----------------------------*- 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 //
9 // This file exposes an abstraction around a platform C compiler, used to
10 // compile C and assembly code.  It also exposes an "AbstractIntepreter"
11 // interface, which is used to execute code using one of the LLVM execution
12 // engines.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef LLVM_TOOLS_BUGPOINT_TOOLRUNNER_H
17 #define LLVM_TOOLS_BUGPOINT_TOOLRUNNER_H
18 
19 #include "llvm/Support/CommandLine.h"
20 #include "llvm/Support/Error.h"
21 #include "llvm/Support/Path.h"
22 #include "llvm/Support/SystemUtils.h"
23 #include "llvm/TargetParser/Triple.h"
24 #include <exception>
25 #include <vector>
26 
27 namespace llvm {
28 
29 extern cl::opt<bool> SaveTemps;
30 extern Triple TargetTriple;
31 
32 class LLC;
33 
34 //===---------------------------------------------------------------------===//
35 // CC abstraction
36 //
37 class CC {
38   std::string CCPath;              // The path to the cc executable.
39   std::string RemoteClientPath;    // The path to the rsh / ssh executable.
40   std::vector<std::string> ccArgs; // CC-specific arguments.
41   CC(StringRef ccPath, StringRef RemotePath,
42      const std::vector<std::string> *CCArgs)
43       : CCPath(std::string(ccPath)), RemoteClientPath(std::string(RemotePath)) {
44     if (CCArgs)
45       ccArgs = *CCArgs;
46   }
47 
48 public:
49   enum FileType { AsmFile, ObjectFile, CFile };
50 
51   static CC *create(const char *Argv0, std::string &Message,
52                     const std::string &CCBinary,
53                     const std::vector<std::string> *Args);
54 
55   /// ExecuteProgram - Execute the program specified by "ProgramFile" (which is
56   /// either a .s file, or a .c file, specified by FileType), with the specified
57   /// arguments.  Standard input is specified with InputFile, and standard
58   /// Output is captured to the specified OutputFile location.  The SharedLibs
59   /// option specifies optional native shared objects that can be loaded into
60   /// the program for execution.
61   ///
62   Expected<int> ExecuteProgram(
63       const std::string &ProgramFile, const std::vector<std::string> &Args,
64       FileType fileType, const std::string &InputFile,
65       const std::string &OutputFile,
66       const std::vector<std::string> &CCArgs = std::vector<std::string>(),
67       unsigned Timeout = 0, unsigned MemoryLimit = 0);
68 
69   /// MakeSharedObject - This compiles the specified file (which is either a .c
70   /// file or a .s file) into a shared object.
71   ///
72   Error MakeSharedObject(const std::string &InputFile, FileType fileType,
73                          std::string &OutputFile,
74                          const std::vector<std::string> &ArgsForCC);
75 };
76 
77 //===---------------------------------------------------------------------===//
78 /// AbstractInterpreter Class - Subclasses of this class are used to execute
79 /// LLVM bitcode in a variety of ways.  This abstract interface hides this
80 /// complexity behind a simple interface.
81 ///
82 class AbstractInterpreter {
83   virtual void anchor();
84 
85 public:
86   static LLC *createLLC(const char *Argv0, std::string &Message,
87                         const std::string &CCBinary,
88                         const std::vector<std::string> *Args = nullptr,
89                         const std::vector<std::string> *CCArgs = nullptr,
90                         bool UseIntegratedAssembler = false);
91 
92   static AbstractInterpreter *
93   createLLI(const char *Argv0, std::string &Message,
94             const std::vector<std::string> *Args = nullptr);
95 
96   static AbstractInterpreter *
97   createJIT(const char *Argv0, std::string &Message,
98             const std::vector<std::string> *Args = nullptr);
99 
100   static AbstractInterpreter *
101   createCustomCompiler(const char *Argv0, std::string &Message,
102                        const std::string &CompileCommandLine);
103 
104   static AbstractInterpreter *
105   createCustomExecutor(const char *Argv0, std::string &Message,
106                        const std::string &ExecCommandLine);
107 
108   virtual ~AbstractInterpreter() {}
109 
110   /// compileProgram - Compile the specified program from bitcode to executable
111   /// code.  This does not produce any output, it is only used when debugging
112   /// the code generator.  It returns false if the code generator fails.
113   virtual Error compileProgram(const std::string &Bitcode, unsigned Timeout = 0,
114                                unsigned MemoryLimit = 0) {
115     return Error::success();
116   }
117 
118   /// Compile the specified program from bitcode to code understood by the CC
119   /// driver (either C or asm).  Returns an error if the code generator fails,,
120   /// otherwise, the type of code emitted.
121   virtual Expected<CC::FileType> OutputCode(const std::string &Bitcode,
122                                             std::string &OutFile,
123                                             unsigned Timeout = 0,
124                                             unsigned MemoryLimit = 0) {
125     return make_error<StringError>(
126         "OutputCode not supported by this AbstractInterpreter!",
127         inconvertibleErrorCode());
128   }
129 
130   /// ExecuteProgram - Run the specified bitcode file, emitting output to the
131   /// specified filename.  This sets RetVal to the exit code of the program or
132   /// returns an Error if a problem was encountered that prevented execution of
133   /// the program.
134   ///
135   virtual Expected<int> ExecuteProgram(
136       const std::string &Bitcode, const std::vector<std::string> &Args,
137       const std::string &InputFile, const std::string &OutputFile,
138       const std::vector<std::string> &CCArgs = std::vector<std::string>(),
139       const std::vector<std::string> &SharedLibs = std::vector<std::string>(),
140       unsigned Timeout = 0, unsigned MemoryLimit = 0) = 0;
141 };
142 
143 //===---------------------------------------------------------------------===//
144 // LLC Implementation of AbstractIntepreter interface
145 //
146 class LLC : public AbstractInterpreter {
147   std::string LLCPath;               // The path to the LLC executable.
148   std::vector<std::string> ToolArgs; // Extra args to pass to LLC.
149   CC *cc;
150   bool UseIntegratedAssembler;
151 
152 public:
153   LLC(const std::string &llcPath, CC *cc, const std::vector<std::string> *Args,
154       bool useIntegratedAssembler)
155       : LLCPath(llcPath), cc(cc),
156         UseIntegratedAssembler(useIntegratedAssembler) {
157     ToolArgs.clear();
158     if (Args)
159       ToolArgs = *Args;
160   }
161   ~LLC() override { delete cc; }
162 
163   /// compileProgram - Compile the specified program from bitcode to executable
164   /// code.  This does not produce any output, it is only used when debugging
165   /// the code generator.  Returns false if the code generator fails.
166   Error compileProgram(const std::string &Bitcode, unsigned Timeout = 0,
167                        unsigned MemoryLimit = 0) override;
168 
169   Expected<int> ExecuteProgram(
170       const std::string &Bitcode, const std::vector<std::string> &Args,
171       const std::string &InputFile, const std::string &OutputFile,
172       const std::vector<std::string> &CCArgs = std::vector<std::string>(),
173       const std::vector<std::string> &SharedLibs = std::vector<std::string>(),
174       unsigned Timeout = 0, unsigned MemoryLimit = 0) override;
175 
176   Expected<CC::FileType> OutputCode(const std::string &Bitcode,
177                                     std::string &OutFile, unsigned Timeout = 0,
178                                     unsigned MemoryLimit = 0) override;
179 };
180 
181 /// Find the first executable file \ExeName, either in the user's PATH or,
182 /// failing that, in the same directory as argv[0]. This allows us to find
183 /// another LLVM tool if it is built in the same directory. If no executable is
184 /// found, an error is returned.
185 ErrorOr<std::string> FindProgramByName(const std::string &ExeName,
186                                        const char *Argv0, void *MainAddr);
187 
188 } // End llvm namespace
189 
190 #endif
191