JDevlieghere created this revision.
JDevlieghere added a reviewer: labath.
Herald added a subscriber: mgorny.
JDevlieghere requested review of this revision.
I revived `lldb-instr` to update the macros for D117712
<https://reviews.llvm.org/D117712>. I think the new macros are simple enough
that we add them by hand, but this tool can do it automatically for you.
https://reviews.llvm.org/D117748
Files:
lldb/tools/CMakeLists.txt
lldb/tools/lldb-instr/CMakeLists.txt
lldb/tools/lldb-instr/Instrument.cpp
Index: lldb/tools/lldb-instr/Instrument.cpp
===================================================================
--- /dev/null
+++ lldb/tools/lldb-instr/Instrument.cpp
@@ -0,0 +1,169 @@
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Tooling.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <sstream>
+#include <string>
+
+using namespace clang;
+using namespace clang::driver;
+using namespace clang::tooling;
+
+static llvm::cl::OptionCategory InstrCategory("LLDB Instrumentation Generator");
+
+class SBVisitor : public RecursiveASTVisitor<SBVisitor> {
+public:
+ SBVisitor(Rewriter &R, ASTContext &Context)
+ : MyRewriter(R), Context(Context) {}
+
+ bool VisitCXXMethodDecl(CXXMethodDecl *Decl) {
+ // Not all decls should be registered. Please refer to that method's
+ // comment for details.
+ if (ShouldSkip(Decl))
+ return false;
+
+ // Print 'bool' instead of '_Bool'.
+ PrintingPolicy Policy(Context.getLangOpts());
+ Policy.Bool = true;
+
+ // Collect the functions parameter types and names.
+ std::vector<std::string> ParamNames;
+ for (auto *P : Decl->parameters())
+ ParamNames.push_back(P->getNameAsString());
+
+ // Construct the macros.
+ std::string Macro;
+ if (ParamNames.empty()) {
+ Macro = "LLDB_INSTRUMENT()";
+ } else {
+ Macro = "LLDB_INSTRUMENT_VA(" + llvm::join(ParamNames, ", ") + ")";
+ }
+
+ Stmt *Body = Decl->getBody();
+ for (auto &C : Body->children()) {
+ if (C->getBeginLoc().isMacroID()) {
+ CharSourceRange Range =
+ MyRewriter.getSourceMgr().getExpansionRange(C->getSourceRange());
+ MyRewriter.ReplaceText(Range, Macro);
+ } else {
+ SourceLocation InsertLoc = Lexer::getLocForEndOfToken(
+ Body->getBeginLoc(), 0, MyRewriter.getSourceMgr(),
+ MyRewriter.getLangOpts());
+ MyRewriter.InsertTextAfter(InsertLoc, Macro);
+ }
+ break;
+ }
+
+ return true;
+ }
+
+private:
+ /// Determine whether we need to consider the given CXXMethodDecl.
+ ///
+ /// Currently we skip the following cases:
+ /// 1. Decls outside the main source file,
+ /// 2. Decls that are only present in the source file,
+ /// 3. Decls that are not definitions,
+ /// 4. Non-public methods,
+ /// 5. Variadic methods.
+ /// 6. Destructors.
+ bool ShouldSkip(CXXMethodDecl *Decl) {
+ // Skip anything outside the main file.
+ if (!MyRewriter.getSourceMgr().isInMainFile(Decl->getBeginLoc()))
+ return true;
+
+ // Skip if the canonical decl in the current decl. It means that the method
+ // is declared in the implementation and is therefore not exposed as part
+ // of the API.
+ if (Decl == Decl->getCanonicalDecl())
+ return true;
+
+ // Skip decls that have no body, i.e. are just declarations.
+ Stmt *Body = Decl->getBody();
+ if (!Body)
+ return true;
+
+ // Skip non-public methods.
+ AccessSpecifier AS = Decl->getAccess();
+ if (AS != AccessSpecifier::AS_public)
+ return true;
+
+ // Skip variadic methods.
+ if (Decl->isVariadic())
+ return true;
+
+ // Skip destructors.
+ if (isa<CXXDestructorDecl>(Decl))
+ return true;
+
+ return false;
+ }
+
+ Rewriter &MyRewriter;
+ ASTContext &Context;
+};
+
+class SBConsumer : public ASTConsumer {
+public:
+ SBConsumer(Rewriter &R, ASTContext &Context) : Visitor(R, Context) {}
+
+ // Override the method that gets called for each parsed top-level
+ // declaration.
+ bool HandleTopLevelDecl(DeclGroupRef DR) override {
+ for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
+ Visitor.TraverseDecl(*b);
+ }
+ return true;
+ }
+
+private:
+ SBVisitor Visitor;
+};
+
+class SBAction : public ASTFrontendAction {
+public:
+ SBAction() = default;
+
+ bool BeginSourceFileAction(CompilerInstance &CI) override { return true; }
+
+ void EndSourceFileAction() override { MyRewriter.overwriteChangedFiles(); }
+
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef File) override {
+ MyRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
+ return std::make_unique<SBConsumer>(MyRewriter, CI.getASTContext());
+ }
+
+private:
+ Rewriter MyRewriter;
+};
+
+int main(int argc, const char **argv) {
+ auto ExpectedParser = CommonOptionsParser::create(
+ argc, argv, InstrCategory, llvm::cl::OneOrMore,
+ "Utility for generating the macros for LLDB's "
+ "instrumentation framework.");
+ if (!ExpectedParser) {
+ llvm::errs() << ExpectedParser.takeError();
+ return 1;
+ }
+ CommonOptionsParser &OP = ExpectedParser.get();
+
+ auto PCHOpts = std::make_shared<PCHContainerOperations>();
+ PCHOpts->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
+ PCHOpts->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
+
+ ClangTool T(OP.getCompilations(), OP.getSourcePathList(), PCHOpts);
+ return T.run(newFrontendActionFactory<SBAction>().get());
+}
Index: lldb/tools/lldb-instr/CMakeLists.txt
===================================================================
--- /dev/null
+++ lldb/tools/lldb-instr/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_lldb_tool(lldb-instr
+ Instrument.cpp
+
+ CLANG_LIBS
+ clangAST
+ clangBasic
+ clangCodeGen
+ clangFrontend
+ clangLex
+ clangRewrite
+ clangSerialization
+ clangTooling
+
+ LINK_COMPONENTS
+ Support
+ )
Index: lldb/tools/CMakeLists.txt
===================================================================
--- lldb/tools/CMakeLists.txt
+++ lldb/tools/CMakeLists.txt
@@ -7,6 +7,7 @@
# example is `check-lldb`. So, we pass EXCLUDE_FROM_ALL here.
add_subdirectory(lldb-test EXCLUDE_FROM_ALL)
+add_lldb_tool_subdirectory(lldb-instr)
add_lldb_tool_subdirectory(lldb-vscode)
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits