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
26namespace 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.
43class 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
88public:
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
257private:
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
266public:
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.

source code of flang/include/flang/Frontend/CompilerInstance.h