1 #include "clang/AST/AST.h" 2 #include "clang/AST/ASTConsumer.h" 3 #include "clang/AST/RecursiveASTVisitor.h" 4 #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" 5 #include "clang/Frontend/ASTConsumers.h" 6 #include "clang/Frontend/CompilerInstance.h" 7 #include "clang/Frontend/FrontendActions.h" 8 #include "clang/Rewrite/Core/Rewriter.h" 9 #include "clang/Tooling/CommonOptionsParser.h" 10 #include "clang/Tooling/Tooling.h" 11 12 #include "llvm/ADT/StringExtras.h" 13 #include "llvm/ADT/StringRef.h" 14 #include "llvm/Support/raw_ostream.h" 15 16 #include <sstream> 17 #include <string> 18 19 using namespace clang; 20 using namespace clang::driver; 21 using namespace clang::tooling; 22 23 static llvm::cl::OptionCategory InstrCategory("LLDB Instrumentation Generator"); 24 25 /// Get the macro name for recording method calls. 26 /// 27 /// LLDB_RECORD_METHOD 28 /// LLDB_RECORD_METHOD_CONST 29 /// LLDB_RECORD_METHOD_NO_ARGS 30 /// LLDB_RECORD_METHOD_CONST_NO_ARGS 31 /// LLDB_RECORD_STATIC_METHOD 32 /// LLDB_RECORD_STATIC_METHOD_NO_ARGS 33 static std::string GetRecordMethodMacroName(bool Static, bool Const, 34 bool NoArgs) { 35 std::string Macro; 36 llvm::raw_string_ostream OS(Macro); 37 38 OS << "LLDB_RECORD"; 39 if (Static) 40 OS << "_STATIC"; 41 OS << "_METHOD"; 42 if (Const) 43 OS << "_CONST"; 44 if (NoArgs) 45 OS << "_NO_ARGS"; 46 47 return OS.str(); 48 } 49 50 /// Get the macro name for register methods. 51 /// 52 /// LLDB_REGISTER_CONSTRUCTOR 53 /// LLDB_REGISTER_METHOD 54 /// LLDB_REGISTER_METHOD_CONST 55 /// LLDB_REGISTER_STATIC_METHOD 56 static std::string GetRegisterMethodMacroName(bool Static, bool Const) { 57 std::string Macro; 58 llvm::raw_string_ostream OS(Macro); 59 60 OS << "LLDB_REGISTER"; 61 if (Static) 62 OS << "_STATIC"; 63 OS << "_METHOD"; 64 if (Const) 65 OS << "_CONST"; 66 67 return OS.str(); 68 } 69 70 static std::string GetRecordMethodMacro(StringRef Result, StringRef Class, 71 StringRef Method, StringRef Signature, 72 StringRef Values, bool Static, 73 bool Const) { 74 std::string Macro; 75 llvm::raw_string_ostream OS(Macro); 76 77 OS << GetRecordMethodMacroName(Static, Const, Values.empty()); 78 OS << "(" << Result << ", " << Class << ", " << Method; 79 80 if (!Values.empty()) { 81 OS << ", (" << Signature << "), " << Values << ");\n\n"; 82 } else { 83 OS << ");\n\n"; 84 } 85 86 return OS.str(); 87 } 88 89 static std::string GetRecordConstructorMacro(StringRef Class, 90 StringRef Signature, 91 StringRef Values) { 92 std::string Macro; 93 llvm::raw_string_ostream OS(Macro); 94 if (!Values.empty()) { 95 OS << "LLDB_RECORD_CONSTRUCTOR(" << Class << ", (" << Signature << "), " 96 << Values << ");\n\n"; 97 } else { 98 OS << "LLDB_RECORD_CONSTRUCTOR_NO_ARGS(" << Class << ");\n\n"; 99 } 100 return OS.str(); 101 } 102 103 static std::string GetRecordDummyMacro(StringRef Result, StringRef Class, 104 StringRef Method, StringRef Signature, 105 StringRef Values) { 106 assert(!Values.empty()); 107 std::string Macro; 108 llvm::raw_string_ostream OS(Macro); 109 110 OS << "LLDB_RECORD_DUMMY(" << Result << ", " << Class << ", " << Method; 111 OS << ", (" << Signature << "), " << Values << ");\n\n"; 112 113 return OS.str(); 114 } 115 116 static std::string GetRegisterConstructorMacro(StringRef Class, 117 StringRef Signature) { 118 std::string Macro; 119 llvm::raw_string_ostream OS(Macro); 120 OS << "LLDB_REGISTER_CONSTRUCTOR(" << Class << ", (" << Signature << "));\n"; 121 return OS.str(); 122 } 123 124 static std::string GetRegisterMethodMacro(StringRef Result, StringRef Class, 125 StringRef Method, StringRef Signature, 126 bool Static, bool Const) { 127 std::string Macro; 128 llvm::raw_string_ostream OS(Macro); 129 OS << GetRegisterMethodMacroName(Static, Const); 130 OS << "(" << Result << ", " << Class << ", " << Method << ", (" << Signature 131 << "));\n"; 132 return OS.str(); 133 } 134 135 class SBReturnVisitor : public RecursiveASTVisitor<SBReturnVisitor> { 136 public: 137 SBReturnVisitor(Rewriter &R) : MyRewriter(R) {} 138 139 bool VisitReturnStmt(ReturnStmt *Stmt) { 140 Expr *E = Stmt->getRetValue(); 141 142 if (E->getBeginLoc().isMacroID()) 143 return false; 144 145 SourceRange R(E->getBeginLoc(), E->getEndLoc()); 146 147 StringRef WrittenExpr = Lexer::getSourceText( 148 CharSourceRange::getTokenRange(R), MyRewriter.getSourceMgr(), 149 MyRewriter.getLangOpts()); 150 151 std::string ReplacementText = 152 "LLDB_RECORD_RESULT(" + WrittenExpr.str() + ")"; 153 MyRewriter.ReplaceText(R, ReplacementText); 154 155 return true; 156 } 157 158 private: 159 Rewriter &MyRewriter; 160 }; 161 162 class SBVisitor : public RecursiveASTVisitor<SBVisitor> { 163 public: 164 SBVisitor(Rewriter &R, ASTContext &Context) 165 : MyRewriter(R), Context(Context) {} 166 167 bool VisitCXXMethodDecl(CXXMethodDecl *Decl) { 168 // Not all decls should be registered. Please refer to that method's 169 // comment for details. 170 if (ShouldSkip(Decl)) 171 return false; 172 173 // Skip CXXMethodDecls that already starts with a macro. This should make 174 // it easier to rerun the tool to find missing macros. 175 Stmt *Body = Decl->getBody(); 176 for (auto &C : Body->children()) { 177 if (C->getBeginLoc().isMacroID()) 178 return false; 179 break; 180 } 181 182 // Print 'bool' instead of '_Bool'. 183 PrintingPolicy Policy(Context.getLangOpts()); 184 Policy.Bool = true; 185 186 // Unsupported signatures get a dummy macro. 187 bool ShouldInsertDummy = false; 188 189 // Collect the functions parameter types and names. 190 std::vector<std::string> ParamTypes; 191 std::vector<std::string> ParamNames; 192 for (auto *P : Decl->parameters()) { 193 QualType T = P->getType(); 194 ParamTypes.push_back(T.getAsString(Policy)); 195 ParamNames.push_back(P->getNameAsString()); 196 197 // Currently we don't support functions that have function pointers as an 198 // argument, in which case we insert a dummy macro. 199 ShouldInsertDummy |= T->isFunctionPointerType(); 200 } 201 202 // Convert the two lists to string for the macros. 203 std::string ParamTypesStr = llvm::join(ParamTypes, ", "); 204 std::string ParamNamesStr = llvm::join(ParamNames, ", "); 205 206 CXXRecordDecl *Record = Decl->getParent(); 207 QualType ReturnType = Decl->getReturnType(); 208 209 // Construct the macros. 210 std::string Macro; 211 if (ShouldInsertDummy) { 212 // Don't insert a register call for dummy macros. 213 Macro = GetRecordDummyMacro( 214 ReturnType.getAsString(Policy), Record->getNameAsString(), 215 Decl->getNameAsString(), ParamTypesStr, ParamNamesStr); 216 217 } else if (isa<CXXConstructorDecl>(Decl)) { 218 llvm::outs() << GetRegisterConstructorMacro(Record->getNameAsString(), 219 ParamTypesStr); 220 221 Macro = GetRecordConstructorMacro(Record->getNameAsString(), 222 ParamTypesStr, ParamNamesStr); 223 } else { 224 llvm::outs() << GetRegisterMethodMacro( 225 ReturnType.getAsString(Policy), Record->getNameAsString(), 226 Decl->getNameAsString(), ParamTypesStr, Decl->isStatic(), 227 Decl->isConst()); 228 229 Macro = GetRecordMethodMacro( 230 ReturnType.getAsString(Policy), Record->getNameAsString(), 231 Decl->getNameAsString(), ParamTypesStr, ParamNamesStr, 232 Decl->isStatic(), Decl->isConst()); 233 } 234 235 // Insert the macro at the beginning of the function. We don't attempt to 236 // fix the formatting and instead rely on clang-format to fix it after the 237 // tool has run. This is also the reason that the macros end with two 238 // newlines, counting on clang-format to normalize this in case the macro 239 // got inserted before an existing newline. 240 SourceLocation InsertLoc = Lexer::getLocForEndOfToken( 241 Body->getBeginLoc(), 0, MyRewriter.getSourceMgr(), 242 MyRewriter.getLangOpts()); 243 MyRewriter.InsertTextAfter(InsertLoc, Macro); 244 245 // If the function returns a class or struct, we need to wrap its return 246 // statement(s). 247 bool ShouldRecordResult = ReturnType->isStructureOrClassType() || 248 ReturnType->getPointeeCXXRecordDecl(); 249 if (!ShouldInsertDummy && ShouldRecordResult) { 250 SBReturnVisitor Visitor(MyRewriter); 251 Visitor.TraverseDecl(Decl); 252 } 253 254 return true; 255 } 256 257 private: 258 /// Determine whether we need to consider the given CXXMethodDecl. 259 /// 260 /// Currently we skip the following cases: 261 /// 1. Decls outside the main source file, 262 /// 2. Decls that are only present in the source file, 263 /// 3. Decls that are not definitions, 264 /// 4. Non-public methods, 265 /// 5. Variadic methods. 266 /// 6. Destructors. 267 bool ShouldSkip(CXXMethodDecl *Decl) { 268 // Skip anything outside the main file. 269 if (!MyRewriter.getSourceMgr().isInMainFile(Decl->getBeginLoc())) 270 return true; 271 272 // Skip if the canonical decl in the current decl. It means that the method 273 // is declared in the implementation and is therefore not exposed as part 274 // of the API. 275 if (Decl == Decl->getCanonicalDecl()) 276 return true; 277 278 // Skip decls that have no body, i.e. are just declarations. 279 Stmt *Body = Decl->getBody(); 280 if (!Body) 281 return true; 282 283 // Skip non-public methods. 284 AccessSpecifier AS = Decl->getAccess(); 285 if (AS != AccessSpecifier::AS_public) 286 return true; 287 288 // Skip variadic methods. 289 if (Decl->isVariadic()) 290 return true; 291 292 // Skip destructors. 293 if (isa<CXXDestructorDecl>(Decl)) 294 return true; 295 296 return false; 297 } 298 299 Rewriter &MyRewriter; 300 ASTContext &Context; 301 }; 302 303 class SBConsumer : public ASTConsumer { 304 public: 305 SBConsumer(Rewriter &R, ASTContext &Context) : Visitor(R, Context) {} 306 307 // Override the method that gets called for each parsed top-level 308 // declaration. 309 bool HandleTopLevelDecl(DeclGroupRef DR) override { 310 for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) { 311 Visitor.TraverseDecl(*b); 312 } 313 return true; 314 } 315 316 private: 317 SBVisitor Visitor; 318 }; 319 320 class SBAction : public ASTFrontendAction { 321 public: 322 SBAction() = default; 323 324 bool BeginSourceFileAction(CompilerInstance &CI) override { 325 llvm::outs() << "{\n"; 326 return true; 327 } 328 329 void EndSourceFileAction() override { 330 llvm::outs() << "}\n"; 331 MyRewriter.overwriteChangedFiles(); 332 } 333 334 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 335 StringRef File) override { 336 MyRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); 337 return std::make_unique<SBConsumer>(MyRewriter, CI.getASTContext()); 338 } 339 340 private: 341 Rewriter MyRewriter; 342 }; 343 344 int main(int argc, const char **argv) { 345 CommonOptionsParser OP(argc, argv, InstrCategory, 346 "Utility for generating the macros for LLDB's " 347 "instrumentation framework."); 348 349 auto PCHOpts = std::make_shared<PCHContainerOperations>(); 350 PCHOpts->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>()); 351 PCHOpts->registerReader(std::make_unique<ObjectFilePCHContainerReader>()); 352 353 ClangTool T(OP.getCompilations(), OP.getSourcePathList(), PCHOpts); 354 return T.run(newFrontendActionFactory<SBAction>().get()); 355 } 356