systemc-clang 2.0.0
Parsing SystemC constructs
Loading...
Searching...
No Matches
HDLBody.cpp
Go to the documentation of this file.
1// clang-format off
2#include "SystemCClang.h"
3#include "HDLBody.h"
4//#include "HDLType.h"
5#include "clang/Basic/OperatorKinds.h"
6#include "clang/Basic/Diagnostic.h"
7#include "APIntUtils.h"
8#include "CallExprUtils.h"
10
11#include <iostream>
12#include <unordered_map>
13
14#include <assert.h>
15
16// clang-format on
17
19#undef DEBUG_TYPE
20#define DEBUG_TYPE "HDL"
21
22// We have to use the Traverse pattern rather than Visitor
23// because we need control to come back to the point of call
24// so that the generated tree can be returned back up the
25// call chain.
26
27// used https://github.com/super-ast/cpptranslate as example
28
29using namespace std;
30using namespace hnode;
31
39
40namespace systemc_hdl {
41 using namespace sc_ast_matchers::utils;
42
43 /*
44 bool HDLBody::isSCConstruct(const Type* type, const CXXMemberCallExpr* ce)
45 const { if (!ce) { return false;}
46
47 std::vector<llvm::StringRef> sc_dt_ns{"sc_dt"};
48 bool is_sc_builtin_t{ isInNamespace(type, sc_dt_ns)};
49
50 std::vector<llvm::StringRef> ports_signals_wait{"sc_port_base",
51 "sc_signal_in_if", "sc_signal_out_if", "sc_signal_inout_if",
52 "sc_prim_channel", "sc_thread_process"}; bool
53 is_ports_signals_wait{isCXXMemberCallExprSystemCCall(ce, ports_signals_wait)};
54
55 std::vector<llvm::StringRef> rvd{"sc_rvd"};
56 bool is_rvd{isCXXMemberCallExprSystemCCall(ce, rvd)};
57
58
59 return is_sc_builtin_t || is_ports_signals_wait || is_rvd;
60 }
61 */
62
63 HDLBody::HDLBody(clang::DiagnosticsEngine &diag_engine,
64 const ASTContext &ast_context, hdecl_name_map_t &mod_vname_map,
65 hfunc_name_map_t &allmethodecls,
66 overridden_method_map_t &overridden_method_map)
67 : diag_e{diag_engine},
68 ast_context_{ast_context},
69 mod_vname_map_{mod_vname_map},
70 allmethodecls_{allmethodecls},
71 overridden_method_map_{overridden_method_map} {
72 LLVM_DEBUG(llvm::dbgs() << "Entering HDLBody constructor\n");
73 }
74
75 void HDLBody::Run(Stmt *stmt, hNodep &h_top, HDLBodyMode runmode,
76 HDLType *HDLt_userclassesp)
77
78 {
79 LLVM_DEBUG(llvm::dbgs() << "Entering HDLBody Run Method\n");
80 h_ret = NULL;
81 add_info = (runmode == rmodinit);
82 HDLt_userclassesp_ = HDLt_userclassesp;
83 thismode = runmode;
84 if (thismode != rthread) methodecls.clear(); // clear out old state but need to preserve for thread
85 methodecls.set_prefix("_func_");
86
88 if (thismode == rthread) {
89 vname_map.set_prefix("_" + h_top->getname() + tvar_prefix);
90 } else {
92 }
93
94 LLVM_DEBUG(llvm::dbgs() << "allmethodecls_ size is " << allmethodecls_.size()
95 << "\n");
96
97 // if (!mod_vname_map_.empty())
98 // vname_map.insertall(mod_vname_map_);
99 bool ret1 = TraverseStmt(stmt);
100 AddVnames(h_top);
101 if (h_ret != NULL) h_top->child_list.push_back(h_ret);
102 LLVM_DEBUG(llvm::dbgs() << "Exiting HDLBody Run Method\n");
103 }
105 LLVM_DEBUG(llvm::dbgs() << "[[ Destructor HDLBody ]]\n");
106 }
107
108 // order of checking is important as some exprs
109 // inherit from binaryoperator
110
111 bool HDLBody::TraverseStmt(Stmt *stmt) {
112 LLVM_DEBUG(llvm::dbgs() << "In TraverseStmt\n");
113 if (stmt == nullptr) return false; // null statement, keep going
114
115 if (isa<CompoundStmt>(stmt)) {
116 LLVM_DEBUG(llvm::dbgs()
117 << "calling traverse compoundstmt from traversestmt\n");
118 VisitCompoundStmt((CompoundStmt *)stmt);
119 } else if (isa<DeclStmt>(stmt)) {
120 RecursiveASTVisitor::TraverseStmt(stmt);
121 // VisitDeclStmt((DeclStmt *)stmt);
122 } else if (isa<CallExpr>(stmt)) {
123 if (CXXOperatorCallExpr *opercall = dyn_cast<CXXOperatorCallExpr>(stmt)) {
124 LLVM_DEBUG(llvm::dbgs() << "found cxxoperatorcallexpr\n");
125 VisitCXXOperatorCallExpr(opercall);
126 } else if (isa<CXXMemberCallExpr>(stmt)) {
127 VisitCXXMemberCallExpr((CXXMemberCallExpr *)stmt);
128 } else {
129 VisitCallExpr((CallExpr *)stmt);
130 }
131 } else if (isa<CXXDefaultArgExpr>(stmt)) {
132 TraverseStmt(((CXXDefaultArgExpr *)stmt)->getExpr());
133 } else if (isa<ReturnStmt>(stmt)) {
134 RecursiveASTVisitor::TraverseStmt(stmt);
135 } else if (isa<CXXTemporaryObjectExpr>(stmt)) {
136 RecursiveASTVisitor::TraverseStmt(stmt);
137 } else {
138 if (isa<CXXConstructExpr>(stmt)) {
139 CXXConstructExpr *exp = (CXXConstructExpr *)stmt;
140 // CXXConstructExpr argument not yet handled
141 // LLVM_DEBUG(llvm::dbgs()
142 // << "CXXConstructExpr found, expr below\n");
143 // LLVM_DEBUG(exp->dump(llvm::dbgs(), ast_context_));
144
145 if ((exp->getNumArgs() == 1) &&
146 ((isa<IntegerLiteral>(exp->getArg(0))) || (isa<CXXBoolLiteralExpr>(exp->getArg(0)))) ) {
147 LLVM_DEBUG(llvm::dbgs()
148 << "CXXConstructExpr followed by integer literal found\n");
149 LLVM_DEBUG(exp->dump(llvm::dbgs(), ast_context_));
150 string s;
151 if (isa<IntegerLiteral>(exp->getArg(0))) {
152 IntegerLiteral *lit = (IntegerLiteral *)exp->getArg(0);
153 s = systemc_clang::utils::apint::toString(lit->getValue());
154 }
155 else { // bool
156 CXXBoolLiteralExpr * boollit = (CXXBoolLiteralExpr *) exp->getArg(0);
157 if (boollit->getValue()) s = "1"; else s = "0";
158 h_ret = new hNode(s, hNode::hdlopsEnum::hLiteral);
159 return true;
160 }
161 // need to add type to back of h_ret
163 te->Enumerate((exp->getType()).getTypePtr());
164 HDLType HDLt;
165 hNodep h_tmp = new hNode(hNode::hdlopsEnum::hNoop);
166 HDLt.SCtype2hcode(s, te->getTemplateArgTreePtr(), 0,
167 hNode::hdlopsEnum::hLiteral, h_tmp);
168 h_ret = h_tmp->child_list.back();
169 return true;
170 }
171 }
172 LLVM_DEBUG(llvm::dbgs()
173 << "stmt type " << stmt->getStmtClassName()
174 << " not recognized, calling default recursive ast visitor\n");
175 hNodep oldh_ret = h_ret;
176 RecursiveASTVisitor::TraverseStmt(stmt);
177 if (h_ret != oldh_ret) {
178 LLVM_DEBUG(
179 llvm::dbgs()
180 << "default recursive ast visitor called - returning translation\n");
181 return true;
182 }
183 for (auto arg : stmt->children()) {
184 LLVM_DEBUG(llvm::dbgs() << "child stmt type "
185 << ((Stmt *)arg)->getStmtClassName() << "\n");
186 if (isa<CXXThisExpr>(arg)) continue;
187 TraverseStmt(arg);
188 if (h_ret == oldh_ret) {
189 LLVM_DEBUG(llvm::dbgs() << "child stmt not handled\n");
190 // no output generated
191 h_ret = new hNode(arg->getStmtClassName(), hNode::hdlopsEnum::hUnimpl);
192 }
193 }
194 }
195
196 return true;
197 }
198
199 bool HDLBody::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *stmt) {
200 int nargs = ((CXXTemporaryObjectExpr *)stmt)->getNumArgs();
201 if (nargs == 0) { // end of the road
202 h_ret = new hNode(
203 "0",
204 (hNode::hdlopsEnum::hLiteral)); // assume this is an initializer of 0
205 } else {
206 Expr **objargs = ((CXXTemporaryObjectExpr *)stmt)->getArgs();
207 for (int i = 0; i < nargs; i++) {
208 TraverseStmt(objargs[i]);
209 }
210 }
211 return false;
212 }
213
214 bool HDLBody::VisitInitListExpr(InitListExpr *stmt) {
215 hNodep h_initlist = new hNode(hNode::hdlopsEnum::hVarInitList);
216 for (auto tmpexpr : ((InitListExpr *)stmt)->inits()) {
217 TraverseStmt(tmpexpr);
218 h_initlist->append(h_ret);
219 }
220 h_ret = h_initlist;
221 return false;
222 }
223
224 bool HDLBody::VisitReturnStmt(ReturnStmt *stmt) {
225 hNodep hretstmt = new hNode(hNode::hdlopsEnum::hReturnStmt);
226 if (((ReturnStmt *)stmt)->getRetValue() != nullptr) {
227 TraverseStmt(((ReturnStmt *)stmt)->getRetValue());
228 hretstmt->child_list.push_back(h_ret);
229 }
230 h_ret = hretstmt;
231 return false;
232 }
233
234 bool HDLBody::VisitCaseStmt(CaseStmt *stmt) {
235 LLVM_DEBUG(llvm::dbgs() << "Found case stmt\n");
236 hNodep old_hret = h_ret;
237 hNodep hcasep = new hNode(hNode::hdlopsEnum::hSwitchCase);
238 if (ConstantExpr *expr =
239 dyn_cast<ConstantExpr>(((CaseStmt *)stmt)->getLHS())) {
240 llvm::APSInt val = expr->getResultAsAPSInt();
241 hcasep->child_list.push_back(
243 hNode::hdlopsEnum::hLiteral));
244 }
245
246 TraverseStmt(((CaseStmt *)stmt)->getSubStmt());
247 if (h_ret != old_hret)
248 hcasep->child_list.push_back(h_ret);
249 else
250 hcasep->child_list.push_back(new hNode(hNode::hdlopsEnum::hUnimpl));
251
252 h_ret = hcasep;
253
254 return false;
255 }
256
257 bool HDLBody::VisitDefaultStmt(DefaultStmt *stmt) {
258 hNodep old_hret = h_ret;
259 hNodep hcasep = new hNode(hNode::hdlopsEnum::hSwitchDefault);
260 TraverseStmt(((DefaultStmt *)stmt)->getSubStmt());
261 if (h_ret != old_hret)
262 hcasep->child_list.push_back(h_ret);
263 else
264 hcasep->child_list.push_back(new hNode(hNode::hdlopsEnum::hNoop));
265 h_ret = hcasep;
266
267 return false;
268 }
269
270 bool HDLBody::VisitBreakStmt(BreakStmt *stmt) {
271 LLVM_DEBUG(llvm::dbgs() << "Found break stmt\n");
272 h_ret = new hNode(thismode == rthread ? hNode::hdlopsEnum::hReturnStmt
273 : hNode::hdlopsEnum::hBreak);
274 return false;
275 }
276
277 bool HDLBody::VisitContinueStmt(ContinueStmt *stmt) {
278 LLVM_DEBUG(llvm::dbgs() << "Found continue stmt\n");
279 h_ret = new hNode(hNode::hdlopsEnum::hContinue);
280
281 return false;
282 }
283
284 bool HDLBody::VisitCompoundStmt(CompoundStmt *cstmt) {
285 // Traverse each statement and append it to the array
286 hNodep h_cstmt = new hNode(hNode::hdlopsEnum::hCStmt);
287
288 for (clang::Stmt *stmt : cstmt->body()) {
289 TraverseStmt(stmt);
290 if (h_ret) {
291 if ((isAssignOp(h_ret)) && (h_ret->child_list.size() == 2) &&
292 (isAssignOp(h_ret->child_list[1]))) {
293 hNodep htmp =
294 NormalizeAssignmentChain(h_ret); // break up assignment chain
295 // h_ret = NormalizeAssignmentChain(h_ret); // break up assignment chain
296 h_cstmt->child_list.insert(h_cstmt->child_list.end(),
297 htmp->child_list.begin(),
298 htmp->child_list.end());
299 } else
300 h_cstmt->child_list.push_back(h_ret);
301 } else
302 LLVM_DEBUG(llvm::dbgs() << "stmt result was empty\n");
303 h_ret = NULL;
304 }
305
306 h_ret = h_cstmt;
307 return false;
308 }
309
314
315 bool HDLBody::VisitDeclStmt(DeclStmt *declstmt) {
316 // hNodep h_varlist = NULL;
317 // if (!declstmt->isSingleDecl()) {
318 // h_varlist = new hNode(hNode::hdlopsEnum::hPortsigvarlist);
319 // }
320 // from https://clang.llvm.org/doxygen/DeadStoresChecker_8cpp_source.html
321 for (auto *DI : declstmt->decls())
322 if (DI) {
323 auto *vardecl = dyn_cast<VarDecl>(DI);
324 if (!vardecl) continue;
326 vardecl); // adds it to the list of renamed local variables
327 }
328 // h_ret = NULL;
329 return false;
330 }
331
332 bool HDLBody::ProcessVarDecl(VarDecl *vardecl) {
333 LLVM_DEBUG(llvm::dbgs() << "ProcessVarDecl var name is " << vardecl->getName()
334 << "\n");
335
336 QualType q = vardecl->getType();
337 const Type *tp = q.getTypePtr();
338 LLVM_DEBUG(llvm::dbgs() << "ProcessVarDecl type name is " << q.getAsString()
339 << "\n");
340 // if (q.getAsString()=="::sc_core::sc_process_handle") { // simulation variable
341 // h_ret = NULL;
342 // return true;
343 // }
344
346
347 te->Enumerate(tp);
348 HDLType HDLt;
349 std::vector<llvm::APInt> array_sizes =
351
352 // create head node for the vardecl
353 hNodep h_varlist = new hNode(hNode::hdlopsEnum::hPortsigvarlist);
354
355 HDLt.SCtype2hcode(generate_vname(vardecl->getName().str()),
356 te->getTemplateArgTreePtr(), &array_sizes,
357 hNode::hdlopsEnum::hVardecl, h_varlist);
358
359 h_ret = NULL;
360
361 if (h_varlist->child_list.size() == 0) return true;
362
363 hNodep h_vardecl = h_varlist->child_list.back();
364 vname_map.add_entry(vardecl, vardecl->getName().str(), h_vardecl);
365
366 const Type *tstp;
367 bool isuserdefinedclass = false;
368 if (HDLt.usertype_info.userrectypes.size() > 0) {
369 tstp = (((te->getTemplateArgTreePtr())->getRoot())->getDataPtr())
370 ->getTypePtr();
371 /*
372 LLVM_DEBUG(
373 llvm::dbgs()
374 << "ProcessVarDecl init of user class, tstp in processvardecl is "
375 << tstp << " isscbytype says " << lutil.isSCByType(tstp) << "\n");
376 */
377 LLVM_DEBUG(HDLt.print(llvm::dbgs()));
378 auto recmapiter = HDLt.usertype_info.userrectypes.find(tstp);
379 if (recmapiter !=
381 .end()) { // && (recmapiter->second.find("sc_process_handle")==
382 // string::npos)) {
383 isuserdefinedclass = true;
384 // varinitp->set( hNode::hdlopsEnum::hMethodCall, recmapiter->second);
385
386 /*
387
388 // we know it is a userdefined class, now handle the constructor initializer
389
390 if (lutil.isSCType(exp->getType().getTypePtr())) {
391 LLVM_DEBUG(llvm::dbgs() << "CXXConstructExpr type is sctype " << exp->getType().getAsString()<< "\n");
392 }
393 else {
394 if ((exp->getNumArgs() == 0) || //
395 (exp->getNumArgs()>0) && !isa<CXXDefaultArgExpr>(exp->getArg(0))) // non-sctype with a true init
396 LLVM_DEBUG(llvm::dbgs() << "CXXConstructExpr type is not sctype " << exp->getType().getAsString()
397 << "num args is " << exp->getNumArgs() << "\n");
398 LLVM_DEBUG(exp->dump(llvm::dbgs(), ast_context_));
399 }
400 */
401
402
403 }
404 }
405
406 string qualmethodname = "ConstructorMethod";
407 if (Expr *declinit = vardecl->getInit()) {
408 LLVM_DEBUG(llvm::dbgs() << "ProcessVarDecl has an init: \n");
409 LLVM_DEBUG(declinit->dump(llvm::dbgs(), ast_context_));
410 CXXConstructExpr *tmpdeclinit = dyn_cast<CXXConstructExpr>(declinit);
411 if ((tmpdeclinit != NULL) &&(tmpdeclinit->getConstructor()->hasTrivialBody())) {
412 isuserdefinedclass = false; // no need to generate a method for it
413 }
414
415 if (isuserdefinedclass && (tmpdeclinit != NULL)) {
416 // For user-defined classes:
417 // If there is an initializer, define the method for the initializer and
418 // insert a call to the method. If there are parameters, they need to be
419 // supplied. if it is a user-defined class defined outside an sc_module,
420 // the "this" parameter needs to be supplied as first parameter to the
421 // constructor method.
422
423 const CXXConstructorDecl *cnstrdcl = tmpdeclinit->getConstructor();
424 // if (cnstrdcl->hasTrivialBody()) {
425
426 // return true; // no real initializer
427 // }
428 string methodname = cnstrdcl->getNameAsString();
429 qualmethodname = cnstrdcl->getQualifiedNameAsString();
430 lutil.make_ident(qualmethodname);
431 LLVM_DEBUG(llvm::dbgs() << "ConstructorDecl " << methodname << ", "
432 << qualmethodname << " for var follows\n");
433 LLVM_DEBUG(cnstrdcl->dump());
434 // add method decl for constructor
435 hNodep h_callp =
436 new hNode(qualmethodname, hNode::hdlopsEnum::hMethodCall);
437 const std::vector<StringRef> tmpmodstr{"sc_module"};
438 if (sc_ast_matchers::utils::isInNamespace(tstp, tmpmodstr)) {
439 LLVM_DEBUG(llvm::dbgs()
440 << "user-defined class is defined in sc module\n");
441 } else
442 h_callp->append(new hNode(FindVname(vardecl), hNode::hdlopsEnum::hVarref));
443 methodecls.add_entry((CXXMethodDecl *)cnstrdcl, qualmethodname, h_callp);
444 methodecls.methodobjtypemap[(const CXXMethodDecl *)cnstrdcl] = tstp;
445 TraverseStmt(tmpdeclinit);
446 if (h_ret) {
447 h_callp->append(h_ret);
448 }
449 h_ret = h_callp;
450 //}
451 return true;
452 }
453
454
455 TraverseStmt(declinit);
456
457 if (h_ret) {
458 hNodep varinitp = new hNode(hNode::hdlopsEnum::hVarAssign);
459 varinitp->child_list.push_back(
460 new hNode(FindVname(vardecl), hNode::hdlopsEnum::hVarref));
461 varinitp->child_list.push_back(h_ret);
462 h_ret = varinitp;
463 }
464 }
465 return true;
466 }
467
468 bool HDLBody::VisitBinaryOperator(BinaryOperator *expr) {
469 // ... handle expr. Can use
470 // bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx,
471 // SourceLocation *Loc = nullptr,
472 // bool isEvaluated = true) const;
473 // However, might be expensive to check on every binary operator
474
475 hNodep h_binop =
476 new hNode(expr->getOpcodeStr().str(),
477 hNode::hdlopsEnum::hBinop); // node to hold binop expr
478
479 string opcodestr = expr->getOpcodeStr().str();
480 string exprtypstr = expr->getType().getAsString();
481 LLVM_DEBUG(llvm::dbgs() << "in TraverseBinaryOperator, opcode is "
482 << opcodestr << "\n");
483 // lutil.checktypematch(exprtypstr, expr->getType().getTypePtr(),
484 // lutil.bothofthem); //
485
486 // ========================== CHECK 1 =====================
487 // FIXME: Cleanup
488 /*
489 bool t11 =
490 ((opcodestr == ",") &&
491 (lutil.isSCType(exprtypstr, expr->getType().getTypePtr()) ||
492 lutil.isSCBuiltinType(exprtypstr, expr->getType().getTypePtr())));
493 bool t21 =
494 ((opcodestr == ",") && (lutil.isSCByType(expr->getType().getTypePtr())));
495
496 if (t11 != t21) {
497 llvm::dbgs() << "### CHECK1: t11 != t21\n";
498 assert(0); // llvm::dbgs() << t11/0;
499 // std::cin.get();
500 }
501 */
502 // ========================== END CHECK =====================
503 //
504 if ((opcodestr == ",") &&
505 (lutil.isSCType(exprtypstr, expr->getType().getTypePtr()) ||
506 lutil.isSCBuiltinType(exprtypstr, expr->getType().getTypePtr()))) {
507 // if ((opcodestr == ",") && (lutil.isSCType(expr->getType()){
508
509 // if ((opcodestr == ",") &&
510 // (lutil.isSCByType(expr->getType().getTypePtr()))){
511 LLVM_DEBUG(llvm::dbgs() << "found comma, with sc type, expr follows\n");
512 LLVM_DEBUG(expr->dump(llvm::dbgs(), ast_context_););
513 h_binop->set("concat");
514 }
515 TraverseStmt(expr->getLHS());
516 h_binop->child_list.push_back(h_ret);
517
518 hNodep save_h_ret = h_ret;
519 TraverseStmt(expr->getRHS());
520 if (h_ret == save_h_ret)
521 h_binop->child_list.push_back(new hNode(hNode::hdlopsEnum::hUnimpl));
522 else
523 h_binop->child_list.push_back(h_ret);
524
525 h_ret = h_binop;
526
527 return false;
528 }
529
530 bool HDLBody::VisitUnaryOperator(UnaryOperator *expr) {
531 LLVM_DEBUG(llvm::dbgs() << "in TraverseUnaryOperator expr node is \n");
532 LLVM_DEBUG(expr->dump(llvm::dbgs(), ast_context_););
533
534 auto opcstr = expr->getOpcode();
535
536 hNodep h_unop;
537
538 if ((expr->getOpcodeStr(opcstr).str() == "++") ||
539 (expr->getOpcodeStr(opcstr).str() == "--")) {
540 if (expr->isPostfix())
541 h_unop = new hNode(expr->getOpcodeStr(opcstr).str(),
542 hNode::hdlopsEnum::hPostfix);
543 else
544 h_unop = new hNode(expr->getOpcodeStr(opcstr).str(),
545 hNode::hdlopsEnum::hPrefix);
546 } else
547 h_unop = new hNode(expr->getOpcodeStr(opcstr).str(),
548 hNode::hdlopsEnum::hUnop); // node to hold unop expr
549
550 TraverseStmt(expr->getSubExpr());
551 h_unop->child_list.push_back(h_ret);
552
553 h_ret = h_unop;
554
555 return false;
556 }
557
558 bool HDLBody::VisitConditionalOperator(ConditionalOperator *expr) {
559 LLVM_DEBUG(llvm::dbgs() << "in VisitConditionalOperator expr node is \n");
560 LLVM_DEBUG(expr->dump(llvm::dbgs(), ast_context_););
561
562 hNodep h_condop = new hNode(hNode::hdlopsEnum::hCondop);
563 TraverseStmt(expr->getCond());
564 h_condop->child_list.push_back(h_ret); // need to check if it's null or didn't get changed
565 TraverseStmt(expr->getTrueExpr());
566 h_condop->child_list.push_back(h_ret); // need to check if it's null or didn't get changed
567 TraverseStmt(expr->getFalseExpr());
568 h_condop->child_list.push_back(h_ret); // need to check if it's null or didn't get changed
569 h_ret = h_condop;
570 return false;
571 }
572
573 bool HDLBody::VisitIntegerLiteral(IntegerLiteral *lit) {
574 LLVM_DEBUG(llvm::dbgs() << "In integerliteral\n");
575 string s = systemc_clang::utils::apint::toString(lit->getValue());
576 h_ret = new hNode(s, hNode::hdlopsEnum::hLiteral);
577
578 return false;
579 }
580
581 bool HDLBody::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *b) {
582 LLVM_DEBUG(llvm::dbgs() << "In boollitexpr\n");
583 bool v = b->getValue();
584 h_ret = new hNode(v ? "1" : "0", hNode::hdlopsEnum::hLiteral);
585
586 return false;
587 }
588
589 bool HDLBody::VisitDeclRefExpr(DeclRefExpr *expr) {
590 // ... handle expr
591 LLVM_DEBUG(llvm::dbgs() << "In TraverseDeclRefExpr\n");
592
593 ValueDecl *value = expr->getDecl();
594 if (isa<EnumConstantDecl>(value)) {
595 EnumConstantDecl *cd = (EnumConstantDecl *)value;
596 LLVM_DEBUG(llvm::dbgs()
597 << "got enum constant value " << cd->getInitVal() << "\n");
598 h_ret = new hNode(systemc_clang::utils::apint::toString(cd->getInitVal()),
599 hNode::hdlopsEnum::hLiteral);
600 return false;
601 }
602
603 // get a name
604
605 string name = (expr->getNameInfo()).getName().getAsString();
606 LLVM_DEBUG(llvm::dbgs() << "name is " << name << "\n");
607
608 // if this is variable reference has a constant initializer, return that value
609 if (isa<VarDecl>(value) && ((VarDecl *)value)->isConstexpr()) {
610 VarDecl *vard = (VarDecl *)value;
611 Expr *einit = vard->getInit();
612 clang::Expr::EvalResult result;
613 if (einit->EvaluateAsInt(result, vard->getASTContext())) {
614 h_ret =
615 new hNode(systemc_clang::utils::apint::toString(result.Val.getInt()),
616 hNode::hdlopsEnum::hLiteral);
617 return false;
618 }
619 }
620 if (isa<FunctionDecl>(value)) {
621 // ============= CHECK ================
622 /*
623 bool t1 = !(lutil.isSCFunc(name) || lutil.isSCMacro(name));
624 bool t2 = !lutil.isSCByCallExpr(expr);
625
626 if (t1 != t2) {
627 llvm::dbgs() << "@@@@ CHECK isSCFunc failed " << t1 << " t2 " << t2
628 << " name " << name << "\n";
629 assert(0);
630 // std::cin.get();
631 }
632 */
633 // ============= END CHECK ================
634 if (!(lutil.isSCFunc(name) ||
635 lutil.isSCMacro(name))) { // similar to method call, skip builtin
636 FunctionDecl *funval = (FunctionDecl *)value;
637
638 string qualfuncname{value->getQualifiedNameAsString()};
639 lutil.make_ident(qualfuncname);
640 if (add_info)
641 qualfuncname +=
642 ":" + name; // !!! add unqualified name for future hcode processing
643 // methodecls[qualfuncname] =
644 // (FunctionDecl *)value; // add to list of "methods" to be generated
645 // methodecls.insert(make_pair(qualfuncname, (FunctionDecl *)value));
646
647 // create the call expression
648 hNodep hfuncall = new hNode(qualfuncname, hNode::hdlopsEnum::hMethodCall);
649 // don't add this method to methodecls if processing modinit
650 if (!add_info) {
651 string tmpname = FindFname((FunctionDecl *)value);
652 if (tmpname == "") { // isn't in local or global symbol table
653 LLVM_DEBUG(llvm::dbgs() << "adding method " << qualfuncname
654 << " with pointer " << value << " \n");
655 LLVM_DEBUG(methodecls.print(llvm::dbgs()));
656 methodecls.add_entry((CXXMethodDecl *)funval, qualfuncname, hfuncall);
657 } else
658 hfuncall->set(tmpname);
659 }
660 h_ret = hfuncall;
661 return false;
662 } else { // here it is an SCFunc
663 string typname = (expr->getType()).getAsString();
664 if (typname.find("sc_dt::sc_concat") != std::string::npos) {
665 // found concat function call
666 hNodep hconcat = new hNode(name, hNode::hdlopsEnum::hBinop);
667 h_ret = hconcat;
668 return false;
669 }
670 h_ret = new hNode(name, hNode::hdlopsEnum::hBuiltinFunction);
671 return false;
672 // may have other special functions to recognize later
673 }
674 }
675
676 string newname = FindVname(expr->getDecl());
677 LLVM_DEBUG(llvm::dbgs() << "new name is " << newname << "\n");
678 LLVM_DEBUG(expr->getDecl()->dump(llvm::dbgs()));
679
680 h_ret =
681 new hNode(newname.empty() ? name : newname, hNode::hdlopsEnum::hVarref);
682 return false;
683 }
684
685 bool HDLBody::VisitArraySubscriptExpr(ArraySubscriptExpr *expr) {
686 LLVM_DEBUG(llvm::dbgs()
687 << "In TraverseArraySubscriptExpr, base, idx, tree follow\n");
688 LLVM_DEBUG(llvm::dbgs() << "base:\n");
689 LLVM_DEBUG(expr->getBase()->dump(llvm::dbgs(), ast_context_));
690 LLVM_DEBUG(llvm::dbgs() << "idx:\n");
691 LLVM_DEBUG(expr->getIdx()->dump(llvm::dbgs(), ast_context_));
692 LLVM_DEBUG(llvm::dbgs() << "tree:\n");
693 LLVM_DEBUG(expr->dump(llvm::dbgs(), ast_context_));
694 hNodep h_arrexpr = new hNode("ARRAYSUBSCRIPT", hNode::hdlopsEnum::hBinop);
695 TraverseStmt(expr->getLHS());
696 h_arrexpr->child_list.push_back(h_ret);
697 TraverseStmt(expr->getRHS());
698 h_arrexpr->child_list.push_back(h_ret);
699 h_ret = h_arrexpr;
700 return false;
701 }
702
703 bool HDLBody::VisitCXXMemberCallExpr(CXXMemberCallExpr *callexpr) {
704 bool is_explicitly_overridden = false;
705 // this doesn't seem to help
706 LangOptions LangOpts;
707
708 LangOpts.CPlusPlus = true;
709 const PrintingPolicy Policy(LangOpts);
710
711 LLVM_DEBUG(llvm::dbgs()
712 << "In TraverseCXXMemberCallExpr, printing implicit object arg\n");
713 // Retrieves the implicit object argument for the member call.
714 // For example, in "x.f(5)", this returns the sub-expression "x".
715
716 Expr *rawarg = (callexpr->getImplicitObjectArgument());
717 LLVM_DEBUG(llvm::dbgs() << "raw implicitobjectargument follows\n");
718 LLVM_DEBUG(rawarg->dump(llvm::dbgs(), ast_context_));
719
720 Expr *objarg = (callexpr->getImplicitObjectArgument())->IgnoreImplicit();
721 LLVM_DEBUG(
722 llvm::dbgs() << "implicitobjectargument, ignore implicit follows\n");
723 LLVM_DEBUG(objarg->dump(llvm::dbgs(), ast_context_));
724 CXXRecordDecl *cdecl = callexpr->getRecordDecl();
725 const Type *typeformethodclass = cdecl->getTypeForDecl();
726 LLVM_DEBUG(llvm::dbgs() << "Type pointer from RecordDecl is "
727 << typeformethodclass << "\n");
728
729 QualType argtyp;
730 if (dyn_cast<ImplicitCastExpr>(rawarg)) { // cast to a specfic type
731 argtyp = rawarg->getType();
732 is_explicitly_overridden = true;
733 } else {
734 argtyp = objarg->getType();
735 }
736 LLVM_DEBUG(llvm::dbgs() << "type of x in x.f(5) is "
737 << argtyp.getAsString(Policy) << "\n");
738 QualType objtyp = callexpr->getObjectType();
739 LLVM_DEBUG(llvm::dbgs() << "... and object type is "
740 << objtyp.getAsString(Policy) << "\n");
741 string methodname = "NoMethod", qualmethodname = "NoQualMethod";
742
743 CXXMethodDecl *methdcl = callexpr->getMethodDecl();
744 if ((!is_explicitly_overridden) && (overridden_method_map_.size() > 0) &&
745 (overridden_method_map_.find(methdcl) != overridden_method_map_.end())) {
746 methdcl = const_cast<CXXMethodDecl *>(overridden_method_map_[methdcl]);
747 }
748 LLVM_DEBUG(llvm::dbgs() << "methoddecl follows\n");
749 LLVM_DEBUG(methdcl->dump(llvm::dbgs()));
750 if (isa<NamedDecl>(methdcl) && methdcl->getDeclName()) {
751 methodname = methdcl->getNameAsString();
752 qualmethodname = methdcl->getQualifiedNameAsString();
753 // make_ident(qualmethodname);
754 // methodecls[qualmethodname] = methdcl; // put it in the set of
755 // method decls
756
757 LLVM_DEBUG(llvm::dbgs()
758 << "here is method printname " << methodname << " and qual name "
759 << qualmethodname << " and declp " << methdcl << " \n");
760 if (methodname.compare(0, 8, "operator") ==
761 0) { // 0 means compare =, 8 is len("operator")
762 // the conversion we know about, can be skipped
763 LLVM_DEBUG(llvm::dbgs() << "Found operator conversion node\n");
764 TraverseStmt(objarg);
765 return false;
766 }
767 }
768
770 hNode *h_callp = NULL;
771 LLVM_DEBUG(llvm::dbgs() << "found " << methodname << "\n");
772
773 // if type of x in x.f(5) is primitive sc type (sc_in, sc_out, sc_inout,
774 // sc_signal and method name is either read or write, generate a SigAssignL|R
775 // -- FIXME need to make sure it is templated to a primitive type
776
777 // lutil.isSCType(qualmethodname, typeformethodclass);
778 // lutil.checktypematch(qualmethodname, typeformethodclass, lutil.issctype);
779
780 // bool inns_result = sc_ast_matchers::utils::isInNamespace(callexpr,
781 // "sc_core") || sc_ast_matchers::utils::isInNamespace(callexpr, "sc_dt");
782 bool foundsctype = lutil.isSCType(qualmethodname, typeformethodclass);
783 /*
784 bool newfoundsctype =
785 lutil.isSCByCallExpr(callexpr); // || lutil.isSCType(typeformethodclass);
786 if (foundsctype != newfoundsctype) {
787 LLVM_DEBUG(llvm::dbgs()
788 << "CHECK callexpr isSCType nonmatch -- old one returned "
789 << foundsctype << " for " << qualmethodname << "\n");
790 callexpr->dump();
791 assert(0);
792 // std::cin.get();
793 // foundsctype = newfoundsctype; // ADD THIS TO TEST SEGV
794 }
795 */
796
797 // bool foundsctype = lutil.isSCByCallExpr(callexpr);
798
799 if ((methodname == "read") && foundsctype)
800 opc = hNode::hdlopsEnum::hSigAssignR;
801 else if ((methodname == "write") && foundsctype)
802 opc = hNode::hdlopsEnum::hSigAssignL;
803 else if ((methodname == "wait") && thismode == rthread)
804 opc = hNode::hdlopsEnum::hWait;
805 else if (foundsctype) { // operator from simulation library
806 opc = hNode::hdlopsEnum::hBuiltinFunction;
807 } else {
808 opc = hNode::hdlopsEnum::hMethodCall;
809 lutil.make_ident(qualmethodname);
810 if (add_info)
811 qualmethodname += ":" + methodname; // include unqualified name for
812 // future hcode processing !!!
813 // methodecls[qualmethodname] = methdcl; // put it in the set of method
814 // decls
815 h_callp = new hNode(qualmethodname, opc);
816 // don't add this method to methodecls if processing modinit
817 if (!add_info) {
818 string tmpname = FindFname((FunctionDecl *)methdcl);
819 if (tmpname == "") { // isn't in local or global symbol table
820 LLVM_DEBUG(llvm::dbgs() << "adding method " << qualmethodname
821 << " with pointer " << methdcl << " \n");
822 methodecls.print(llvm::dbgs());
823 methodecls.add_entry(methdcl, qualmethodname, h_callp);
824 // string objstr = objtyp.getAsString(Policy);
825 // lutil.make_ident(objstr);
826 // bool a = !isCXXMemberCallExprSystemCCall(callexpr), b
827 // =sc_ast_matchers::utils::isInNamespace(callexpr, "sc_core") ;
828
829 // LLVM_DEBUG(llvm::dbgs() << "is sysc call " << qualmethodname << "
830 // old, new "<< a
831 // << " " << b << " end\n");
832 if (!isCXXMemberCallExprSystemCCall(callexpr))
833 methodecls.methodobjtypemap[methdcl] = typeformethodclass;
834 } else
835 h_callp->set(tmpname);
836 }
837 methodname = qualmethodname;
838 }
839
840 if (h_callp == NULL)
841 h_callp = new hNode(methodname, opc); // list to hold call expr node
842
843 // check for constant expr in wait statement
844 if ((opc == hNode::hdlopsEnum::hWait) && (callexpr->getNumArgs() > 0)) {
845 GetWaitArg(h_callp, callexpr->getArg(0));
846 h_ret = h_callp;
847 return false;
848 }
849
850
851 hNodep save_hret = h_ret;
852 // insert "this" argument if mod init block or recognized as special method
853 // (read|write|wait of sc type), or it is a method but not derived for
854 // scmodule hierarchy
855 if ((add_info) || ((opc != hNode::hdlopsEnum::hMethodCall) ||
856 (opc == hNode::hdlopsEnum::hMethodCall) &&
857 (!isCXXMemberCallExprSystemCCall(callexpr)))) {
858 TraverseStmt(objarg); // traverse the x in x.f(5)
859 if (h_ret && (h_ret != save_hret)) h_callp->child_list.push_back(h_ret);
860 }
861
862 for (auto arg : callexpr->arguments()) {
863 save_hret = h_ret;
864 TraverseStmt(arg);
865 if (h_ret != save_hret) h_callp->child_list.push_back(h_ret);
866 }
867 h_ret = h_callp;
868 return false;
869 }
870
871 bool HDLBody::isLogicalOp(clang::OverloadedOperatorKind opc) {
872 switch (opc) {
873 case OO_Less:
874 case OO_LessEqual:
875 case OO_Greater:
876 case OO_GreaterEqual:
877 case OO_ExclaimEqual:
878 case OO_EqualEqual:
879 return true;
880
881 default:
882 return false;
883 }
884 }
885
886 bool HDLBody::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *opcall) {
887 string operatorname = getOperatorSpelling(opcall->getOperator());
888 string operatortype = (opcall->getType()).getAsString();
889 hNodep h_operop;
890
891 LLVM_DEBUG(llvm::dbgs() << "In TraverseCXXOperatorCallExpr, Operator name is "
892 << operatorname << "\n");
893 LLVM_DEBUG(llvm::dbgs() << "Type name " << operatortype << "\n");
894 LLVM_DEBUG(opcall->getType()->dump(llvm::dbgs(), ast_context_));
895
896 // ========================== CHECK 2=====================
897 const Type *optypepointer = opcall->getType().getTypePtr();
898
899 /*
900 bool t12 =
901 ((operatorname == "=") || lutil.isSCBuiltinType(operatortype) ||
902 lutil.isSCType(operatortype) || (opcall->getType())->isBuiltinType() ||
903 ((operatorname == "<<") &&
904 (operatortype.find("sensitive") != std::string::npos)));
905 bool t22 = ((operatorname == "=") || lutil.isSCByType(optypepointer) ||
906 (opcall->getType())->isBuiltinType() ||
907 ((operatorname == "<<") &&
908 (operatortype.find("sensitive") != std::string::npos)));
909
910 if (t12 != t22) {
911 llvm::dbgs() << "CHECK### 2: t12 != t22\n";
912 assert(0);
913 // std::cin.get();
914 }
915 */
916 // ========================== END CHECK =====================
917 //
918
919 if ((operatorname == "=") ||
920 lutil.isSCBuiltinType(operatortype, optypepointer) ||
921 lutil.isSCType(operatortype, optypepointer) ||
922
923 // if ((operatorname == "=") || lutil.isSCByType(optypepointer ) ||
924 (opcall->getType())->isBuiltinType() ||
925 ((operatorname == "<<") &&
926 (operatortype.find("sensitive") != std::string::npos))) {
927 LLVM_DEBUG(llvm::dbgs() << "Processing operator call type\n");
928 // operator for an SC type
929 if ((operatorname.compare("()") == 0) &&
930 (operatortype.find("subref") != string::npos) &&
931 (opcall->getNumArgs() == 3)) {
932 // bit slice
933 h_operop = new hNode("SLICE", hNode::hdlopsEnum::hBinop);
934 } else {
935 if (operatorname == "[]") // subscript in operator call expre
936 h_operop = new hNode("ARRAYSUBSCRIPT", hNode::hdlopsEnum::hBinop);
937 else if ((operatorname == "++") || (operatorname == "--")) {
938 if (opcall->getNumArgs() == 2)
939 h_operop = new hNode(operatorname, hNode::hdlopsEnum::hPostfix);
940 else
941 h_operop = new hNode(operatorname, hNode::hdlopsEnum::hPrefix);
942 } else {
943 if (opcall->getNumArgs() == 1)
944 h_operop = new hNode(operatorname, hNode::hdlopsEnum::hUnop);
945 else
946 h_operop = new hNode(operatorname, hNode::hdlopsEnum::hBinop);
947
948 if ((operatorname == ",") /*&& (lutil.isSCByCallExpr(opcall))*/ )
949 h_operop->set("concat"); // overloaded comma is concat for sc types
950 //
951 //
952 }
953 }
954 int nargs = (h_operop->getopc() == hNode::hdlopsEnum::hPostfix ||
955 h_operop->getopc() == hNode::hdlopsEnum::hPrefix)
956 ? 1
957 : opcall->getNumArgs();
958 for (int i = 0; i < nargs; i++) {
959 hNodep save_h_ret = h_ret;
960 TraverseStmt(opcall->getArg(i));
961 if (h_ret == save_h_ret)
962 h_operop->child_list.push_back(new hNode(hNode::hdlopsEnum::hUnimpl));
963 else
964 h_operop->child_list.push_back(h_ret);
965 LLVM_DEBUG(llvm::dbgs()
966 << "operator call argument " << i << " follows\n");
967 LLVM_DEBUG(opcall->getArg(i)->dump(llvm::dbgs(), ast_context_));
968 }
969 h_ret = h_operop;
970 return false;
971 }
972
973 LLVM_DEBUG(llvm::dbgs() << "not yet implemented operator call expr, opc is "
974 << clang::getOperatorSpelling(opcall->getOperator())
975 << " num arguments " << opcall->getNumArgs()
976 << " skipping\n");
977 LLVM_DEBUG(opcall->dump(llvm::dbgs(), ast_context_));
978 h_ret = new hNode(hNode::hdlopsEnum::hUnimpl);
979 return false;
980 }
981
982 bool HDLBody::VisitMemberExpr(MemberExpr *memberexpr) {
983 bool founduserclass = false;
984 LLVM_DEBUG(llvm::dbgs() << "In TraverseMemberExpr\n");
985 string nameinfo = (memberexpr->getMemberNameInfo()).getName().getAsString();
986 LLVM_DEBUG(llvm::dbgs() << "name is " << nameinfo
987 << ", base and memberdecl trees follow\n");
988 LLVM_DEBUG(llvm::dbgs() << "base is \n");
989 LLVM_DEBUG(memberexpr->getBase()->dump(llvm::dbgs(), ast_context_););
990 LLVM_DEBUG(llvm::dbgs() << "memberdecl is " << memberexpr->getMemberDecl()
991 << " \n");
992 // if field decl, check if parent is a userdefined type XXXXXX
993 LLVM_DEBUG(memberexpr->getMemberDecl()->dump(llvm::dbgs()));
994 if (FieldDecl *fld = dyn_cast<FieldDecl>(memberexpr->getMemberDecl())) {
995 LLVM_DEBUG(llvm::dbgs() << "and field decl parent record pointer is "
996 << fld->getParent() << "\n");
997 const Type *classrectype = fld->getParent()->getTypeForDecl();
998 LLVM_DEBUG(llvm::dbgs() << "and field decl parent record type is "
999 << classrectype << "\n");
1000 if (isUserClass(classrectype)) {
1001 LLVM_DEBUG(llvm::dbgs()
1002 << "member expr, found user defined class in usertypes "
1003 << classrectype << "\n");
1004 founduserclass = true;
1005 }
1006 }
1007
1008 string thisref = founduserclass ? "hthis##" : "";
1009 // traverse the memberexpr base in case it is a nested structure
1010 hNodep old_h_ret = h_ret;
1011 TraverseStmt(memberexpr->getBase()); // get hcode for the base
1012 if (h_ret != old_h_ret) {
1013 if (h_ret->h_op == hNode::hdlopsEnum::hVarref) {
1014 // concatenate base name in front of field name
1015 hNodep memexprnode = new hNode(thisref + h_ret->h_name + "##" + nameinfo,
1016 hNode::hdlopsEnum::hVarref);
1017 delete h_ret;
1018 h_ret = memexprnode; // replace returned h_ret with single node, field
1019 // names concatenated
1020 return false;
1021 } else {
1022 LLVM_DEBUG(llvm::dbgs()
1023 << "Value returned from member expr base was not Varref\n");
1024 LLVM_DEBUG(h_ret->print(llvm::dbgs()));
1025 string newname = FindVname(memberexpr->getMemberDecl());
1026 LLVM_DEBUG(llvm::dbgs()
1027 << "member with base expr new name is " << newname << "\n");
1028 if ((newname == "")) { //&& (thismode != rmodinit)) { TRY this for new portbinding code
1029 LLVM_DEBUG(llvm::dbgs() << "vname lookup of memberdecl is null, "
1030 "assuming field reference\n");
1031 hNodep hfieldref = new hNode(hNode::hdlopsEnum::hFieldaccess);
1032 hfieldref->append(h_ret);
1033 hfieldref->append(
1034 new hNode(thisref + nameinfo, hNode::hdlopsEnum::hField));
1035 h_ret = hfieldref;
1036 return false;
1037 } else {
1038 hNodep memexprnode =
1039 new hNode(newname == "" ? thisref + nameinfo : thisref + newname,
1040 hNode::hdlopsEnum::hVarref);
1041 memexprnode->child_list.push_back(h_ret);
1042 h_ret = memexprnode;
1043 return false;
1044 }
1045 }
1046 }
1047
1048 string newname = FindVname(memberexpr->getMemberDecl());
1049 LLVM_DEBUG(llvm::dbgs() << "member expr new name is " << newname << "\n");
1050
1051 h_ret = new hNode(newname.empty() ? thisref + nameinfo : thisref + newname,
1052 hNode::hdlopsEnum::hVarref);
1053
1054 return false;
1055 }
1056
1057 bool HDLBody::VisitCallExpr(CallExpr *callexpr) {
1058 hNodep hcall; // = new hNode(hNode::hdlopsEnum::hMethodCall);
1059 hNodep save_hret = h_ret;
1060
1061 if (isa<FunctionDecl>(callexpr->getCalleeDecl()) &&
1062 ((FunctionDecl *)callexpr->getCalleeDecl())->isConstexpr()) {
1063 Expr::EvalResult res;
1064 if (callexpr->EvaluateAsRValue(
1065 res, callexpr->getCalleeDecl()->getASTContext())) {
1066 h_ret = new hNode(systemc_clang::utils::apint::toString(res.Val.getInt()),
1067 hNode::hdlopsEnum::hLiteral);
1068 return false;
1069 }
1070 }
1071
1072 TraverseStmt(callexpr->getCallee());
1073 // unlike methodcall, the function call name will hopefully resolve to a
1074 // declref. in traversedeclref, we create the hnode for the function call
1075 if ((h_ret !=
1076 save_hret) // &&
1077 //(h_ret->getopc() == hNode::hdlopsEnum::hMethodCall)) {
1078 ) {
1079 hcall = h_ret;
1080 } else {
1081 hcall = new hNode(
1082 hNode::hdlopsEnum::hMethodCall); // function name was more complicated
1083 hcall->child_list.push_back(h_ret);
1084 }
1085 for (auto arg : callexpr->arguments()) {
1086 hNodep sret = h_ret;
1087 TraverseStmt(arg);
1088 if (h_ret != sret) {
1089 hcall->child_list.push_back(h_ret);
1090 }
1091 }
1092 h_ret = hcall;
1093 LLVM_DEBUG(llvm::dbgs() << "found a call expr"
1094 << " AST follows\n ");
1095 LLVM_DEBUG(callexpr->dump(llvm::dbgs(), ast_context_););
1096 return false;
1097 }
1098
1099 bool HDLBody::VisitIfStmt(IfStmt *ifs) {
1100 hNodep h_ifstmt, h_ifc = NULL, h_ifthen = NULL, h_ifelse = NULL;
1101 h_ifstmt = new hNode(hNode::hdlopsEnum::hIfStmt);
1102 if (ifs->getConditionVariable()) {
1103 // Variable declarations are not allowed in if conditions
1104 LLVM_DEBUG(llvm::dbgs() << "Variable declarations are not allowed in if "
1105 "conditions, skipping\n");
1106 return false;
1107 } else {
1108 TraverseStmt(ifs->getCond());
1109 h_ifc = h_ret;
1110 }
1111 TraverseStmt(ifs->getThen());
1112 if (h_ret != h_ifc) // unchanged if couldn't translate the then clause
1113 h_ifthen = h_ret;
1114
1115 if (ifs->getElse()) {
1116 TraverseStmt(ifs->getElse());
1117 if ((h_ret != h_ifc) && (h_ret != h_ifthen)) h_ifelse = h_ret;
1118 }
1119 h_ifstmt->child_list.push_back(h_ifc);
1120 h_ifstmt->child_list.push_back(h_ifthen);
1121 if (h_ifelse) h_ifstmt->child_list.push_back(h_ifelse);
1122 h_ret = h_ifstmt;
1123 return false;
1124 }
1125
1126 bool HDLBody::VisitForStmt(ForStmt *fors) {
1127 hNodep h_forstmt, h_forinit, h_forcond, h_forinc, h_forbody;
1128 LLVM_DEBUG(llvm::dbgs() << "For stmt\n");
1129 h_forstmt = new hNode(hNode::hdlopsEnum::hForStmt);
1130 if ((fors->getInit() != NULL) && (isa<CompoundStmt>(fors->getInit())))
1131 LLVM_DEBUG(llvm::dbgs()
1132 << "Compound stmt not handled in for init, skipping\n");
1133 else {
1134 if ((fors->getInit() != NULL) && isa<DeclStmt>(fors->getInit())) {
1135 LLVM_DEBUG(llvm::dbgs() << "for init is a decl stmt\n");
1136 LLVM_DEBUG((fors->getInit())->dump(llvm::dbgs(), ast_context_));
1137 }
1138 TraverseStmt(fors->getInit());
1139 }
1140 h_forinit = (h_ret == NULL) ? new hNode(hNode::hdlopsEnum::hNoop)
1141 : h_ret; // null if in place var decl
1142 TraverseStmt(fors->getCond());
1143 h_forcond = (h_ret == NULL) ? new hNode(hNode::hdlopsEnum::hNoop)
1144 : h_ret; // null if in place if no cond
1145 TraverseStmt(fors->getInc());
1146 h_forinc =(h_ret == NULL) ? new hNode(hNode::hdlopsEnum::hNoop)
1147 : h_ret; // null if in place no inc
1148 LLVM_DEBUG(llvm::dbgs() << "For loop body\n");
1149 LLVM_DEBUG(fors->getBody()->dump(llvm::dbgs(), ast_context_););
1150 TraverseStmt(fors->getBody());
1151 h_forbody = h_ret;
1152 h_forstmt->child_list.push_back(h_forinit);
1153 h_forstmt->child_list.push_back(h_forcond);
1154 h_forstmt->child_list.push_back(h_forinc);
1155 h_forstmt->child_list.push_back(h_forbody);
1156 h_ret = h_forstmt;
1157
1158 return false;
1159 }
1160
1161 bool HDLBody::ProcessSwitchCase(SwitchCase *sc) {
1162 LLVM_DEBUG(llvm::dbgs() << "In ProcessSwitchCase\n");
1163 hNodep hcasep;
1164 hNodep old_hret = h_ret;
1165 if (isa<DefaultStmt>(sc)) {
1166 LLVM_DEBUG(llvm::dbgs() << "Found default stmt in switchcase\n");
1167 hcasep = new hNode(hNode::hdlopsEnum::hSwitchDefault);
1168 TraverseStmt((DefaultStmt *)sc->getSubStmt());
1169 } else {
1170 LLVM_DEBUG(llvm::dbgs() << "Found case stmt in switchcase\n");
1171 hcasep = new hNode(hNode::hdlopsEnum::hSwitchCase);
1172 if (ConstantExpr *expr =
1173 dyn_cast<ConstantExpr>(((CaseStmt *)sc)->getLHS())) {
1174 llvm::APSInt val = expr->getResultAsAPSInt();
1175 hcasep->child_list.push_back(
1177 hNode::hdlopsEnum::hLiteral));
1178 }
1179 TraverseStmt((CaseStmt *)sc->getSubStmt());
1180 }
1181 if (h_ret != old_hret) {
1182 hcasep->child_list.push_back(h_ret);
1183 } else {
1184 hcasep->child_list.push_back(new hNode(hNode::hdlopsEnum::hUnimpl));
1185 }
1186 h_ret = hcasep;
1187 return true;
1188 }
1189
1190 bool HDLBody::VisitSwitchStmt(SwitchStmt *switchs) {
1191 hNodep h_switchstmt;
1192 LLVM_DEBUG(llvm::dbgs() << "Switch stmt body -----\n");
1193 LLVM_DEBUG(switchs->getBody()->dump(llvm::dbgs(), ast_context_););
1194 LLVM_DEBUG(llvm::dbgs() << "End Switch stmt body -----\n");
1195
1196 h_switchstmt = new hNode(hNode::hdlopsEnum::hSwitchStmt);
1197 // Stmt * swinit = dyn_cast<Stmt>(switchs->getInit());
1198 // if (swinit) {
1199 // LLVM_DEBUG(llvm::dbgs() << "switch init not handled, skipping\n");
1200 //}
1201 hNodep old_ret = h_ret;
1202 TraverseStmt(switchs->getCond());
1203 if (h_ret != old_ret) {
1204 h_switchstmt->child_list.push_back(h_ret);
1205 } else
1206 h_switchstmt->child_list.push_back(new hNode(hNode::hdlopsEnum::hUnimpl));
1207
1208 old_ret = h_ret;
1209
1210 TraverseStmt(switchs->getBody());
1211
1212 if (h_ret != old_ret) {
1214 // here need extra code to append non switchcase hcode into previous
1215 // switchcase group, which happens if the switchcase isn't wrapped in
1216 // a compound statement {}.
1217
1218 h_switchstmt->child_list.push_back(h_ret);
1219 }
1220
1221 // for (SwitchCase *sc = switchs->getSwitchCaseList(); sc != NULL;
1222 // sc = sc->getNextSwitchCase()) {
1223 // LLVM_DEBUG(llvm::dbgs() << "Switch case\n");
1224 // LLVM_DEBUG(sc->dump(llvm::dbgs()));
1225 // if (isa<DefaultStmt>(sc)) {
1226 // LLVM_DEBUG(llvm::dbgs() << "Found default stmt in case\n");
1227 // }
1228 // else {
1229 // ProcessSwitchCase(sc);
1230 // h_switchstmt->child_list.push_back(h_ret);
1231 // }
1232 // }
1233 // TraverseStmt(switchs->getBody());
1234 // h_switchbody = h_ret;
1235 // h_switchstmt->child_list.push_back(h_switchinit);
1236
1237 // h_switchstmt->child_list.push_back(h_switchbody);
1238 h_ret = h_switchstmt;
1239
1240 return false;
1241 }
1242
1243 bool HDLBody::VisitWhileStmt(WhileStmt *whiles) {
1244 hNodep h_whilestmt, h_whilecond, h_whilebody;
1245 LLVM_DEBUG(llvm::dbgs() << "While stmt\n");
1246 h_whilestmt = new hNode(hNode::hdlopsEnum::hWhileStmt);
1247 if (whiles->getConditionVariable()) {
1248 LLVM_DEBUG(
1249 llvm::dbgs()
1250 << "Variable declarations not handled in while condition, skipping\n");
1251 } else {
1252 // Get condition
1253 TraverseStmt(whiles->getCond());
1254 h_whilecond = h_ret;
1255 }
1256
1257 // Get the body
1258 TraverseStmt(whiles->getBody());
1259 h_whilebody = h_ret;
1260 h_whilestmt->child_list.push_back(h_whilecond);
1261 h_whilestmt->child_list.push_back(h_whilebody);
1262 h_ret = h_whilestmt;
1263
1264 return false;
1265 }
1266
1267 // unfortunately clang ast doesn't do inheritance on the classes
1268 // so code is duplicated
1269
1270 bool HDLBody::VisitDoStmt(DoStmt *whiles) {
1271 hNodep h_whilestmt, h_whilecond, h_whilebody;
1272 LLVM_DEBUG(llvm::dbgs() << "Do stmt\n");
1273 h_whilestmt = new hNode(hNode::hdlopsEnum::hDoStmt);
1274 // Get condition
1275 TraverseStmt(whiles->getCond());
1276 h_whilecond = h_ret;
1277
1278 // Get the body
1279 TraverseStmt(whiles->getBody());
1280 h_whilebody = h_ret;
1281 h_whilestmt->child_list.push_back(h_whilecond);
1282 h_whilestmt->child_list.push_back(h_whilebody);
1283 h_ret = h_whilestmt;
1284
1285 return false;
1286 }
1287
1288 // these two functions are so clumsy. The data structure should handle
1289 // multi-level symbol tables.
1290
1291 string HDLBody::FindVname(NamedDecl *vard) {
1292 string newname = vname_map.find_entry_newn(
1293 vard, thismode == rthread); // set referenced bit if in thread
1294 if (newname == "")
1296 vard, thismode == rthread); // set referenced bit if in thread
1297 return newname;
1298 }
1299
1300 string HDLBody::FindFname(FunctionDecl *funcd) {
1301 string newname = methodecls.find_entry_newn(
1302 funcd, thismode == rthread); // set referenced bit if in thread
1303 if (newname == "")
1305 funcd, thismode == rthread); // set referenced bit if in thread
1306 return newname;
1307 }
1308
1310 LLVM_DEBUG(llvm::dbgs() << "Vname Dump\n");
1311 // for (auto const &var : vname_map.hdecl_name_map) {
1312 for (auto const &var : vname_map) {
1313 LLVM_DEBUG(llvm::dbgs() << "(" << var.first << "," << var.second.oldn
1314 << ", " << var.second.newn << ")\n");
1315 if (add_info && (var.second.newn.find(gvar_prefix) == std::string::npos)) {
1316 // if this isn't a global variable
1317 // mark this var decl as a renamed var decl and tack on the original name
1318 // used in later processing of hcode
1319 var.second.h_vardeclp->h_op = hNode::hdlopsEnum::hVardeclrn;
1320 var.second.h_vardeclp->child_list.push_back(
1321 new hNode(var.second.oldn, hNode::hdlopsEnum::hLiteral));
1322 }
1323 if (var.second.newn.find(gvar_prefix) == std::string::npos)
1324 // don't add global variable to local list
1325 hvns->child_list.push_back(var.second.h_vardeclp);
1326 }
1327 }
1328
1329
1331 // break up chain of assignments a = b = c = d = 0;
1332 // at entry there is a chain of at least two: a = b = 0;
1333
1334 hNodep hassignchain = new hNode(hNode::hdlopsEnum::hCStmt);
1335 hNodep htmp = hinp; // (= a subtree)
1336 do {
1337 hNodep htmp2 = htmp->child_list[1]; // (= b subtree)
1338 htmp->child_list[1] = htmp2->child_list[0]; // (= a b)
1339 hassignchain->child_list.push_back(htmp);
1340 htmp = htmp2; // (= b subtree)
1341 } while (isAssignOp(htmp->child_list[1]));
1342 hassignchain->child_list.push_back(htmp);
1343 std::reverse(hassignchain->child_list.begin(),
1344 hassignchain->child_list.end());
1345 return hassignchain;
1346 }
1347 void HDLBody::GetWaitArg(hNodep &h_callp, Expr *callarg) {
1348 int64_t waitarg = 0;
1349 if (callarg->isEvaluatable(ast_context_)) {
1350 clang::Expr::EvalResult result{};
1351 callarg->EvaluateAsInt(result, ast_context_);
1352 waitarg = result.Val.getInt().getExtValue();
1353 llvm::dbgs() << " wait arg val: " << waitarg << "\n";
1354 }
1355 hNodep arglit = new hNode( std::to_string(waitarg), hNode::hdlopsEnum::hLiteral);
1356 h_callp->append(arglit);
1357 }
1358
1360 if (hswitchstmt->child_list.size() == 0) return;
1361 hNodep hprev = hswitchstmt->child_list[0]; // should be a switchcase node
1362 for (int i = 1; i < hswitchstmt->child_list.size(); i++) {
1363 if ((hswitchstmt->child_list[i]->getopc() !=
1364 hNode::hdlopsEnum::hSwitchCase) &&
1365 (hswitchstmt->child_list[i]->getopc() !=
1366 hNode::hdlopsEnum::hSwitchDefault)) {
1367 hNodep htmp = new hNode((hswitchstmt->child_list[i])->getname(),
1368 (hswitchstmt->child_list[i])->getopc());
1369 htmp->child_list = (hswitchstmt->child_list[i])->child_list;
1370 hprev->append(htmp);
1371 hswitchstmt->child_list[i]->set(hNode::hdlopsEnum::hLast);
1372 } else
1373 hprev = hswitchstmt->child_list[i];
1374 }
1375 hswitchstmt->child_list.erase(
1376 std::remove_if(
1377 hswitchstmt->child_list.begin(), hswitchstmt->child_list.end(),
1378 [](hNodep hp) { return hp->getopc() == hNode::hdlopsEnum::hLast; }),
1379 hswitchstmt->child_list.end());
1380 }
1381
1382 // CXXMethodDecl *HDLBody::getEMD() {
1383 // return _emd;
1384 // }
1385} // namespace systemc_hdl
void print(llvm::raw_ostream &modelout=llvm::outs(), unsigned int indnt=2)
Definition HDLType.h:45
usertype_info_t usertype_info
Definition HDLType.h:44
void SCtype2hcode(string prefix, Tree< TemplateType > *template_argtp, std::vector< llvm::APInt > *arr_sizes, hNode::hdlopsEnum h_op, hNodep &h_info)
Definition HDLType.cpp:29
hdlopsEnum h_op
Definition hNode.h:107
hdlopsEnum getopc()
Definition hNode.h:173
string getname()
Definition hNode.h:169
string h_name
Definition hNode.h:106
void set(hdlopsEnum h, string s="")
Definition hNode.h:148
std::vector< hNodep > child_list
Definition hNode.h:109
void append(hNodep hnew)
Definition hNode.h:157
void print(llvm::raw_ostream &modelout=llvm::outs(), unsigned int indnt=2)
Definition hNode.h:188
void print(llvm::raw_ostream &modelout=llvm::outs(), unsigned int indnt=2)
Definition hNode.h:617
method_object_map_t methodobjtypemap
Definition hNode.h:612
void add_entry(T declp, string old_name, hNodep hnp)
Definition hNode.h:539
void set_prefix(string prefix)
Definition hNode.h:573
string get_prefix()
Definition hNode.h:575
string find_entry_newn(T declp, bool set_ref=false)
Definition hNode.h:552
bool isSCFunc(const string &tstring)
Definition hNode.h:418
bool isSCMacro(const std::string &str_in)
Definition hNode.h:430
bool isSCBuiltinType(const string &tstring, const Type *typ=NULL)
Definition hNode.h:389
bool isSCType(const string &tstring, const clang::Type *typ=NULL)
Definition hNode.h:438
static void make_ident(string &nm)
Definition hNode.h:254
Tree< TemplateType > * getTemplateArgTreePtr()
void Enumerate(const clang::Type *type)
const ASTContext & ast_context_
Definition HDLBody.h:130
bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *opcall)
Definition HDLBody.cpp:886
bool VisitBinaryOperator(BinaryOperator *expr)
Definition HDLBody.cpp:468
HDLBodyMode thismode
Definition HDLBody.h:102
bool isLogicalOp(clang::OverloadedOperatorKind opc)
Definition HDLBody.cpp:871
bool VisitCaseStmt(CaseStmt *stmt)
Definition HDLBody.cpp:234
string FindFname(FunctionDecl *funcd)
Definition HDLBody.cpp:1300
hdecl_name_map_t vname_map
Definition HDLBody.h:88
overridden_method_map_t & overridden_method_map_
Definition HDLBody.h:90
hfunc_name_map_t methodecls
Definition HDLBody.h:84
bool VisitCompoundStmt(CompoundStmt *compoundStmt)
Definition HDLBody.cpp:284
bool VisitDefaultStmt(DefaultStmt *stmt)
Definition HDLBody.cpp:257
void NormalizeSwitchStmt(hNodep hswitchbody)
Definition HDLBody.cpp:1359
void GetWaitArg(hNodep &h_callp, Expr *callarg)
Definition HDLBody.cpp:1347
bool VisitConditionalOperator(ConditionalOperator *expr)
Definition HDLBody.cpp:558
bool VisitReturnStmt(ReturnStmt *stmt)
Definition HDLBody.cpp:224
bool VisitDeclStmt(DeclStmt *declstmt)
Definition HDLBody.cpp:315
bool ProcessVarDecl(VarDecl *vardecl)
Definition HDLBody.cpp:332
bool VisitMemberExpr(MemberExpr *memberexpr)
Definition HDLBody.cpp:982
string generate_vname(string nm)
Definition HDLBody.h:124
bool VisitUnaryOperator(UnaryOperator *expr)
Definition HDLBody.cpp:530
bool isUserClass(const Type *classrectype)
Definition HDLBody.h:107
bool VisitArraySubscriptExpr(ArraySubscriptExpr *expr)
Definition HDLBody.cpp:685
void AddVnames(hNodep &hvns)
Definition HDLBody.cpp:1309
bool VisitSwitchStmt(SwitchStmt *switchs)
Definition HDLBody.cpp:1190
bool TraverseStmt(Stmt *stmt)
Definition HDLBody.cpp:111
HDLBody(clang::DiagnosticsEngine &diag_engine, const ASTContext &ast_context, hdecl_name_map_t &mod_vname_map, hfunc_name_map_t &allmethodecls, overridden_method_map_t &overridden_method_map)
Definition HDLBody.cpp:63
hdecl_name_map_t & mod_vname_map_
Definition HDLBody.h:96
hfunc_name_map_t & allmethodecls_
Definition HDLBody.h:103
bool isAssignOp(hNodep hp)
Definition HDLBody.h:115
bool VisitWhileStmt(WhileStmt *whiles)
Definition HDLBody.cpp:1243
bool VisitContinueStmt(ContinueStmt *stmt)
Definition HDLBody.cpp:277
HDLType * HDLt_userclassesp_
Definition HDLBody.h:105
void Run(Stmt *stmt, hNodep &h_top, HDLBodyMode runmode, HDLType *HDLt_userclassesp=NULL)
Definition HDLBody.cpp:75
hNodep NormalizeAssignmentChain(hNodep hinp)
Definition HDLBody.cpp:1330
bool VisitInitListExpr(InitListExpr *stmt)
Definition HDLBody.cpp:214
bool ProcessSwitchCase(SwitchCase *cases)
Definition HDLBody.cpp:1161
bool VisitDoStmt(DoStmt *whiles)
Definition HDLBody.cpp:1270
bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *b)
Definition HDLBody.cpp:581
bool VisitIfStmt(IfStmt *ifs)
Definition HDLBody.cpp:1099
bool VisitCallExpr(CallExpr *callexpr)
Definition HDLBody.cpp:1057
bool VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *stmt)
Definition HDLBody.cpp:199
bool VisitBreakStmt(BreakStmt *stmt)
Definition HDLBody.cpp:270
string FindVname(NamedDecl *vard)
Definition HDLBody.cpp:1291
bool VisitCXXMemberCallExpr(CXXMemberCallExpr *callexpr)
Definition HDLBody.cpp:703
bool VisitDeclRefExpr(DeclRefExpr *expr)
Definition HDLBody.cpp:589
bool VisitForStmt(ForStmt *fors)
Definition HDLBody.cpp:1126
bool VisitIntegerLiteral(IntegerLiteral *lit)
Definition HDLBody.cpp:573
Definition hNode.h:24
std::unordered_map< const CXXMethodDecl *, const CXXMethodDecl * > overridden_method_map_t
Definition hNode.h:628
ArraySizesType getConstantArraySizes(const clang::ValueDecl *fd)
bool isCXXMemberCallExprSystemCCall(const clang::CallExpr *ce, const std::vector< llvm::StringRef > &names)
bool isInNamespace(const clang::ValueDecl *fd, const std::vector< llvm::StringRef > &names)
std::string toString(const T &i)
Definition APIntUtils.h:14
userrectype_map_t userrectypes
Definition HDLType.h:28