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 #ifndef LLVM_FLANG_FRONTEND_COMPILERINSTANCE_H 9 #define LLVM_FLANG_FRONTEND_COMPILERINSTANCE_H 10 11 #include "flang/Frontend/CompilerInvocation.h" 12 #include "flang/Frontend/FrontendAction.h" 13 #include "flang/Parser/parsing.h" 14 #include "flang/Parser/provenance.h" 15 #include "llvm/Support/raw_ostream.h" 16 17 namespace Fortran::frontend { 18 19 class CompilerInstance { 20 21 /// The options used in this compiler instance. 22 std::shared_ptr<CompilerInvocation> invocation_; 23 24 /// Flang file manager. 25 std::shared_ptr<Fortran::parser::AllSources> allSources_; 26 27 std::shared_ptr<Fortran::parser::AllCookedSources> allCookedSources_; 28 29 std::shared_ptr<Fortran::parser::Parsing> parsing_; 30 31 /// The diagnostics engine instance. 32 llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_; 33 34 /// Holds information about the output file. 35 struct OutputFile { 36 std::string filename_; OutputFileOutputFile37 OutputFile(std::string inputFilename) 38 : filename_(std::move(inputFilename)) {} 39 }; 40 41 /// Output stream that doesn't support seeking (e.g. terminal, pipe). 42 /// This stream is normally wrapped in buffer_ostream before being passed 43 /// to users (e.g. via CreateOutputFile). 44 std::unique_ptr<llvm::raw_fd_ostream> nonSeekStream_; 45 46 /// The list of active output files. 47 std::list<OutputFile> outputFiles_; 48 49 /// Holds the output stream provided by the user. Normally, users of 50 /// CompilerInstance will call CreateOutputFile to obtain/create an output 51 /// stream. If they want to provide their own output stream, this field will 52 /// facilitate this. It is optional and will normally be just a nullptr. 53 std::unique_ptr<llvm::raw_pwrite_stream> outputStream_; 54 55 public: 56 explicit CompilerInstance(); 57 58 ~CompilerInstance(); 59 60 /// @name Compiler Invocation 61 /// { 62 invocation()63 CompilerInvocation &invocation() { 64 assert(invocation_ && "Compiler instance has no invocation!"); 65 return *invocation_; 66 }; 67 68 /// Replace the current invocation. 69 void set_invocation(std::shared_ptr<CompilerInvocation> value); 70 71 /// } 72 /// @name File manager 73 /// { 74 75 /// Return the current allSources. allSources()76 Fortran::parser::AllSources &allSources() const { return *allSources_; } 77 HasAllSources()78 bool HasAllSources() const { return allSources_ != nullptr; } 79 80 /// } 81 /// @name Parser Operations 82 /// { 83 84 /// Return parsing to be used by Actions. parsing()85 Fortran::parser::Parsing &parsing() const { return *parsing_; } 86 87 /// } 88 /// @name High-Level Operations 89 /// { 90 91 /// Execute the provided action against the compiler's 92 /// CompilerInvocation object. 93 /// \param act - The action to execute. 94 /// \return - True on success. 95 bool ExecuteAction(FrontendAction &act); 96 97 /// } 98 /// @name Forwarding Methods 99 /// { 100 GetDiagnosticOpts()101 clang::DiagnosticOptions &GetDiagnosticOpts() { 102 return invocation_->GetDiagnosticOpts(); 103 } GetDiagnosticOpts()104 const clang::DiagnosticOptions &GetDiagnosticOpts() const { 105 return invocation_->GetDiagnosticOpts(); 106 } 107 frontendOpts()108 FrontendOptions &frontendOpts() { return invocation_->frontendOpts(); } frontendOpts()109 const FrontendOptions &frontendOpts() const { 110 return invocation_->frontendOpts(); 111 } 112 113 /// } 114 /// @name Diagnostics Engine 115 /// { 116 HasDiagnostics()117 bool HasDiagnostics() const { return diagnostics_ != nullptr; } 118 119 /// Get the current diagnostics engine. diagnostics()120 clang::DiagnosticsEngine &diagnostics() const { 121 assert(diagnostics_ && "Compiler instance has no diagnostics!"); 122 return *diagnostics_; 123 } 124 GetDiagnosticClient()125 clang::DiagnosticConsumer &GetDiagnosticClient() const { 126 assert(diagnostics_ && diagnostics_->getClient() && 127 "Compiler instance has no diagnostic client!"); 128 return *diagnostics_->getClient(); 129 } 130 131 /// { 132 /// @name Output Files 133 /// { 134 135 /// Add an output file onto the list of tracked output files. 136 /// 137 /// \param outFile - The output file info. 138 void AddOutputFile(OutputFile &&outFile); 139 140 /// Clear the output file list. 141 void ClearOutputFiles(bool eraseFiles); 142 143 /// Create the default output file (based on the invocation's options) and 144 /// add it to the list of tracked output files. If the name of the output 145 /// file is not provided, it is derived from the input file. 146 /// 147 /// \param binary The mode to open the file in. 148 /// \param baseInput If the invocation contains no output file name (i.e. 149 /// outputFile_ in FrontendOptions is empty), the input path 150 /// name to use for deriving the output path. 151 /// \param extension The extension to use for output names derived from 152 /// \p baseInput. 153 /// \return ostream for the output file or nullptr on error. 154 std::unique_ptr<llvm::raw_pwrite_stream> CreateDefaultOutputFile( 155 bool binary = true, llvm::StringRef baseInput = "", 156 llvm::StringRef extension = ""); 157 158 /// Create a new output file 159 /// 160 /// \param outputPath The path to the output file. 161 /// \param error [out] On failure, the error. 162 /// \param binary The mode to open the file in. 163 /// \return ostream for the output file or nullptr on error. 164 std::unique_ptr<llvm::raw_pwrite_stream> CreateOutputFile( 165 llvm::StringRef outputPath, std::error_code &error, bool binary); 166 167 /// } 168 /// @name Construction Utility Methods 169 /// { 170 171 /// Create a DiagnosticsEngine object 172 /// 173 /// If no diagnostic client is provided, this method creates a 174 /// DiagnosticConsumer that is owned by the returned diagnostic object. If 175 /// using directly the caller is responsible for releasing the returned 176 /// DiagnosticsEngine's client eventually. 177 /// 178 /// \param opts - The diagnostic options; note that the created text 179 /// diagnostic object contains a reference to these options. 180 /// 181 /// \param client - If non-NULL, a diagnostic client that will be attached to 182 /// (and optionally, depending on /p shouldOwnClient, owned by) the returned 183 /// DiagnosticsEngine object. 184 /// 185 /// \return The new object on success, or null on failure. 186 static clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> CreateDiagnostics( 187 clang::DiagnosticOptions *opts, 188 clang::DiagnosticConsumer *client = nullptr, bool shouldOwnClient = true); 189 void CreateDiagnostics( 190 clang::DiagnosticConsumer *client = nullptr, bool shouldOwnClient = true); 191 192 /// } 193 /// @name Output Stream Methods 194 /// { set_outputStream(std::unique_ptr<llvm::raw_pwrite_stream> outStream)195 void set_outputStream(std::unique_ptr<llvm::raw_pwrite_stream> outStream) { 196 outputStream_ = std::move(outStream); 197 } 198 IsOutputStreamNull()199 bool IsOutputStreamNull() { return (outputStream_ == nullptr); } 200 201 // Allow the frontend compiler to write in the output stream. WriteOutputStream(const std::string & message)202 void WriteOutputStream(const std::string &message) { 203 *outputStream_ << message; 204 } 205 }; 206 207 } // end namespace Fortran::frontend 208 #endif // LLVM_FLANG_FRONTEND_COMPILERINSTANCE_H 209