14#ifndef _SENSITIVITY_MATCHER_H_
15#define _SENSITIVITY_MATCHER_H_
22#include "clang/ASTMatchers/ASTMatchFinder.h"
23#include "clang/ASTMatchers/ASTMatchers.h"
24#include "llvm/Support/Debug.h"
29#define DEBUG_TYPE "SensitivityMatcher"
32using namespace clang::ast_matchers;
48 std::tuple<std::string, clang::ValueDecl *, clang::MemberExpr *,
49 clang::VarDecl *, clang::ArraySubscriptExpr *, clang::ForStmt*>>
53 std::vector<std::tuple<std::string, clang::ValueDecl *, clang::MemberExpr *,
54 clang::VarDecl *, clang::ArraySubscriptExpr *, clang::ForStmt*>>
70 auto match_member_expr = findAll(memberExpr().bind(
"me"));
73 finder.addMatcher(match_member_expr,
this);
77 virtual void run(
const MatchFinder::MatchResult &result) {
78 auto me{
const_cast<clang::MemberExpr *
>(
79 result.Nodes.getNodeAs<clang::MemberExpr>(
"me"))};
82 std::string name{me->getMemberDecl()->getNameAsString()};
83 calls_.insert(
calls_.begin(), std::make_tuple(name, me->getMemberDecl(),
84 me,
vd_,
nullptr,
nullptr));
90 for (
auto const &call :
calls_) {
91 (llvm::outs() << std::get<0>(call) <<
" " << std::get<1>(call) <<
" "
92 << std::get<2>(call) <<
"\n");
147 fieldDecl().bind(
"fd")
151 cxxMemberCallExpr().bind(
"cxx_mcall")
153 arraySubscriptExpr().bind(
"array_fd")
157 hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
158 cxxRecordDecl(isSameOrDerivedFrom(
"sc_event")).bind(
"crd")))))
159 , hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
160 cxxRecordDecl(isSameOrDerivedFrom(
"sc_interface")).bind(
"crd")))))
161 , hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
162 cxxRecordDecl(isSameOrDerivedFrom(
"sc_event_finder")).bind(
"crd")))))
163 , hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
164 cxxRecordDecl(isSameOrDerivedFrom(
"sc_port_base")).bind(
"crd")))))
170 hasType(hasUnqualifiedDesugaredType(
171 recordType(hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom(
"sc_sensitive"))))
174 ).bind(
"cxx_operator_call_expr");
178 finder.addMatcher(match_opcall,
this);
181 virtual void run(
const MatchFinder::MatchResult &result) {
182 LLVM_DEBUG(llvm::dbgs() <<
"#### OperatorCallMatcher\n");
184 auto array_fd{result.Nodes.getNodeAs<clang::ArraySubscriptExpr>(
"array_fd")};
190 auto cxxcall{result.Nodes.getNodeAs<clang::CXXOperatorCallExpr>(
"cxx_operator_call_expr")};
193 auto cxx_mcall{
const_cast<clang::CXXMemberCallExpr*
>(
194 result.Nodes.getNodeAs<clang::CXXMemberCallExpr>(
"cxx_mcall"))};
196 const_cast<clang::MemberExpr*
>(result.Nodes.getNodeAs<clang::MemberExpr>(
"me"))};
219 typedef std::tuple<std::string, clang::ValueDecl*, clang::MemberExpr*, clang::VarDecl*, clang::ArraySubscriptExpr*, clang::ForStmt*>
223 typedef std::pair<std::string, std::vector<SensitivityTupleType>>
228 typedef std::map<std::string, std::vector<SensitivityTupleType>>
SenseMapType;
239 const std::vector<SensitivityTupleType> &sense_args) {
241 std::string ef_name{};
242 for (
auto const entry : sense_args) {
243 name = name + std::get<0>(entry);
244 auto vd{std::get<3>(entry)};
245 if (vd) { ef_name = vd->getNameAsString();}
247 return ef_name+
"__"+name;
262 auto NoNestedFor = forStmt(unless(hasDescendant(forStmt())), unless(hasAncestor(forStmt()))).bind(
"for_stmt");
264 auto scProcessType = hasType(hasUnqualifiedDesugaredType(recordType()));
265 auto processHandle = hasDescendant(valueDecl(scProcessType).bind(
"proc_vd"));
267 auto operatorCall = forEachDescendant(cxxOperatorCallExpr( ).bind(
"opcall"));
269 auto sensitivityInOneLoop = forStmt(operatorCall).bind(
"for_stmt");
271 auto match_single_for =
277 forEachDescendant(sensitivityInOneLoop)
279 allOf(operatorCall, unless(sensitivityInOneLoop))
281 ).bind(
"compound_stmt")
283 ).bind(
"cxx_constructor_decl");
303 finder.addMatcher(match_single_for,
this);
307 virtual void run(
const MatchFinder::MatchResult &result) {
309 DEBUG_WITH_TYPE(
"matcher-header",
311 <<
"====== SENSITIVITY MATCHER EXECUTED ======= \n");
313 clang::CXXMemberCallExpr *cxx_mcall{};
314 clang::MemberExpr *me_wo_mcall{};
315 clang::ArraySubscriptExpr *array_expr{};
318 auto proc_vd{
const_cast<clang::VarDecl *
>(
319 result.Nodes.getNodeAs<clang::VarDecl>(
"proc_vd"))};
320 auto proc_handle = proc_vd;
322 auto cons_decl{
const_cast<clang::CXXConstructorDecl *
>(
323 result.Nodes.getNodeAs<clang::CXXConstructorDecl>(
324 "cxx_constructor_decl"))};
325 auto opcall{
const_cast<clang::CXXOperatorCallExpr *
>(
326 result.Nodes.getNodeAs<clang::CXXOperatorCallExpr>(
"opcall"))};
327 auto for_stmt{
const_cast<clang::ForStmt *
>(
328 result.Nodes.getNodeAs<clang::ForStmt>(
"for_stmt"))};
339 llvm::dbgs() <<
"# proc_vd " <<
" " << proc_vd->getNameAsString() <<
"\n";
345 LLVM_DEBUG(llvm::dbgs() <<
"# ForStmt \n";
346 for_stmt->getInit()->
dump(););
350 MatchFinder sense_registry{};
353 sense_registry.match(*opcall, *result.Context);
355 cxx_mcall = sop_matcher.getMemberExprCallExpr();
356 me_wo_mcall = sop_matcher.getMemberExprWithoutCall();
357 array_expr =
const_cast<clang::ArraySubscriptExpr *
>(
358 sop_matcher.getMemberArraySubscriptExpr());
362 llvm::dbgs() <<
"cxx_mcall is true; ";
364 llvm::dbgs() <<
"me_wo_mcall is true; ";
365 }
if (array_expr) { llvm::dbgs() <<
"array_expr is true; "; }
376 MatchFinder call_registry{};
379 call_registry.match(*me_wo_mcall, *result.Context);
382 auto entry{call_matcher.getCallerCallee()};
391 MatchFinder call_registry{};
394 call_registry.match(*cxx_mcall, *result.Context);
396 auto entry{call_matcher.getCallerCallee()};
405 std::string name{me->getMemberDecl()->getNameAsString()};
406 auto entry{std::make_tuple(name, me->getMemberDecl(),
407 const_cast<clang::MemberExpr *
>(me),
409 std::vector<SensitivityTupleType> calls;
414 calls.insert(calls.begin(),
415 std::make_tuple(name, me->getMemberDecl(),
416 const_cast<clang::MemberExpr *
>(me),
431 auto generated_name{entry.first};
432 auto callercallee{entry.second};
433 LLVM_DEBUG(llvm::dbgs()
434 <<
"generated name is " << generated_name <<
" \n");
436 for (
auto const &call : callercallee) {
437 clang::VarDecl *vd{std::get<3>(call)};
438 clang::ForStmt *fs{std::get<5>(call)};
440 LLVM_DEBUG(llvm::dbgs()
441 <<
"sensitive signal is " << std::get<0>(call) <<
" "
442 << std::get<1>(call) <<
" " << std::get<2>(call) <<
"\n");
444 llvm::dbgs() <<
"within a for statement \n";
445 fs->getInit()->dump();
448 if (
auto array_expr = std::get<4>(call)) {
449 LLVM_DEBUG(llvm::dbgs() <<
"ArraySubscriptExpr\n";
450 array_expr->dump(););
451 llvm::dbgs() <<
"Print subscripts\n";
452 std::vector<const clang::Expr *> arr_subs{
454 for (
auto const &ex : arr_subs) {
void dump()
Dump out the caller and callee found in the sensitivity list.
CallerCalleeType getCallerCallee() const
This returns a list of all the caller and callees that are identified.
virtual void run(const MatchFinder::MatchResult &result)
This is the callback function when there is a match.
void registerMatchers(MatchFinder &finder, clang::VarDecl *vd)
Register the matchers to identify caller and callees.
std::vector< std::tuple< std::string, clang::ValueDecl *, clang::MemberExpr *, clang::VarDecl *, clang::ArraySubscriptExpr *, clang::ForStmt * > > CallerCalleeType
std::vector< std::tuple< std::string, clang::ValueDecl *, clang::MemberExpr *, clang::VarDecl *, clang::ArraySubscriptExpr *, clang::ForStmt * > > calls_
Store the information.
virtual void run(const MatchFinder::MatchResult &result)
clang::MemberExpr * getMemberExprWithoutCall()
clang::CXXMemberCallExpr * getMemberExprCallExpr()
const clang::ArraySubscriptExpr * getMemberArraySubscriptExpr()
const clang::ArraySubscriptExpr * array_fd_
clang::MemberExpr * me_wo_mcall_
void registerMatchers(MatchFinder &finder)
clang::CXXMemberCallExpr * cxx_mcall_
Class SensitivityMatcher.
virtual void run(const MatchFinder::MatchResult &result)
This is the callback function whenever there is a match.
std::pair< std::string, std::vector< SensitivityTupleType > > SensitivityPairType
This is the pair for inserting key-value entries in the map.
std::map< std::string, std::vector< SensitivityTupleType > > SenseMapType
The key is going to be the name of the FieldDecl/VarDecl.
std::tuple< std::string, clang::ValueDecl *, clang::MemberExpr *, clang::VarDecl *, clang::ArraySubscriptExpr *, clang::ForStmt * > SensitivityTupleType
clang::VarDecl * process_handle_
This provides access to the SystemC process' entry function handler.
void registerMatchers(MatchFinder &finder)
Defines the matcher, and setup the matcher.
SenseMapType getSensitivityMap()
Return the sensitivity map that has been created.
void dump()
Dump out the detected sensitivity list for every process.
std::string generateSensitivityName(const std::vector< SensitivityTupleType > &sense_args)
This generates an encoded name of the argument for the sensitivity.
SenseMapType sensitivity_
This is the map structure to store the identified sensitivity list.
ArraySizesExprType getArraySubscripts(const clang::Expr *expr)
const clang::MemberExpr * getArrayMemberExprName(const clang::Expr *expr)