Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===-- CompilerInstance.h - Flang Compiler Instance ------------*- 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 | // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef FORTRAN_FRONTEND_COMPILERINSTANCE_H |
14 | #define FORTRAN_FRONTEND_COMPILERINSTANCE_H |
15 | |
16 | #include "flang/Frontend/CompilerInvocation.h" |
17 | #include "flang/Frontend/FrontendAction.h" |
18 | #include "flang/Frontend/PreprocessorOptions.h" |
19 | #include "flang/Parser/parsing.h" |
20 | #include "flang/Parser/provenance.h" |
21 | #include "flang/Semantics/runtime-type-info.h" |
22 | #include "flang/Semantics/semantics.h" |
23 | #include "llvm/Support/raw_ostream.h" |
24 | #include "llvm/Target/TargetMachine.h" |
25 | |
26 | namespace Fortran::frontend { |
27 | |
28 | /// Helper class for managing a single instance of the Flang compiler. |
29 | /// |
30 | /// This class serves two purposes: |
31 | /// (1) It manages the various objects which are necessary to run the compiler |
32 | /// (2) It provides utility routines for constructing and manipulating the |
33 | /// common Flang objects. |
34 | /// |
35 | /// The compiler instance generally owns the instance of all the objects that it |
36 | /// manages. However, clients can still share objects by manually setting the |
37 | /// object and retaking ownership prior to destroying the CompilerInstance. |
38 | /// |
39 | /// The compiler instance is intended to simplify clients, but not to lock them |
40 | /// in to the compiler instance for everything. When possible, utility functions |
41 | /// come in two forms; a short form that reuses the CompilerInstance objects, |
42 | /// and a long form that takes explicit instances of any required objects. |
43 | class CompilerInstance { |
44 | |
45 | /// The options used in this compiler instance. |
46 | std::shared_ptr<CompilerInvocation> invocation; |
47 | |
48 | /// Flang file manager. |
49 | std::shared_ptr<Fortran::parser::AllSources> allSources; |
50 | |
51 | std::shared_ptr<Fortran::parser::AllCookedSources> allCookedSources; |
52 | |
53 | std::shared_ptr<Fortran::parser::Parsing> parsing; |
54 | |
55 | std::unique_ptr<Fortran::semantics::Semantics> semantics; |
56 | |
57 | std::unique_ptr<Fortran::semantics::RuntimeDerivedTypeTables> rtTyTables; |
58 | |
59 | std::unique_ptr<Fortran::semantics::SemanticsContext> semaContext; |
60 | |
61 | std::unique_ptr<llvm::TargetMachine> targetMachine; |
62 | |
63 | /// The stream for diagnostics from Semantics |
64 | llvm::raw_ostream *semaOutputStream = &llvm::errs(); |
65 | |
66 | /// The stream for diagnostics from Semantics if owned, otherwise nullptr. |
67 | std::unique_ptr<llvm::raw_ostream> ownedSemaOutputStream; |
68 | |
69 | /// The diagnostics engine instance. |
70 | llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics; |
71 | |
72 | /// Holds information about the output file. |
73 | struct OutputFile { |
74 | std::string filename; |
75 | OutputFile(std::string inputFilename) |
76 | : filename(std::move(inputFilename)) {} |
77 | }; |
78 | |
79 | /// The list of active output files. |
80 | std::list<OutputFile> outputFiles; |
81 | |
82 | /// Holds the output stream provided by the user. Normally, users of |
83 | /// CompilerInstance will call CreateOutputFile to obtain/create an output |
84 | /// stream. If they want to provide their own output stream, this field will |
85 | /// facilitate this. It is optional and will normally be just a nullptr. |
86 | std::unique_ptr<llvm::raw_pwrite_stream> outputStream; |
87 | |
88 | public: |
89 | explicit CompilerInstance(); |
90 | |
91 | ~CompilerInstance(); |
92 | |
93 | /// @name Compiler Invocation |
94 | /// { |
95 | |
96 | CompilerInvocation &getInvocation() { |
97 | assert(invocation && "Compiler instance has no invocation!"); |
98 | return *invocation; |
99 | }; |
100 | |
101 | /// Replace the current invocation. |
102 | void setInvocation(std::shared_ptr<CompilerInvocation> value); |
103 | |
104 | /// } |
105 | /// @name File manager |
106 | /// { |
107 | |
108 | /// Return the current allSources. |
109 | Fortran::parser::AllSources &getAllSources() const { return *allSources; } |
110 | |
111 | bool hasAllSources() const { return allSources != nullptr; } |
112 | |
113 | parser::AllCookedSources &getAllCookedSources() { |
114 | assert(allCookedSources && "Compiler instance has no AllCookedSources!"); |
115 | return *allCookedSources; |
116 | }; |
117 | |
118 | /// } |
119 | /// @name Parser Operations |
120 | /// { |
121 | |
122 | /// Return parsing to be used by Actions. |
123 | Fortran::parser::Parsing &getParsing() const { return *parsing; } |
124 | |
125 | /// } |
126 | /// @name Semantic analysis |
127 | /// { |
128 | |
129 | Fortran::semantics::SemanticsContext &getSemanticsContext() { |
130 | return *semaContext; |
131 | } |
132 | const Fortran::semantics::SemanticsContext &getSemanticsContext() const { |
133 | return *semaContext; |
134 | } |
135 | |
136 | /// Replace the current stream for verbose output. |
137 | void setSemaOutputStream(llvm::raw_ostream &value); |
138 | |
139 | /// Replace the current stream for verbose output. |
140 | void setSemaOutputStream(std::unique_ptr<llvm::raw_ostream> value); |
141 | |
142 | /// Get the current stream for verbose output. |
143 | llvm::raw_ostream &getSemaOutputStream() { return *semaOutputStream; } |
144 | |
145 | Fortran::semantics::Semantics &getSemantics() { return *semantics; } |
146 | const Fortran::semantics::Semantics &getSemantics() const { |
147 | return *semantics; |
148 | } |
149 | |
150 | void setSemantics(std::unique_ptr<Fortran::semantics::Semantics> sema) { |
151 | semantics = std::move(sema); |
152 | } |
153 | |
154 | void setRtTyTables( |
155 | std::unique_ptr<Fortran::semantics::RuntimeDerivedTypeTables> tables) { |
156 | rtTyTables = std::move(tables); |
157 | } |
158 | |
159 | Fortran::semantics::RuntimeDerivedTypeTables &getRtTyTables() { |
160 | assert(rtTyTables && "Missing runtime derived type tables!"); |
161 | return *rtTyTables; |
162 | } |
163 | |
164 | /// } |
165 | /// @name High-Level Operations |
166 | /// { |
167 | |
168 | /// Execute the provided action against the compiler's |
169 | /// CompilerInvocation object. |
170 | /// \param act - The action to execute. |
171 | /// \return - True on success. |
172 | bool executeAction(FrontendAction &act); |
173 | |
174 | /// } |
175 | /// @name Forwarding Methods |
176 | /// { |
177 | |
178 | clang::DiagnosticOptions &getDiagnosticOpts() { |
179 | return invocation->getDiagnosticOpts(); |
180 | } |
181 | const clang::DiagnosticOptions &getDiagnosticOpts() const { |
182 | return invocation->getDiagnosticOpts(); |
183 | } |
184 | |
185 | FrontendOptions &getFrontendOpts() { return invocation->getFrontendOpts(); } |
186 | const FrontendOptions &getFrontendOpts() const { |
187 | return invocation->getFrontendOpts(); |
188 | } |
189 | |
190 | PreprocessorOptions &preprocessorOpts() { |
191 | return invocation->getPreprocessorOpts(); |
192 | } |
193 | const PreprocessorOptions &preprocessorOpts() const { |
194 | return invocation->getPreprocessorOpts(); |
195 | } |
196 | |
197 | /// } |
198 | /// @name Diagnostics Engine |
199 | /// { |
200 | |
201 | bool hasDiagnostics() const { return diagnostics != nullptr; } |
202 | |
203 | /// Get the current diagnostics engine. |
204 | clang::DiagnosticsEngine &getDiagnostics() const { |
205 | assert(diagnostics && "Compiler instance has no diagnostics!"); |
206 | return *diagnostics; |
207 | } |
208 | |
209 | clang::DiagnosticConsumer &getDiagnosticClient() const { |
210 | assert(diagnostics && diagnostics->getClient() && |
211 | "Compiler instance has no diagnostic client!"); |
212 | return *diagnostics->getClient(); |
213 | } |
214 | |
215 | /// { |
216 | /// @name Output Files |
217 | /// { |
218 | |
219 | /// Clear the output file list. |
220 | void clearOutputFiles(bool eraseFiles); |
221 | |
222 | /// Create the default output file (based on the invocation's options) and |
223 | /// add it to the list of tracked output files. If the name of the output |
224 | /// file is not provided, it will be derived from the input file. |
225 | /// |
226 | /// \param binary The mode to open the file in. |
227 | /// \param baseInput If the invocation contains no output file name (i.e. |
228 | /// outputFile in FrontendOptions is empty), the input path |
229 | /// name to use for deriving the output path. |
230 | /// \param extension The extension to use for output names derived from |
231 | /// \p baseInput. |
232 | /// \return Null on error, ostream for the output file otherwise |
233 | std::unique_ptr<llvm::raw_pwrite_stream> |
234 | createDefaultOutputFile(bool binary = true, llvm::StringRef baseInput = "", |
235 | llvm::StringRef extension = ""); |
236 | |
237 | /// { |
238 | /// @name Target Machine |
239 | /// { |
240 | |
241 | /// Get the target machine. |
242 | const llvm::TargetMachine &getTargetMachine() const { |
243 | assert(targetMachine && "target machine was not set"); |
244 | return *targetMachine; |
245 | } |
246 | llvm::TargetMachine &getTargetMachine() { |
247 | assert(targetMachine && "target machine was not set"); |
248 | return *targetMachine; |
249 | } |
250 | |
251 | /// Sets up LLVM's TargetMachine. |
252 | bool setUpTargetMachine(); |
253 | |
254 | /// Produces the string which represents target feature |
255 | std::string getTargetFeatures(); |
256 | |
257 | private: |
258 | /// Create a new output file |
259 | /// |
260 | /// \param outputPath The path to the output file. |
261 | /// \param binary The mode to open the file in. |
262 | /// \return Null on error, ostream for the output file otherwise |
263 | llvm::Expected<std::unique_ptr<llvm::raw_pwrite_stream>> |
264 | createOutputFileImpl(llvm::StringRef outputPath, bool binary); |
265 | |
266 | public: |
267 | /// } |
268 | /// @name Construction Utility Methods |
269 | /// { |
270 | |
271 | /// Create a DiagnosticsEngine object |
272 | /// |
273 | /// If no diagnostic client is provided, this method creates a |
274 | /// DiagnosticConsumer that is owned by the returned diagnostic object. If |
275 | /// using directly the caller is responsible for releasing the returned |
276 | /// DiagnosticsEngine's client eventually. |
277 | /// |
278 | /// \param opts - The diagnostic options; note that the created text |
279 | /// diagnostic object contains a reference to these options. |
280 | /// |
281 | /// \param client - If non-NULL, a diagnostic client that will be attached to |
282 | /// (and optionally, depending on /p shouldOwnClient, owned by) the returned |
283 | /// DiagnosticsEngine object. |
284 | /// |
285 | /// \return The new object on success, or null on failure. |
286 | static clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> |
287 | createDiagnostics(clang::DiagnosticOptions *opts, |
288 | clang::DiagnosticConsumer *client = nullptr, |
289 | bool shouldOwnClient = true); |
290 | void createDiagnostics(clang::DiagnosticConsumer *client = nullptr, |
291 | bool shouldOwnClient = true); |
292 | |
293 | /// } |
294 | /// @name Output Stream Methods |
295 | /// { |
296 | void setOutputStream(std::unique_ptr<llvm::raw_pwrite_stream> outStream) { |
297 | outputStream = std::move(outStream); |
298 | } |
299 | |
300 | bool isOutputStreamNull() { return (outputStream == nullptr); } |
301 | |
302 | // Allow the frontend compiler to write in the output stream. |
303 | void writeOutputStream(const std::string &message) { |
304 | *outputStream << message; |
305 | } |
306 | |
307 | /// Get the user specified output stream. |
308 | llvm::raw_pwrite_stream &getOutputStream() { |
309 | assert(outputStream && |
310 | "Compiler instance has no user-specified output stream!"); |
311 | return *outputStream; |
312 | } |
313 | }; |
314 | |
315 | } // end namespace Fortran::frontend |
316 | #endif // FORTRAN_FRONTEND_COMPILERINSTANCE_H |
317 |
Warning: This file is not a C or C++ file. It does not have highlighting.