[Lldb-commits] [lldb] f811cb8 - [lldb] Revive lldb-instr

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Thu Jan 20 18:06:20 PST 2022


Author: Jonas Devlieghere
Date: 2022-01-20T18:06:14-08:00
New Revision: f811cb82a6cd811dbb4730009d0f060503aa1c76

URL: https://github.com/llvm/llvm-project/commit/f811cb82a6cd811dbb4730009d0f060503aa1c76
DIFF: https://github.com/llvm/llvm-project/commit/f811cb82a6cd811dbb4730009d0f060503aa1c76.diff

LOG: [lldb] Revive lldb-instr

I revived lldb-instr to update the macros for D117712. I think the new
macros are simple enough that we add them by hand, but this tool can do
it automatically for you.

Differential revision: https://reviews.llvm.org/D117748

Added: 
    lldb/tools/lldb-instr/CMakeLists.txt
    lldb/tools/lldb-instr/Instrument.cpp

Modified: 
    lldb/tools/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/lldb/tools/CMakeLists.txt b/lldb/tools/CMakeLists.txt
index a5f4ca8ec7eb..1585fd4dc4b9 100644
--- a/lldb/tools/CMakeLists.txt
+++ b/lldb/tools/CMakeLists.txt
@@ -7,6 +7,7 @@ add_subdirectory(intel-features)
 # 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")

diff  --git a/lldb/tools/lldb-instr/CMakeLists.txt b/lldb/tools/lldb-instr/CMakeLists.txt
new file mode 100644
index 000000000000..8da453b2894f
--- /dev/null
+++ b/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
+  )

diff  --git a/lldb/tools/lldb-instr/Instrument.cpp b/lldb/tools/lldb-instr/Instrument.cpp
new file mode 100644
index 000000000000..4b8725396a61
--- /dev/null
+++ b/lldb/tools/lldb-instr/Instrument.cpp
@@ -0,0 +1,173 @@
+#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;
+    if (!Decl->isStatic())
+      ParamNames.push_back("this");
+    for (auto *P : Decl->parameters())
+      ParamNames.push_back(P->getNameAsString());
+
+    // Construct the macros.
+    std::string Buffer;
+    llvm::raw_string_ostream Macro(Buffer);
+    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.str());
+      } else {
+        Macro << ";";
+        SourceLocation InsertLoc = Lexer::getLocForEndOfToken(
+            Body->getBeginLoc(), 0, MyRewriter.getSourceMgr(),
+            MyRewriter.getLangOpts());
+        MyRewriter.InsertTextAfter(InsertLoc, Macro.str());
+      }
+      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());
+}


        


More information about the lldb-commits mailing list