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 void pointers or 198 // function pointers as an argument, in which case we insert a dummy 199 // macro. 200 ShouldInsertDummy |= T->isFunctionPointerType() || T->isVoidPointerType(); 201 } 202 203 // Convert the two lists to string for the macros. 204 std::string ParamTypesStr = llvm::join(ParamTypes, ", "); 205 std::string ParamNamesStr = llvm::join(ParamNames, ", "); 206 207 CXXRecordDecl *Record = Decl->getParent(); 208 QualType ReturnType = Decl->getReturnType(); 209 210 // Construct the macros. 211 std::string Macro; 212 if (ShouldInsertDummy) { 213 // Don't insert a register call for dummy macros. 214 Macro = GetRecordDummyMacro( 215 ReturnType.getAsString(Policy), Record->getNameAsString(), 216 Decl->getNameAsString(), ParamTypesStr, ParamNamesStr); 217 218 } else if (isa<CXXConstructorDecl>(Decl)) { 219 llvm::outs() << GetRegisterConstructorMacro(Record->getNameAsString(), 220 ParamTypesStr); 221 222 Macro = GetRecordConstructorMacro(Record->getNameAsString(), 223 ParamTypesStr, ParamNamesStr); 224 } else { 225 llvm::outs() << GetRegisterMethodMacro( 226 ReturnType.getAsString(Policy), Record->getNameAsString(), 227 Decl->getNameAsString(), ParamTypesStr, Decl->isStatic(), 228 Decl->isConst()); 229 230 Macro = GetRecordMethodMacro( 231 ReturnType.getAsString(Policy), Record->getNameAsString(), 232 Decl->getNameAsString(), ParamTypesStr, ParamNamesStr, 233 Decl->isStatic(), Decl->isConst()); 234 } 235 236 // Insert the macro at the beginning of the function. We don't attempt to 237 // fix the formatting and instead rely on clang-format to fix it after the 238 // tool has run. This is also the reason that the macros end with two 239 // newlines, counting on clang-format to normalize this in case the macro 240 // got inserted before an existing newline. 241 SourceLocation InsertLoc = Lexer::getLocForEndOfToken( 242 Body->getBeginLoc(), 0, MyRewriter.getSourceMgr(), 243 MyRewriter.getLangOpts()); 244 MyRewriter.InsertTextAfter(InsertLoc, Macro); 245 246 // If the function returns a class or struct, we need to wrap its return 247 // statement(s). 248 bool ShouldRecordResult = ReturnType->isStructureOrClassType() || 249 ReturnType->getPointeeCXXRecordDecl(); 250 if (!ShouldInsertDummy && ShouldRecordResult) { 251 SBReturnVisitor Visitor(MyRewriter); 252 Visitor.TraverseDecl(Decl); 253 } 254 255 return true; 256 } 257 258 private: 259 /// Determine whether we need to consider the given CXXMethodDecl. 260 /// 261 /// Currently we skip the following cases: 262 /// 1. Decls outside the main source file, 263 /// 2. Decls that are only present in the source file, 264 /// 3. Decls that are not definitions, 265 /// 4. Non-public methods, 266 /// 5. Variadic methods. 267 /// 6. Destructors. 268 bool ShouldSkip(CXXMethodDecl *Decl) { 269 // Skip anything outside the main file. 270 if (!MyRewriter.getSourceMgr().isInMainFile(Decl->getBeginLoc())) 271 return true; 272 273 // Skip if the canonical decl in the current decl. It means that the method 274 // is declared in the implementation and is therefore not exposed as part 275 // of the API. 276 if (Decl == Decl->getCanonicalDecl()) 277 return true; 278 279 // Skip decls that have no body, i.e. are just declarations. 280 Stmt *Body = Decl->getBody(); 281 if (!Body) 282 return true; 283 284 // Skip non-public methods. 285 AccessSpecifier AS = Decl->getAccess(); 286 if (AS != AccessSpecifier::AS_public) 287 return true; 288 289 // Skip variadic methods. 290 if (Decl->isVariadic()) 291 return true; 292 293 // Skip destructors. 294 if (isa<CXXDestructorDecl>(Decl)) 295 return true; 296 297 return false; 298 } 299 300 Rewriter &MyRewriter; 301 ASTContext &Context; 302 }; 303 304 class SBConsumer : public ASTConsumer { 305 public: 306 SBConsumer(Rewriter &R, ASTContext &Context) : Visitor(R, Context) {} 307 308 // Override the method that gets called for each parsed top-level 309 // declaration. 310 bool HandleTopLevelDecl(DeclGroupRef DR) override { 311 for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) { 312 Visitor.TraverseDecl(*b); 313 } 314 return true; 315 } 316 317 private: 318 SBVisitor Visitor; 319 }; 320 321 class SBAction : public ASTFrontendAction { 322 public: 323 SBAction() = default; 324 325 bool BeginSourceFileAction(CompilerInstance &CI) override { 326 llvm::outs() << "{\n"; 327 return true; 328 } 329 330 void EndSourceFileAction() override { 331 llvm::outs() << "}\n"; 332 MyRewriter.overwriteChangedFiles(); 333 } 334 335 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 336 StringRef File) override { 337 MyRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); 338 return std::make_unique<SBConsumer>(MyRewriter, CI.getASTContext()); 339 } 340 341 private: 342 Rewriter MyRewriter; 343 }; 344 345 int main(int argc, const char **argv) { 346 CommonOptionsParser OP(argc, argv, InstrCategory, 347 "Utility for generating the macros for LLDB's " 348 "instrumentation framework."); 349 350 auto PCHOpts = std::make_shared<PCHContainerOperations>(); 351 PCHOpts->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>()); 352 PCHOpts->registerReader(std::make_unique<ObjectFilePCHContainerReader>()); 353 354 ClangTool T(OP.getCompilations(), OP.getSourcePathList(), PCHOpts); 355 return T.run(newFrontendActionFactory<SBAction>().get()); 356 } 357