Commit e67cb561 authored by Paul Chaignon's avatar Paul Chaignon

Merge BType, Map, and Probe Consumers

parent eae0acfb
...@@ -108,33 +108,26 @@ class ProbeSetter : public RecursiveASTVisitor<ProbeSetter> { ...@@ -108,33 +108,26 @@ class ProbeSetter : public RecursiveASTVisitor<ProbeSetter> {
set<Decl *> *ptregs_; set<Decl *> *ptregs_;
}; };
// Traces maps with external pointers as values. MapVisitor::MapVisitor(set<Decl *> &m) : m_(m) {}
class MapVisitor : public RecursiveASTVisitor<MapVisitor> {
public:
explicit MapVisitor(set<Decl *> &m) : m_(m) {}
bool VisitCallExpr(CallExpr *Call) {
if (MemberExpr *Memb = dyn_cast<MemberExpr>(Call->getCallee()->IgnoreImplicit())) {
StringRef memb_name = Memb->getMemberDecl()->getName();
if (DeclRefExpr *Ref = dyn_cast<DeclRefExpr>(Memb->getBase())) {
if (SectionAttr *A = Ref->getDecl()->getAttr<SectionAttr>()) {
if (!A->getName().startswith("maps"))
return true;
if (memb_name == "update" || memb_name == "insert") { bool MapVisitor::VisitCallExpr(CallExpr *Call) {
if (ProbeChecker(Call->getArg(1), ptregs_).needs_probe()) { if (MemberExpr *Memb = dyn_cast<MemberExpr>(Call->getCallee()->IgnoreImplicit())) {
m_.insert(Ref->getDecl()); StringRef memb_name = Memb->getMemberDecl()->getName();
} if (DeclRefExpr *Ref = dyn_cast<DeclRefExpr>(Memb->getBase())) {
if (SectionAttr *A = Ref->getDecl()->getAttr<SectionAttr>()) {
if (!A->getName().startswith("maps"))
return true;
if (memb_name == "update" || memb_name == "insert") {
if (ProbeChecker(Call->getArg(1), ptregs_).needs_probe()) {
m_.insert(Ref->getDecl());
} }
} }
} }
} }
return true;
} }
void set_ptreg(Decl *D) { ptregs_.insert(D); } return true;
private: }
set<Decl *> &m_;
set<clang::Decl *> ptregs_;
};
ProbeVisitor::ProbeVisitor(ASTContext &C, Rewriter &rewriter, set<Decl *> &m) : ProbeVisitor::ProbeVisitor(ASTContext &C, Rewriter &rewriter, set<Decl *> &m) :
C(C), rewriter_(rewriter), m_(m) {} C(C), rewriter_(rewriter), m_(m) {}
...@@ -801,59 +794,47 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) { ...@@ -801,59 +794,47 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
} }
// First traversal of AST to retrieve maps with external pointers. // First traversal of AST to retrieve maps with external pointers.
class MapConsumer : public clang::ASTConsumer { BTypeConsumer::BTypeConsumer(ASTContext &C, BFrontendAction &fe,
public: Rewriter &rewriter, set<Decl *> &m) :
explicit MapConsumer(set<Decl *> &m) : visitor_(m) {} map_visitor_(m), btype_visitor_(C, fe), probe_visitor_(C, rewriter, m) {}
bool HandleTopLevelDecl(DeclGroupRef Group) {
for (auto D : Group) { bool BTypeConsumer::HandleTopLevelDecl(DeclGroupRef Group) {
if (FunctionDecl *F = dyn_cast<FunctionDecl>(D)) { for (auto D : Group) {
if (F->isExternallyVisible() && F->hasBody()) { if (FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
for (auto arg : F->parameters()) { if (F->isExternallyVisible() && F->hasBody()) {
if (arg != F->getParamDecl(0) && !arg->getType()->isFundamentalType()) { for (auto arg : F->parameters()) {
visitor_.set_ptreg(arg); if (arg != F->getParamDecl(0) && !arg->getType()->isFundamentalType()) {
} map_visitor_.set_ptreg(arg);
} }
visitor_.TraverseDecl(D);
} }
map_visitor_.TraverseDecl(D);
} }
} }
return true;
} }
private: return true;
MapVisitor visitor_; }
};
BTypeConsumer::BTypeConsumer(ASTContext &C, BFrontendAction &fe) : visitor_(C, fe) {}
void BTypeConsumer::HandleTranslationUnit(ASTContext &Context) { void BTypeConsumer::HandleTranslationUnit(ASTContext &Context) {
DeclContext::decl_iterator it; DeclContext::decl_iterator it;
DeclContext *DC = TranslationUnitDecl::castToDeclContext(Context.getTranslationUnitDecl()); DeclContext *DC = TranslationUnitDecl::castToDeclContext(Context.getTranslationUnitDecl());
for (it = DC->decls_begin(); it != DC->decls_end(); it++) {
visitor_.TraverseDecl(*it);
}
}
ProbeConsumer::ProbeConsumer(ASTContext &C, Rewriter &rewriter, set<Decl *> &m) /**
: visitor_(C, rewriter, m) {} * ProbeVisitor's traversal runs after an entire translation unit has been parsed.
* to make sure maps with external pointers have been identified.
/** */
* ProbeVisitor's traversal runs after an entire translation unit has been parsed.
* to make sure maps with external pointers have been identified.
*/
void ProbeConsumer::HandleTranslationUnit(ASTContext &Context) {
DeclContext::decl_iterator it;
DeclContext *DC = TranslationUnitDecl::castToDeclContext(Context.getTranslationUnitDecl());
for (it = DC->decls_begin(); it != DC->decls_end(); it++) { for (it = DC->decls_begin(); it != DC->decls_end(); it++) {
Decl *D = *it; Decl *D = *it;
if (FunctionDecl *F = dyn_cast<FunctionDecl>(D)) { if (FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
if (F->isExternallyVisible() && F->hasBody()) { if (F->isExternallyVisible() && F->hasBody()) {
for (auto arg : F->parameters()) { for (auto arg : F->parameters()) {
if (arg != F->getParamDecl(0) && !arg->getType()->isFundamentalType()) if (arg != F->getParamDecl(0) && !arg->getType()->isFundamentalType())
visitor_.set_ptreg(arg); probe_visitor_.set_ptreg(arg);
} }
visitor_.TraverseDecl(D); probe_visitor_.TraverseDecl(D);
} }
} }
btype_visitor_.TraverseDecl(D);
} }
} }
...@@ -889,9 +870,7 @@ void BFrontendAction::EndSourceFileAction() { ...@@ -889,9 +870,7 @@ void BFrontendAction::EndSourceFileAction() {
unique_ptr<ASTConsumer> BFrontendAction::CreateASTConsumer(CompilerInstance &Compiler, llvm::StringRef InFile) { unique_ptr<ASTConsumer> BFrontendAction::CreateASTConsumer(CompilerInstance &Compiler, llvm::StringRef InFile) {
rewriter_->setSourceMgr(Compiler.getSourceManager(), Compiler.getLangOpts()); rewriter_->setSourceMgr(Compiler.getSourceManager(), Compiler.getLangOpts());
vector<unique_ptr<ASTConsumer>> consumers; vector<unique_ptr<ASTConsumer>> consumers;
consumers.push_back(unique_ptr<ASTConsumer>(new MapConsumer(m_))); consumers.push_back(unique_ptr<ASTConsumer>(new BTypeConsumer(Compiler.getASTContext(), *this, *rewriter_, m_)));
consumers.push_back(unique_ptr<ASTConsumer>(new ProbeConsumer(Compiler.getASTContext(), *rewriter_, m_)));
consumers.push_back(unique_ptr<ASTConsumer>(new BTypeConsumer(Compiler.getASTContext(), *this)));
return unique_ptr<ASTConsumer>(new MultiplexConsumer(std::move(consumers))); return unique_ptr<ASTConsumer>(new MultiplexConsumer(std::move(consumers)));
} }
......
...@@ -42,6 +42,17 @@ namespace ebpf { ...@@ -42,6 +42,17 @@ namespace ebpf {
class BFrontendAction; class BFrontendAction;
class FuncSource; class FuncSource;
// Traces maps with external pointers as values.
class MapVisitor : public clang::RecursiveASTVisitor<MapVisitor> {
public:
explicit MapVisitor(std::set<clang::Decl *> &m);
bool VisitCallExpr(clang::CallExpr *Call);
void set_ptreg(clang::Decl *D) { ptregs_.insert(D); }
private:
std::set<clang::Decl *> &m_;
std::set<clang::Decl *> ptregs_;
};
// Type visitor and rewriter for B programs. // Type visitor and rewriter for B programs.
// It will look for B-specific features and rewrite them into a valid // It will look for B-specific features and rewrite them into a valid
// C program. As part of the processing, open the necessary BPF tables // C program. As part of the processing, open the necessary BPF tables
...@@ -100,19 +111,13 @@ class ProbeVisitor : public clang::RecursiveASTVisitor<ProbeVisitor> { ...@@ -100,19 +111,13 @@ class ProbeVisitor : public clang::RecursiveASTVisitor<ProbeVisitor> {
// A helper class to the frontend action, walks the decls // A helper class to the frontend action, walks the decls
class BTypeConsumer : public clang::ASTConsumer { class BTypeConsumer : public clang::ASTConsumer {
public: public:
explicit BTypeConsumer(clang::ASTContext &C, BFrontendAction &fe); explicit BTypeConsumer(clang::ASTContext &C, BFrontendAction &fe, clang::Rewriter &rewriter, std::set<clang::Decl *> &map);
void HandleTranslationUnit(clang::ASTContext &Context) override; bool HandleTopLevelDecl(clang::DeclGroupRef Group) override;
private:
BTypeVisitor visitor_;
};
// A helper class to the frontend action, walks the decls
class ProbeConsumer : public clang::ASTConsumer {
public:
ProbeConsumer(clang::ASTContext &C, clang::Rewriter &rewriter, std::set<clang::Decl *> &map);
void HandleTranslationUnit(clang::ASTContext &Context) override; void HandleTranslationUnit(clang::ASTContext &Context) override;
private: private:
ProbeVisitor visitor_; MapVisitor map_visitor_;
BTypeVisitor btype_visitor_;
ProbeVisitor probe_visitor_;
}; };
// Create a B program in 2 phases (everything else is normal C frontend): // Create a B program in 2 phases (everything else is normal C frontend):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment