Add pluggable action support to clang-cc, via -plugin command line option.

- Expects the plugin has been loaded with -load.

 - Using this may require disabling TOOL_NO_EXPORTS in the clang-cc Makefile, this breaks the llvm::Registry way of working (static constructors are bad, kids). This should be replaced with a "real" plugin model that has explicit plugin interfaces.

llvm-svn: 88824
This commit is contained in:
Daniel Dunbar 2009-11-15 00:12:04 +00:00
parent f5b2869b75
commit d392dd0709
5 changed files with 79 additions and 7 deletions

View File

@ -28,6 +28,8 @@ def err_fe_no_fixit_and_codegen : Error<
"FIX-ITs cannot be applied when generating code">;
def err_fe_unable_to_find_fixit_file : Error<
"FIX-IT could not find file '%0'">;
def err_fe_invalid_plugin_name : Error<
"unable to find plugin '%0'">;
def err_verify_bogus_characters : Error<
"bogus characters before '{{' in expected string">;

View File

@ -39,6 +39,7 @@ namespace frontend {
ParseNoop, ///< Parse with noop callbacks.
ParsePrintCallbacks, ///< Parse and print each callback.
ParseSyntaxOnly, ///< Parse and perform semantic analysis.
PluginAction, ///< Run a plugin action, \see ActionName.
PrintDeclContext, ///< Print DeclContext and their Decls.
PrintPreprocessedInput, ///< -E mode.
RewriteBlocks, ///< ObjC->C Rewriter for Blocks.
@ -109,12 +110,16 @@ public:
/// The frontend action to perform.
frontend::ActionKind ProgramAction;
/// The name of the action to run when using a plugin action.
std::string ActionName;
public:
FrontendOptions() {
DebugCodeCompletionPrinter = 0;
DisableFree = 0;
EmptyInputOnly = 0;
ProgramAction = frontend::ParseSyntaxOnly;
ActionName = "";
RelocatablePCH = 0;
ShowMacrosInCodeCompletion = 0;
ShowStats = 0;

View File

@ -0,0 +1,23 @@
//===-- FrontendAction.h - Pluggable Frontend Action Interface --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H
#define LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H
#include "clang/Frontend/FrontendAction.h"
#include "llvm/Support/Registry.h"
namespace clang {
/// The frontend plugin registry.
typedef llvm::Registry<FrontendAction> FrontendPluginRegistry;
} // end namespace clang
#endif

View File

@ -26,6 +26,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/RegistryParser.h"
#include <stdio.h>
using namespace clang;
@ -383,6 +384,11 @@ OutputFile("o",
llvm::cl::value_desc("path"),
llvm::cl::desc("Specify output file"));
static llvm::cl::opt<std::string>
PluginActionName("plugin",
llvm::cl::desc("Use the named plugin action "
"(use \"help\" to list available options)"));
static llvm::cl::opt<ActionKind>
ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore,
llvm::cl::init(ParseSyntaxOnly),
@ -885,12 +891,18 @@ void clang::InitializeDiagnosticOptions(DiagnosticOptions &Opts) {
void clang::InitializeFrontendOptions(FrontendOptions &Opts) {
using namespace frontendoptions;
// Select program action.
Opts.ProgramAction = ProgAction;
if (PluginActionName.getPosition()) {
Opts.ProgramAction = frontend::PluginAction;
Opts.ActionName = PluginActionName;
}
Opts.CodeCompletionAt = CodeCompletionAt;
Opts.DebugCodeCompletionPrinter = CodeCompletionDebugPrinter;
Opts.DisableFree = DisableFree;
Opts.EmptyInputOnly = EmptyInputOnly;
Opts.FixItLocations = FixItAtLocations;
Opts.ProgramAction = ProgAction;
Opts.OutputFile = OutputFile;
Opts.RelocatablePCH = RelocatablePCH;
Opts.ShowMacrosInCodeCompletion = CodeCompletionWantsMacros;

View File

@ -24,6 +24,7 @@
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/PathDiagnosticClients.h"
#include "clang/Frontend/PreprocessorOptions.h"
#include "clang/Frontend/PreprocessorOutputOptions.h"
@ -36,6 +37,7 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Registry.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
@ -81,11 +83,13 @@ std::string GetBuiltinIncludePath(const char *Argv0) {
/// anything.
llvm::Timer *ClangFrontendTimer = 0;
static FrontendAction *CreateFrontendAction(frontend::ActionKind AK) {
static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
using namespace clang::frontend;
switch (AK) {
default: return 0;
switch (CI.getFrontendOpts().ProgramAction) {
default:
llvm::llvm_unreachable("Invalid program action!");
case ASTDump: return new ASTDumpAction();
case ASTPrint: return new ASTPrintAction();
case ASTPrintXML: return new ASTPrintXMLAction();
@ -105,6 +109,30 @@ static FrontendAction *CreateFrontendAction(frontend::ActionKind AK) {
case ParseNoop: return new ParseOnlyAction();
case ParsePrintCallbacks: return new PrintParseAction();
case ParseSyntaxOnly: return new SyntaxOnlyAction();
case PluginAction: {
if (CI.getFrontendOpts().ActionName == "help") {
llvm::errs() << "clang-cc plugins:\n";
for (FrontendPluginRegistry::iterator it =
FrontendPluginRegistry::begin(),
ie = FrontendPluginRegistry::end();
it != ie; ++it)
llvm::errs() << " " << it->getName() << " - " << it->getDesc() << "\n";
exit(1);
}
for (FrontendPluginRegistry::iterator it =
FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
it != ie; ++it) {
if (it->getName() == CI.getFrontendOpts().ActionName)
return it->instantiate();
}
CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
<< CI.getFrontendOpts().ActionName;
return 0;
}
case PrintDeclContext: return new DeclContextPrintAction();
case PrintPreprocessedInput: return new PrintPreprocessedAction();
case RewriteBlocks: return new RewriteBlocksAction();
@ -279,9 +307,10 @@ int main(int argc, char **argv) {
Clang.createPreprocessor();
}
llvm::OwningPtr<FrontendAction> Act(
CreateFrontendAction(Clang.getFrontendOpts().ProgramAction));
assert(Act && "Invalid program action!");
llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
if (!Act)
break;
Act->setCurrentTimer(ClangFrontendTimer);
if (Act->BeginSourceFile(Clang, InFile, IsAST)) {
Act->Execute();
@ -315,3 +344,4 @@ int main(int argc, char **argv) {
return (Clang.getDiagnostics().getNumErrors() != 0);
}