brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.4 KiB · 7586be5 Raw
227 lines · cpp
1//===--- ExecuteCompilerInvocation.cpp ------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file holds ExecuteCompilerInvocation(). It is split into its own file to10// minimize the impact of pulling in essentially everything else in Flang.11//12//===----------------------------------------------------------------------===//13//14// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/15//16//===----------------------------------------------------------------------===//17 18#include "flang/Frontend/CompilerInstance.h"19#include "flang/Frontend/FrontendActions.h"20#include "flang/Frontend/FrontendPluginRegistry.h"21 22#include "mlir/IR/AsmState.h"23#include "mlir/IR/MLIRContext.h"24#include "mlir/Pass/PassManager.h"25#include "clang/Basic/DiagnosticFrontend.h"26#include "clang/Options/Options.h"27#include "llvm/Option/OptTable.h"28#include "llvm/Option/Option.h"29#include "llvm/Support/BuryPointer.h"30#include "llvm/Support/CommandLine.h"31 32namespace Fortran::frontend {33 34static std::unique_ptr<FrontendAction>35createFrontendAction(CompilerInstance &ci) {36 37  switch (ci.getFrontendOpts().programAction) {38  case InputOutputTest:39    return std::make_unique<InputOutputTestAction>();40  case PrintPreprocessedInput:41    return std::make_unique<PrintPreprocessedAction>();42  case ParseSyntaxOnly:43    return std::make_unique<ParseSyntaxOnlyAction>();44  case EmitFIR:45    return std::make_unique<EmitFIRAction>();46  case EmitHLFIR:47    return std::make_unique<EmitHLFIRAction>();48  case EmitLLVM:49    return std::make_unique<EmitLLVMAction>();50  case EmitLLVMBitcode:51    return std::make_unique<EmitLLVMBitcodeAction>();52  case EmitObj:53    return std::make_unique<EmitObjAction>();54  case EmitAssembly:55    return std::make_unique<EmitAssemblyAction>();56  case DebugUnparse:57    return std::make_unique<DebugUnparseAction>();58  case DebugUnparseNoSema:59    return std::make_unique<DebugUnparseNoSemaAction>();60  case DebugUnparseWithSymbols:61    return std::make_unique<DebugUnparseWithSymbolsAction>();62  case DebugUnparseWithModules:63    return std::make_unique<DebugUnparseWithModulesAction>();64  case DebugDumpSymbols:65    return std::make_unique<DebugDumpSymbolsAction>();66  case DebugDumpParseTree:67    return std::make_unique<DebugDumpParseTreeAction>();68  case DebugDumpPFT:69    return std::make_unique<DebugDumpPFTAction>();70  case DebugDumpParseTreeNoSema:71    return std::make_unique<DebugDumpParseTreeNoSemaAction>();72  case DebugDumpAll:73    return std::make_unique<DebugDumpAllAction>();74  case DebugDumpProvenance:75    return std::make_unique<DebugDumpProvenanceAction>();76  case DebugDumpParsingLog:77    return std::make_unique<DebugDumpParsingLogAction>();78  case DebugMeasureParseTree:79    return std::make_unique<DebugMeasureParseTreeAction>();80  case DebugPreFIRTree:81    return std::make_unique<DebugPreFIRTreeAction>();82  case GetDefinition:83    return std::make_unique<GetDefinitionAction>();84  case GetSymbolsSources:85    return std::make_unique<GetSymbolsSourcesAction>();86  case InitOnly:87    return std::make_unique<InitOnlyAction>();88  case PluginAction: {89    for (const FrontendPluginRegistry::entry &plugin :90         FrontendPluginRegistry::entries()) {91      if (plugin.getName() == ci.getFrontendOpts().actionName) {92        std::unique_ptr<PluginParseTreeAction> p(plugin.instantiate());93        return std::move(p);94      }95    }96    unsigned diagID = ci.getDiagnostics().getCustomDiagID(97        clang::DiagnosticsEngine::Error, "unable to find plugin '%0'");98    ci.getDiagnostics().Report(diagID) << ci.getFrontendOpts().actionName;99    return nullptr;100  }101  }102 103  llvm_unreachable("Invalid program action!");104}105 106static void emitUnknownDiagWarning(clang::DiagnosticsEngine &diags,107                                   clang::diag::Flavor flavor,108                                   llvm::StringRef prefix,109                                   llvm::StringRef opt) {110  llvm::StringRef suggestion =111      clang::DiagnosticIDs::getNearestOption(flavor, opt);112  diags.Report(clang::diag::warn_unknown_diag_option)113      << (flavor == clang::diag::Flavor::WarningOrError ? 0 : 1)114      << (prefix.str() += std::string(opt)) << !suggestion.empty()115      << (prefix.str() += std::string(suggestion));116}117 118// Remarks are ignored by default in Diagnostic.td, hence, we have to119// enable them here before execution. Clang follows same idea using120// ProcessWarningOptions in Warnings.cpp121// This function is also responsible for emitting early warnings for122// invalid -R options.123static void124updateDiagEngineForOptRemarks(clang::DiagnosticsEngine &diagsEng,125                              const clang::DiagnosticOptions &opts) {126  llvm::SmallVector<clang::diag::kind, 10> diags;127  const llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs =128      diagsEng.getDiagnosticIDs();129 130  for (unsigned i = 0; i < opts.Remarks.size(); i++) {131    llvm::StringRef remarkOpt = opts.Remarks[i];132    const auto flavor = clang::diag::Flavor::Remark;133 134    // Check to see if this opt starts with "no-", if so, this is a135    // negative form of the option.136    bool isPositive = !remarkOpt.starts_with("no-");137    if (!isPositive)138      remarkOpt = remarkOpt.substr(3);139 140    // Verify that this is a valid optimization remarks option141    if (diagIDs->getDiagnosticsInGroup(flavor, remarkOpt, diags)) {142      emitUnknownDiagWarning(diagsEng, flavor, isPositive ? "-R" : "-Rno-",143                             remarkOpt);144      return;145    }146 147    diagsEng.setSeverityForGroup(flavor, remarkOpt,148                                 isPositive ? clang::diag::Severity::Remark149                                            : clang::diag::Severity::Ignored);150  }151}152 153bool executeCompilerInvocation(CompilerInstance *flang) {154  // Honor -help.155  if (flang->getFrontendOpts().showHelp) {156    clang::getDriverOptTable().printHelp(157        llvm::outs(), "flang -fc1 [options] file...", "LLVM 'Flang' Compiler",158        /*ShowHidden=*/false, /*ShowAllAliases=*/false,159        llvm::opt::Visibility(clang::options::FC1Option));160    return true;161  }162 163  // Honor -version.164  if (flang->getFrontendOpts().showVersion) {165    llvm::cl::PrintVersionMessage();166    return true;167  }168 169  // Load any requested plugins.170  for (const std::string &path : flang->getFrontendOpts().plugins) {171    std::string error;172    if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(path.c_str(),173                                                          &error)) {174      unsigned diagID = flang->getDiagnostics().getCustomDiagID(175          clang::DiagnosticsEngine::Error, "unable to load plugin '%0': '%1'");176      flang->getDiagnostics().Report(diagID) << path << error;177    }178  }179 180  // Honor -mllvm. This should happen AFTER plugins have been loaded!181  if (!flang->getFrontendOpts().llvmArgs.empty()) {182    unsigned numArgs = flang->getFrontendOpts().llvmArgs.size();183    auto args = std::make_unique<const char *[]>(numArgs + 2);184    args[0] = "flang (LLVM option parsing)";185 186    for (unsigned i = 0; i != numArgs; ++i)187      args[i + 1] = flang->getFrontendOpts().llvmArgs[i].c_str();188 189    args[numArgs + 1] = nullptr;190    llvm::cl::ParseCommandLineOptions(numArgs + 1, args.get());191  }192 193  // Honor -mmlir. This should happen AFTER plugins have been loaded!194  if (!flang->getFrontendOpts().mlirArgs.empty()) {195    mlir::registerMLIRContextCLOptions();196    mlir::registerPassManagerCLOptions();197    mlir::registerAsmPrinterCLOptions();198    unsigned numArgs = flang->getFrontendOpts().mlirArgs.size();199    auto args = std::make_unique<const char *[]>(numArgs + 2);200    args[0] = "flang (MLIR option parsing)";201 202    for (unsigned i = 0; i != numArgs; ++i)203      args[i + 1] = flang->getFrontendOpts().mlirArgs[i].c_str();204 205    args[numArgs + 1] = nullptr;206    llvm::cl::ParseCommandLineOptions(numArgs + 1, args.get());207  }208 209  // If there were errors in processing arguments, don't do anything else.210  if (flang->getDiagnostics().hasErrorOccurred()) {211    return false;212  }213 214  updateDiagEngineForOptRemarks(flang->getDiagnostics(),215                                flang->getDiagnosticOpts());216 217  // Create and execute the frontend action.218  std::unique_ptr<FrontendAction> act(createFrontendAction(*flang));219  if (!act)220    return false;221 222  bool success = flang->executeAction(*act);223  return success;224}225 226} // namespace Fortran::frontend227