systemc-clang 2.0.0
Parsing SystemC constructs
Loading...
Searching...
No Matches
InstanceMatcher.h
Go to the documentation of this file.
1#ifndef _INSTANCE_MATCHER_H_
2#define _INSTANCE_MATCHER_H_
3
4//#include <type_traits>
5#include <vector>
6
8#include "ArrayTypeUtils.h"
9#include "clang/ASTMatchers/ASTMatchers.h"
10#include "llvm/Support/Debug.h"
11
13#undef DEBUG_TYPE
14#define DEBUG_TYPE "InstanceMatcher"
15
16using namespace clang::ast_matchers;
17
18namespace sc_ast_matchers {
19using namespace clang;
20using namespace utils::array_type;
21
22class InstanceArgumentMatcher : public MatchFinder::MatchCallback {
23 private:
24 clang::StringLiteral *instance_literal_;
25
26 public:
27 clang::StringLiteral *getInstanceLiteral() const { return instance_literal_; }
28
29 void registerMatchers(MatchFinder &finder) {
30 instance_literal_ = nullptr;
31 // clang-format off
32 auto arg_matcher = cxxConstructExpr(hasDescendant(
33 cxxConstructExpr(hasArgument(0,
34 stringLiteral().bind("inst_arg")
35 )
36 )
37 )
38 ).bind("ctor_expr");
39 // clang-format on
40
41 finder.addMatcher(arg_matcher, this);
42 }
43
44 virtual void run(const MatchFinder::MatchResult &result) {
45 auto ctor_expr = const_cast<clang::CXXConstructExpr *>(
46 result.Nodes.getNodeAs<clang::CXXConstructExpr>("ctor_expr"));
47 auto inst_arg = const_cast<clang::StringLiteral *>(
48 result.Nodes.getNodeAs<clang::StringLiteral>("inst_arg"));
49
50 LLVM_DEBUG(llvm::dbgs() << "## InstanceArgumentMatcher\n");
51 if (ctor_expr && inst_arg) {
52 LLVM_DEBUG(llvm::dbgs() << "@@ ctor expr\n");
53 instance_literal_ = inst_arg;
54 }
55 }
56
57 void dump() {
59 LLVM_DEBUG(instance_literal_->dump(););
60 }
61 }
62};
63
65//
67//
68//
70class InstanceMatcher : public MatchFinder::MatchCallback {
71 public:
72 typedef std::tuple<std::string, clang::Decl *, ModuleInstanceType>
74 typedef std::vector<InstanceDeclType> InstanceDeclarationsType;
75
79 //
80
81 typedef std::pair<clang::Decl *, ModuleInstanceType> ModuleInstanceTuple;
82 typedef std::map<clang::Decl *, ModuleInstanceType> InstanceDeclarations;
83
84 private:
93 //
95 // InstanceDeclarationsType instances_;
96
99
100 clang::ValueDecl *parent_fd_;
101
102 public:
104 instance_map_.insert(from.instance_map_.begin(), from.instance_map_.end());
105 return *this;
106 }
107
109
110 void setParentFieldDecl(clang::ValueDecl *parent_fd) {
111 parent_fd_ = parent_fd;
112 }
113 // Finds the instance with the same type as the argument.
114 // Pass by reference to the instance.
115
117 clang::CXXRecordDecl *decl,
118 std::vector<InstanceDeclType> &found_instances) {
119 // First check in the instance_fields.
120 // Check to see if the pointer to the type is the same as the sc_module
121 // type.
122
123 LLVM_DEBUG(llvm::dbgs() << "\n[findInstance] instance size: "
124 << instance_map_.size() << "\n");
125
126 LLVM_DEBUG(llvm::dbgs()
127 << "find decl name: " << decl->getName() << " " << decl << "\n");
128
129 // Walk through all the instances.
130 for (auto const &element : instance_map_) {
131 auto p_field_var_decl{element.first};
132 auto instance{element.second};
133
134 // TODO factor out this code to be handled for both.
135 if (auto *p_field{clang::dyn_cast<clang::FieldDecl>(p_field_var_decl)}) {
136 auto qtype{p_field->getType().getTypePtr()};
137 if (qtype->isRecordType()) {
138 auto rt{qtype->getAsCXXRecordDecl()};
139 LLVM_DEBUG(llvm::dbgs() << "- fd " << rt << " "
140 << p_field->getCanonicalDecl() << " ");
141 LLVM_DEBUG(instance.dump());
142
143 if (rt == decl) {
144 LLVM_DEBUG(llvm::dbgs()
145 << "- Insert fieldDecl into found instance\n");
146 found_instances.push_back(
147 InstanceDeclType(instance.instance_name, rt, instance));
148 }
149 }
150 } else {
151 // This is a VarDecl instance.
152 auto p_var{clang::dyn_cast<clang::VarDecl>(p_field_var_decl)};
153 auto qtype{p_var->getType().getTypePtr()};
154
155 std::string dbg{"[InstanceMatcher] VarDecl"};
156 if (qtype->isRecordType()) {
157 auto rt{qtype->getAsCXXRecordDecl()};
158 LLVM_DEBUG(llvm::dbgs() << "- vd " << rt << " "
159 << " ");
160 LLVM_DEBUG(instance.dump());
161 if (rt == decl) {
162 LLVM_DEBUG(llvm::dbgs()
163 << "- Insert vardecl into found instance\n");
164 found_instances.push_back(
165 InstanceDeclType(instance.instance_name, rt, instance));
166 }
167 }
168 }
169 }
170 LLVM_DEBUG(llvm::dbgs()
171 << "=> found_instances: " << found_instances.size() << "\n");
172
173 return (found_instances.size() != 0);
174 }
175
176 auto match_ctor_arg(const std::string &bind_arg_name,
177 const std::string &bind_ctor_expr) {
178 return cxxConstructExpr(hasArgument(0, stringLiteral().bind(bind_arg_name)))
179 .bind(bind_ctor_expr);
180 }
181
182 auto match_is_derived_sc_module(const std::string &bind_name) {
183 return recordType(hasDeclaration(
184 cxxRecordDecl(isDerivedFrom(hasName("::sc_core::sc_module")))
185 .bind(bind_name)) // hasDeclaration
186 ); // recordType;
187 }
188
189 void registerMatchers(MatchFinder &finder) {
190 parent_fd_ = nullptr;
204 /* clang-format off */
205 auto match_cxx_ctor_init =
206 cxxRecordDecl(
207 hasDescendant(
208 cxxConstructorDecl(
209 forEachConstructorInitializer(
210 cxxCtorInitializer(
211 isMemberInitializer(),
212 forField(
213 allOf(
214
215 anyOf(
216 hasType(
217 hasUnqualifiedDesugaredType(match_is_derived_sc_module("submodule")
218 )//hasUnqualifiedDesugaredType
219 )//hasType
220
221 ,
222 //1d
223 hasType(
224 hasUnqualifiedDesugaredType(
225 arrayType(
226 hasElementType(hasUnqualifiedDesugaredType(match_is_derived_sc_module("submodule")
227 )//hasUnqualifiedDesugaredType
228 )//hasElementType
229 )//arrayType
230 )//hasUnqualifiedDesugaredType
231 )//hasType
232
233 ,
234 //2d
235 hasType(
236 hasUnqualifiedDesugaredType(
237 arrayType(
238 hasElementType(hasUnqualifiedDesugaredType(
239 arrayType(hasElementType(hasUnqualifiedDesugaredType(match_is_derived_sc_module("submodule")
240 //
241 //
242 )//hasUnqualifiedDesugaredType
243 )//hasElementType
244 )//arrayType
245 )//hasUnqualifiedDesugaredType
246 )//hasElementType
247 )//arrayType
248 )//hasUnqualifiedDesugaredType
249 )//hasType
250 ,
251 // 3d
252 hasType(
253 hasUnqualifiedDesugaredType(
254 arrayType(
255 hasElementType(hasUnqualifiedDesugaredType(
256 arrayType(hasElementType(hasUnqualifiedDesugaredType(
257 arrayType(hasElementType(hasUnqualifiedDesugaredType(match_is_derived_sc_module("submodule")
258
259 )//hasUnqualifiedDesugaredType
260 )//hasElementType
261 )//arrayType
262
263
264 )//hasUnqualifiedDesugaredType
265 )//hasElementType
266 )//arrayType
267 )//hasUnqualifiedDesugaredType
268 )//hasElementType
269 )//arrayType
270 )//hasUnqualifiedDesugaredType
271 )//hasType
272
273 ) //anyOf
274 ,
275 fieldDecl().bind("ctor_fd")
276 )
277 )
278 ).bind("ctor_init")
279 )
280 )
281 ) //hasDescendant
282 ); //cxxRecordDecl
283
284
285
286 auto match_with_parent =
287 valueDecl(hasType(
288 hasUnqualifiedDesugaredType(
289 recordType(
290 hasDeclaration(match_cxx_ctor_init))))).bind("parent_fd");
291
292
293 auto match_instances_decl =
294 valueDecl(
295 hasDescendant(
296 match_ctor_arg("ctor_arg", "constructor_expr"))
297 ,
298 anyOf(
299 // 1d
300 hasType(
301 hasUnqualifiedDesugaredType(match_is_derived_sc_module("var_cxx_decl").bind("record_type")
302
304 // recordType(
305 // hasDeclaration(
306 // cxxRecordDecl(
307 // isDerivedFrom("::sc_core::sc_module")
308 // ).bind("var_cxx_decl")
309 // )
310 // ).bind("record_type")
311
312 )
313 ) // hasType
314 // 2d
315 ,
316 hasType(
317 hasUnqualifiedDesugaredType(
318 arrayType(
319 hasElementType(hasUnqualifiedDesugaredType(
320
321 match_is_derived_sc_module("submodule")
323 // recordType(
324 // hasDeclaration(
325 // cxxRecordDecl(isDerivedFrom(hasName("::sc_core::sc_module"))).bind("submodule")
326 // ) //hasDeclaration
327 // )// recordType
329 //
330 )
331 )
332 )//arrayType
333 )
334 )//hasType
335 )// anyOf
336 ).bind("instance_vd");
337
338 auto match_base_decl = match_cxx_ctor_init;
339 /* clang-format on */
340
342 //
343 finder.addMatcher(match_instances_decl, this);
344 finder.addMatcher(match_with_parent, this);
345 finder.addMatcher(match_base_decl, this);
346 }
347
348 void parseVarDecl(clang::VarDecl *instance_decl, std::string &instance_name) {
349 std::string name{instance_decl->getIdentifier()->getNameStart()};
350
352 auto var_name{instance_decl->getNameAsString()};
355 auto var_type_name{instance_decl->getType().getAsString()};
357
358 std::string parent_name{};
359 clang::ValueDecl *parent_rdecl{nullptr};
360
361 LLVM_DEBUG(llvm::dbgs()
362 << "=> VD: var_name " << var_name << " var_type_name "
363 << var_type_name << " parent_name " << parent_name
364 << "\n"); // instance_name "; // << instance_name << "\n";
365
366 ModuleInstanceType parsed_instance{};
367 parsed_instance.var_name = var_name;
368 parsed_instance.var_type_name = var_type_name;
369 parsed_instance.instance_name = instance_name;
370 parsed_instance.add_instance_name(instance_name);
371 // This is the Type of the FieldDecl.
372 parsed_instance.type_decl =
373 instance_decl->getType().getTypePtr()->getAsCXXRecordDecl();
374 // This is the FieldDecl.
375 parsed_instance.instance_decl = instance_decl;
376 parsed_instance.is_field_decl = false;
377 // FIXME: No parsing of VarDecl's as arrays?
378 parsed_instance.is_array = false;
379 parsed_instance.parent_name = parent_name;
380 parsed_instance.parent_decl = parent_rdecl;
381
382 LLVM_DEBUG(parsed_instance.dump(););
383 // Don't add repeated matches
384 // auto found_it{instance_map_.find(instance_decl)};
385 // if (found_it == instance_map_.end()) {
386 LLVM_DEBUG(llvm::dbgs() << "Inserting VD instance"
387 << "\n");
388 instance_map_.insert(
389 std::pair<Decl *, ModuleInstanceType>(instance_decl, parsed_instance));
390 // }
391 }
392
393 void parseFieldDecl(clang::FieldDecl *instance_decl,
394 clang::ValueDecl *parent_decl, std::string instance_name,
395 IndexMapType &index_map) {
396 std::string name{instance_decl->getIdentifier()->getNameStart()};
397
398 // This is the main object's constructor name
399 auto var_name{instance_decl->getNameAsString()};
400 // We do not get the instance name from within the field declaration.
401 // Get the type of the class of the field.
402 auto var_type_name{instance_decl->getType().getAsString()};
403
404 std::string parent_name{};
405 if (parent_decl) {
406 parent_name = parent_decl->getName().str();
407 }
408
409 auto array_indices{index_map[instance_name]};
410 LLVM_DEBUG(llvm::dbgs()
411 << "=> FD: var_name: " << var_name << " var_type_name, "
412 << var_type_name << " parent_name " << parent_name
413 << ", instance name " << instance_name << "[ "
414 << std::get<0>(array_indices) << ", "
415 << std::get<1>(array_indices) << ", "
416 << std::get<2>(array_indices)
417 << "]"
418 "\n");
419
420 ModuleInstanceType parsed_instance{};
421 parsed_instance.var_name = var_name;
422 parsed_instance.var_type_name = var_type_name;
423 LLVM_DEBUG(instance_decl->getType()->dump(););
424
426 const ArrayType *array_1d{
427 instance_decl->getType().getTypePtrOrNull()->getAsArrayTypeUnsafe()};
428 const ArrayType *array_2d{nullptr};
429 const ArrayType *array_3d{nullptr};
430 const ArrayType *array_type{nullptr};
431
435 //
436 if (array_1d) {
437 array_type = array_1d;
438 array_2d =
439 array_1d->getElementType().getTypePtrOrNull()->getAsArrayTypeUnsafe();
440 if (array_2d) {
441 array_type = array_2d;
442 array_3d = array_2d->getElementType()
443 .getTypePtrOrNull()
444 ->getAsArrayTypeUnsafe();
445
446 if (array_3d) {
447 array_type = array_3d;
448 }
449 }
450 }
451
452 LLVM_DEBUG(llvm::outs() << " All dim. arrays: " << array_1d << " "
453 << array_2d << " " << array_3d << "\n";);
454
455 // auto array_type{
456 // instance_decl->getType().getTypePtr()->getAsArrayTypeUnsafe()};
457 // Array type.
458 if (array_type) {
459 auto element_type{array_type->getElementType().getTypePtr()};
460 parsed_instance.type_decl = element_type->getAsCXXRecordDecl();
461 LLVM_DEBUG(
462 llvm::dbgs()
463 << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IS ARRAY type decl null: "
464 << parsed_instance.type_decl << "\n";
465 element_type->dump(););
466 parsed_instance.setArrayType();
467 parsed_instance.addArraySizes(getConstantArraySizes(instance_decl));
468 parsed_instance.setArrayParameters(index_map[instance_name]);
469 LLVM_DEBUG(llvm::outs() << "Dimension of array: "
470 << parsed_instance.getArrayDimension() << "\n";);
471 } else {
472 // Not an array type.
473 parsed_instance.type_decl =
474 instance_decl->getType().getTypePtr()->getAsCXXRecordDecl();
475 LLVM_DEBUG(
476 llvm::dbgs()
477 << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ NOT ARRAY type decl null: "
478 << parsed_instance.type_decl << "\n";);
479 }
480
481 LLVM_DEBUG(
482 instance_decl->dump();
483 );
484 parsed_instance.instance_decl = instance_decl;
485 parsed_instance.is_field_decl = true;
486 parsed_instance.parent_name = parent_name;
487 parsed_instance.parent_decl = parent_decl;
488 parsed_instance.instance_name = instance_name;
489 parsed_instance.add_instance_name(instance_name);
490
491 LLVM_DEBUG(parsed_instance.dump(););
492 // Don't add repeated matches
493 LLVM_DEBUG(llvm::dbgs() << "Inserting FD instance\n");
494
496 //
497
498 auto exists_instance{instance_map_.find(instance_decl)};
499
500 // Instance is NOT found
501 if (exists_instance == instance_map_.end()) {
502 instance_map_.insert(std::pair<Decl *, ModuleInstanceType>(
503 instance_decl, parsed_instance));
504 } else {
505 // Instance IS found.
506
507 exists_instance->second.add_instance_name(instance_name);
508 }
509 }
510
511 virtual void run(const MatchFinder::MatchResult &result) {
512 LLVM_DEBUG(llvm::dbgs()
513 << " ================== INSTANCE MATCHER ================= \n");
514 // General decl
515 auto instance_vd = const_cast<clang::VarDecl *>(
516 result.Nodes.getNodeAs<clang::VarDecl>("instance_vd"));
517 auto ctor_init = const_cast<clang::CXXCtorInitializer *>(
518 result.Nodes.getNodeAs<clang::CXXCtorInitializer>("ctor_init"));
519 auto ctor_fd = const_cast<clang::FieldDecl *>(
520 result.Nodes.getNodeAs<FieldDecl>("ctor_fd"));
521
524 clang::ValueDecl *parent_fd{parent_fd_};
525 if (!parent_fd) {
526 parent_fd = const_cast<clang::ValueDecl *>(
527 result.Nodes.getNodeAs<clang::ValueDecl>("parent_fd"));
528 }
529
530 auto ctor_arg = const_cast<clang::Stmt *>(
531 result.Nodes.getNodeAs<clang::Stmt>("ctor_arg"));
532
537 if (ctor_fd && ctor_init && parent_fd) {
538 LLVM_DEBUG(llvm::dbgs()
539 << "#### CTOR_FD: parent_fd " << parent_fd->getNameAsString()
540 << " ctor_fd " << ctor_fd->getNameAsString() << "\n");
541 LLVM_DEBUG(ctor_fd->dump());
542
543 auto index_map{getArrayInstanceIndex(ctor_init)};
544
545 clang::Expr *expr = ctor_init->getInit()->IgnoreImplicit();
546 clang::CXXConstructExpr *cexpr{
547 clang::dyn_cast<clang::CXXConstructExpr>(expr)};
548 clang::InitListExpr *iexpr{clang::dyn_cast<clang::InitListExpr>(expr)};
549
555 //
556
557 if ((iexpr != nullptr) && (cexpr == nullptr)) {
558 LLVM_DEBUG(llvm::dbgs() << "### IEXPR is not NULL\n";
559
560 llvm::dbgs() << "######## Going through index map: "
561 << index_map.size() << "\n";);
562 for (auto const &init : index_map) {
563 auto submodule_instance_name{init.first};
564 parseFieldDecl(ctor_fd, parent_fd, submodule_instance_name,
565 index_map);
566 LLVM_DEBUG(llvm::dbgs() << "#==> submodule_instance_name "
567 << submodule_instance_name << "\n");
568 }
569
570 } else {
571 MatchFinder iarg_registry{};
572 InstanceArgumentMatcher iarg_matcher{};
573 iarg_matcher.registerMatchers(iarg_registry);
574 // iarg_registry.match(*cexpr, *result.Context);
575
576 if (ctor_fd->hasInClassInitializer()) {
577 LLVM_DEBUG(llvm::dbgs() << "### In-class initializer\n";);
578 const Expr *in_class_init{ctor_fd->getInClassInitializer()};
579 iarg_registry.match(*in_class_init->IgnoreImplicit(),
580 *result.Context);
581 } else {
582 LLVM_DEBUG(llvm::dbgs() << "### Constructor initializer\n";);
583 iarg_registry.match(*cexpr, *result.Context);
584 }
585
586 LLVM_DEBUG(iarg_matcher.dump();
587 llvm::dbgs()
588 << "#### IndexMap: " << index_map.size() << "\n";);
589 // This retrieves the submodule instance name.
590 if (auto inst_literal = iarg_matcher.getInstanceLiteral()) {
591 auto submodule_instance_name = inst_literal->getString().str();
592 parseFieldDecl(ctor_fd, parent_fd, submodule_instance_name,
593 index_map);
594 LLVM_DEBUG(llvm::dbgs() << "=> submodule_instance_name "
595 << submodule_instance_name << "\n");
596 }
597 }
598 }
599
600 // Is it a FieldDecl or VarDecl
601
602 if (instance_vd) {
603 auto instance_name{cast<StringLiteral>(ctor_arg)->getString().str()};
604 LLVM_DEBUG(llvm::dbgs()
605 << "## VD: " << instance_vd->getNameAsString() << " "
606 << instance_vd << " instance_name " << instance_name << "\n");
607
608 parseVarDecl(instance_vd, instance_name);
609 }
610 }
611
612 // This is the callback function whenever there is a match.
613
614 void dump() {
615 // Instances holds both FieldDecl and VarDecl as its base class Decl.
616 LLVM_DEBUG(llvm::dbgs() << "# INSTANCE MATCHER DUMP \n";);
617 for (const auto &i : instance_map_) {
618 auto instance{i.second};
619 LLVM_DEBUG(llvm::dbgs()
620 << "decl* " << i.first << " " << instance.instance_name;);
621
622 auto instance_field{instance.type_decl};
623 LLVM_DEBUG(llvm::dbgs()
624 << " instance_field*: " << instance_field << "\n";);
625 //
626 // if (clang::dyn_cast<clang::FieldDecl>(instance_field)) {
627 // if (instance.is_field_decl) {
628 // LLVM_DEBUG(llvm::dbgs() << " FieldDecl ";);
629 // } else {
630 // LLVM_DEBUG(llvm::dbgs() << " VarDecl ";);
631 // }
632 // }
633 //
634 instance.dump();
635 }
636 }
637};
638}; // namespace sc_ast_matchers
639#endif
clang::StringLiteral * getInstanceLiteral() const
virtual void run(const MatchFinder::MatchResult &result)
void registerMatchers(MatchFinder &finder)
void setParentFieldDecl(clang::ValueDecl *parent_fd)
std::map< clang::Decl *, ModuleInstanceType > InstanceDeclarations
std::pair< clang::Decl *, ModuleInstanceType > ModuleInstanceTuple
std::vector< InstanceDeclType > InstanceDeclarationsType
std::tuple< std::string, clang::Decl *, ModuleInstanceType > InstanceDeclType
void parseVarDecl(clang::VarDecl *instance_decl, std::string &instance_name)
InstanceMatcher & operator=(const InstanceMatcher &from)
void parseFieldDecl(clang::FieldDecl *instance_decl, clang::ValueDecl *parent_decl, std::string instance_name, IndexMapType &index_map)
virtual void run(const MatchFinder::MatchResult &result)
void registerMatchers(MatchFinder &finder)
InstanceDeclarations instance_map_
deprecated
bool findInstanceByVariableType(clang::CXXRecordDecl *decl, std::vector< InstanceDeclType > &found_instances)
auto match_ctor_arg(const std::string &bind_arg_name, const std::string &bind_ctor_expr)
const InstanceDeclarations & getInstanceMap()
auto match_is_derived_sc_module(const std::string &bind_name)
Clang forward declarations.
Definition FindArgument.h:6
ArraySizesType getConstantArraySizes(const clang::ValueDecl *fd)
IndexMapType getArrayInstanceIndex(clang::CXXCtorInitializer *ctor_init)
std::map< std::string, std::tuple< std::size_t, std::size_t, std::size_t > > IndexMapType