mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-15 20:33:10 +00:00
ClangPlugin: Add a PPCallbacks instance to collect JS_CELL-like macros
This commit is contained in:
parent
d74838f44d
commit
54fffef902
|
@ -10,6 +10,7 @@
|
|||
#include <clang/Basic/SourceManager.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
#include <clang/Frontend/FrontendPluginRegistry.h>
|
||||
#include <clang/Lex/MacroArgs.h>
|
||||
#include <unordered_set>
|
||||
|
||||
template<typename T>
|
||||
|
@ -258,4 +259,65 @@ void LibJSGCASTConsumer::HandleTranslationUnit(clang::ASTContext& context)
|
|||
visitor.TraverseDecl(context.getTranslationUnitDecl());
|
||||
}
|
||||
|
||||
char const* LibJSCellMacro::type_name(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Type::JSCell:
|
||||
return "JS_CELL";
|
||||
case Type::JSObject:
|
||||
return "JS_OBJECT";
|
||||
case Type::JSEnvironment:
|
||||
return "JS_ENVIRONMENT";
|
||||
case Type::JSPrototypeObject:
|
||||
return "JS_PROTOTYPE_OBJECT";
|
||||
case Type::WebPlatformObject:
|
||||
return "WEB_PLATFORM_OBJECT";
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
void LibJSPPCallbacks::LexedFileChanged(clang::FileID curr_fid, LexedFileChangeReason reason, clang::SrcMgr::CharacteristicKind, clang::FileID, clang::SourceLocation)
|
||||
{
|
||||
if (reason == LexedFileChangeReason::EnterFile) {
|
||||
m_curr_fid_hash_stack.push_back(curr_fid.getHashValue());
|
||||
} else {
|
||||
assert(!m_curr_fid_hash_stack.empty());
|
||||
m_curr_fid_hash_stack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void LibJSPPCallbacks::MacroExpands(clang::Token const& name_token, clang::MacroDefinition const&, clang::SourceRange range, clang::MacroArgs const* args)
|
||||
{
|
||||
if (auto* ident_info = name_token.getIdentifierInfo()) {
|
||||
static llvm::StringMap<LibJSCellMacro::Type> libjs_macro_types {
|
||||
{ "JS_CELL", LibJSCellMacro::Type::JSCell },
|
||||
{ "JS_OBJECT", LibJSCellMacro::Type::JSObject },
|
||||
{ "JS_ENVIRONMENT", LibJSCellMacro::Type::JSEnvironment },
|
||||
{ "JS_PROTOTYPE_OBJECT", LibJSCellMacro::Type::JSPrototypeObject },
|
||||
{ "WEB_PLATFORM_OBJECT", LibJSCellMacro::Type::WebPlatformObject },
|
||||
};
|
||||
|
||||
auto name = ident_info->getName();
|
||||
if (auto it = libjs_macro_types.find(name); it != libjs_macro_types.end()) {
|
||||
LibJSCellMacro macro { range, it->second, {} };
|
||||
|
||||
for (size_t arg_index = 0; arg_index < args->getNumMacroArguments(); arg_index++) {
|
||||
auto const* first_token = args->getUnexpArgument(arg_index);
|
||||
auto stringified_token = clang::MacroArgs::StringifyArgument(first_token, m_preprocessor, false, range.getBegin(), range.getEnd());
|
||||
// The token includes leading and trailing quotes
|
||||
auto len = strlen(stringified_token.getLiteralData());
|
||||
std::string arg_text { stringified_token.getLiteralData() + 1, len - 2 };
|
||||
macro.args.push_back({ arg_text, first_token->getLocation() });
|
||||
}
|
||||
|
||||
assert(!m_curr_fid_hash_stack.empty());
|
||||
auto curr_fid_hash = m_curr_fid_hash_stack.back();
|
||||
if (m_macro_map.find(curr_fid_hash) == m_macro_map.end())
|
||||
m_macro_map[curr_fid_hash] = {};
|
||||
m_macro_map[curr_fid_hash].push_back(macro);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static clang::FrontendPluginRegistry::Add<LibJSGCPluginAction> X("libjs_gc_scanner", "analyze LibJS GC usage");
|
||||
|
|
|
@ -10,6 +10,47 @@
|
|||
#include <clang/AST/RecursiveASTVisitor.h>
|
||||
#include <clang/Frontend/FrontendAction.h>
|
||||
|
||||
struct LibJSCellMacro {
|
||||
enum class Type {
|
||||
JSCell,
|
||||
JSObject,
|
||||
JSEnvironment,
|
||||
JSPrototypeObject,
|
||||
WebPlatformObject,
|
||||
};
|
||||
|
||||
struct Arg {
|
||||
std::string text;
|
||||
clang::SourceLocation location;
|
||||
};
|
||||
|
||||
clang::SourceRange range;
|
||||
Type type;
|
||||
std::vector<Arg> args;
|
||||
|
||||
static char const* type_name(Type);
|
||||
};
|
||||
|
||||
using LibJSCellMacroMap = std::unordered_map<unsigned int, std::vector<LibJSCellMacro>>;
|
||||
|
||||
class LibJSPPCallbacks : public clang::PPCallbacks {
|
||||
public:
|
||||
LibJSPPCallbacks(clang::Preprocessor& preprocessor, LibJSCellMacroMap& macro_map)
|
||||
: m_preprocessor(preprocessor)
|
||||
, m_macro_map(macro_map)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void LexedFileChanged(clang::FileID curr_fid, LexedFileChangeReason, clang::SrcMgr::CharacteristicKind, clang::FileID, clang::SourceLocation) override;
|
||||
|
||||
virtual void MacroExpands(clang::Token const& name_token, clang::MacroDefinition const& definition, clang::SourceRange range, clang::MacroArgs const* args) override;
|
||||
|
||||
private:
|
||||
clang::Preprocessor& m_preprocessor;
|
||||
std::vector<unsigned int> m_curr_fid_hash_stack;
|
||||
LibJSCellMacroMap& m_macro_map;
|
||||
};
|
||||
|
||||
class LibJSGCVisitor : public clang::RecursiveASTVisitor<LibJSGCVisitor> {
|
||||
public:
|
||||
explicit LibJSGCVisitor(clang::ASTContext& context)
|
||||
|
|
Loading…
Reference in a new issue