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 // create head node for the vardecl
336 hNodep h_varlist = new hNode(hNode::hdlopsEnum::hPortsigvarlist);
337
338 QualType q = vardecl->getType();
339 const Type *tp = q.getTypePtr();
340 LLVM_DEBUG(llvm::dbgs() << "ProcessVarDecl type name is " << q.getAsString()
341 << "\n");
343
344 te->Enumerate(tp);
345 HDLType HDLt;
346 std::vector<llvm::APInt> array_sizes =
348 HDLt.SCtype2hcode(generate_vname(vardecl->getName().str()),
349 te->getTemplateArgTreePtr(), &array_sizes,
350 hNode::hdlopsEnum::hVardecl, h_varlist);
351
352 h_ret = NULL;
353
354 if (h_varlist->child_list.size() == 0) return true;
355
356 hNodep h_vardecl = h_varlist->child_list.back();
357 vname_map.add_entry(vardecl, vardecl->getName().str(), h_vardecl);
358
359 const Type *tstp;
360 bool isuserdefinedclass = false;
361 if (HDLt.usertype_info.userrectypes.size() > 0) {
362 tstp = (((te->getTemplateArgTreePtr())->getRoot())->getDataPtr())
363 ->getTypePtr();
364 /*
365 LLVM_DEBUG(
366 llvm::dbgs()
367 << "ProcessVarDecl init of user class, tstp in processvardecl is "
368 << tstp << " isscbytype says " << lutil.isSCByType(tstp) << "\n");
369 */
370 LLVM_DEBUG(HDLt.print(llvm::dbgs()));
371 auto recmapiter = HDLt.usertype_info.userrectypes.find(tstp);
372 if (recmapiter !=
374 .end()) { // && (recmapiter->second.find("sc_process_handle")==
375 // string::npos)) {
376 isuserdefinedclass = true;
377 // varinitp->set( hNode::hdlopsEnum::hMethodCall, recmapiter->second);
378
379 /*
380
381 // we know it is a userdefined class, now handle the constructor initializer
382
383 if (lutil.isSCType(exp->getType().getTypePtr())) {
384 LLVM_DEBUG(llvm::dbgs() << "CXXConstructExpr type is sctype " << exp->getType().getAsString()<< "\n");
385 }
386 else {
387 if ((exp->getNumArgs() == 0) || //
388 (exp->getNumArgs()>0) && !isa<CXXDefaultArgExpr>(exp->getArg(0))) // non-sctype with a true init
389 LLVM_DEBUG(llvm::dbgs() << "CXXConstructExpr type is not sctype " << exp->getType().getAsString()
390 << "num args is " << exp->getNumArgs() << "\n");
391 LLVM_DEBUG(exp->dump(llvm::dbgs(), ast_context_));
392 }
393 */
394
395
396 }
397 }
398
399 string qualmethodname = "ConstructorMethod";
400 if (Expr *declinit = vardecl->getInit()) {
401 LLVM_DEBUG(llvm::dbgs() << "ProcessVarDecl has an init: \n");
402 LLVM_DEBUG(declinit->dump(llvm::dbgs(), ast_context_));
403 CXXConstructExpr *tmpdeclinit = dyn_cast<CXXConstructExpr>(declinit);
404 if (isuserdefinedclass && (tmpdeclinit != NULL)) {
405 // For user-defined classes:
406 // If there is an initializer, define the method for the initializer and
407 // insert a call to the method. If there are parameters, they need to be
408 // supplied. if it is a user-defined class defined outside an sc_module,
409 // the "this" parameter needs to be supplied as first parameter to the
410 // constructor method.
411
412 const CXXConstructorDecl *cnstrdcl = tmpdeclinit->getConstructor();
413 string methodname = cnstrdcl->getNameAsString();
414 qualmethodname = cnstrdcl->getQualifiedNameAsString();
415 lutil.make_ident(qualmethodname);
416 LLVM_DEBUG(llvm::dbgs() << "ConstructorDecl " << methodname << ", "
417 << qualmethodname << " for var follows\n");
418 LLVM_DEBUG(cnstrdcl->dump());
419 // add method decl for constructor
420 hNodep h_callp =
421 new hNode(qualmethodname, hNode::hdlopsEnum::hMethodCall);
422 const std::vector<StringRef> tmpmodstr{"sc_module"};
423 if (sc_ast_matchers::utils::isInNamespace(tstp, tmpmodstr)) {
424 LLVM_DEBUG(llvm::dbgs()
425 << "user-defined class is defined in sc module\n");
426 } else
427 h_callp->append(
428 new hNode(FindVname(vardecl), hNode::hdlopsEnum::hVarref));
429 methodecls.add_entry((CXXMethodDecl *)cnstrdcl, qualmethodname, h_callp);
430 methodecls.methodobjtypemap[(const CXXMethodDecl *)cnstrdcl] = tstp;
431 TraverseStmt(tmpdeclinit);
432 if (h_ret) {
433 h_callp->append(h_ret);
434 }
435 h_ret = h_callp;
436 //}
437 return true;
438 }
439
440 TraverseStmt(declinit);
441
442 if (h_ret) {
443 hNodep varinitp = new hNode(hNode::hdlopsEnum::hVarAssign);
444 varinitp->child_list.push_back(
445 new hNode(FindVname(vardecl), hNode::hdlopsEnum::hVarref));
446 varinitp->child_list.push_back(h_ret);
447 h_ret = varinitp;
448 }
449 }
450 return true;
451 }
452
453 bool HDLBody::VisitBinaryOperator(BinaryOperator *expr) {
454 // ... handle expr. Can use
455 // bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx,
456 // SourceLocation *Loc = nullptr,
457 // bool isEvaluated = true) const;
458 // However, might be expensive to check on every binary operator
459
460 hNodep h_binop =
461 new hNode(expr->getOpcodeStr().str(),
462 hNode::hdlopsEnum::hBinop); // node to hold binop expr
463
464 string opcodestr = expr->getOpcodeStr().str();
465 string exprtypstr = expr->getType().getAsString();
466 LLVM_DEBUG(llvm::dbgs() << "in TraverseBinaryOperator, opcode is "
467 << opcodestr << "\n");
468 // lutil.checktypematch(exprtypstr, expr->getType().getTypePtr(),
469 // lutil.bothofthem); //
470
471 // ========================== CHECK 1 =====================
472 // FIXME: Cleanup
473 /*
474 bool t11 =
475 ((opcodestr == ",") &&
476 (lutil.isSCType(exprtypstr, expr->getType().getTypePtr()) ||
477 lutil.isSCBuiltinType(exprtypstr, expr->getType().getTypePtr())));
478 bool t21 =
479 ((opcodestr == ",") && (lutil.isSCByType(expr->getType().getTypePtr())));
480
481 if (t11 != t21) {
482 llvm::dbgs() << "### CHECK1: t11 != t21\n";
483 assert(0); // llvm::dbgs() << t11/0;
484 // std::cin.get();
485 }
486 */
487 // ========================== END CHECK =====================
488 //
489 if ((opcodestr == ",") &&
490 (lutil.isSCType(exprtypstr, expr->getType().getTypePtr()) ||
491 lutil.isSCBuiltinType(exprtypstr, expr->getType().getTypePtr()))) {
492 // if ((opcodestr == ",") && (lutil.isSCType(expr->getType()){
493
494 // if ((opcodestr == ",") &&
495 // (lutil.isSCByType(expr->getType().getTypePtr()))){
496 LLVM_DEBUG(llvm::dbgs() << "found comma, with sc type, expr follows\n");
497 LLVM_DEBUG(expr->dump(llvm::dbgs(), ast_context_););
498 h_binop->set("concat");
499 }
500 TraverseStmt(expr->getLHS());
501 h_binop->child_list.push_back(h_ret);
502
503 hNodep save_h_ret = h_ret;
504 TraverseStmt(expr->getRHS());
505 if (h_ret == save_h_ret)
506 h_binop->child_list.push_back(new hNode(hNode::hdlopsEnum::hUnimpl));
507 else
508 h_binop->child_list.push_back(h_ret);
509
510 h_ret = h_binop;
511
512 return false;
513 }
514
515 bool HDLBody::VisitUnaryOperator(UnaryOperator *expr) {
516 LLVM_DEBUG(llvm::dbgs() << "in TraverseUnaryOperator expr node is \n");
517 LLVM_DEBUG(expr->dump(llvm::dbgs(), ast_context_););
518
519 auto opcstr = expr->getOpcode();
520
521 hNodep h_unop;
522
523 if ((expr->getOpcodeStr(opcstr).str() == "++") ||
524 (expr->getOpcodeStr(opcstr).str() == "--")) {
525 if (expr->isPostfix())
526 h_unop = new hNode(expr->getOpcodeStr(opcstr).str(),
527 hNode::hdlopsEnum::hPostfix);
528 else
529 h_unop = new hNode(expr->getOpcodeStr(opcstr).str(),
530 hNode::hdlopsEnum::hPrefix);
531 } else
532 h_unop = new hNode(expr->getOpcodeStr(opcstr).str(),
533 hNode::hdlopsEnum::hUnop); // node to hold unop expr
534
535 TraverseStmt(expr->getSubExpr());
536 h_unop->child_list.push_back(h_ret);
537
538 h_ret = h_unop;
539
540 return false;
541 }
542
543 bool HDLBody::VisitConditionalOperator(ConditionalOperator *expr) {
544 LLVM_DEBUG(llvm::dbgs() << "in VisitConditionalOperator expr node is \n");
545 LLVM_DEBUG(expr->dump(llvm::dbgs(), ast_context_););
546
547 hNodep h_condop = new hNode(hNode::hdlopsEnum::hCondop);
548 TraverseStmt(expr->getCond());
549 h_condop->child_list.push_back(h_ret); // need to check if it's null or didn't get changed
550 TraverseStmt(expr->getTrueExpr());
551 h_condop->child_list.push_back(h_ret); // need to check if it's null or didn't get changed
552 TraverseStmt(expr->getFalseExpr());
553 h_condop->child_list.push_back(h_ret); // need to check if it's null or didn't get changed
554 h_ret = h_condop;
555 return false;
556 }
557
558 bool HDLBody::VisitIntegerLiteral(IntegerLiteral *lit) {
559 LLVM_DEBUG(llvm::dbgs() << "In integerliteral\n");
560 string s = systemc_clang::utils::apint::toString(lit->getValue());
561 h_ret = new hNode(s, hNode::hdlopsEnum::hLiteral);
562
563 return false;
564 }
565
566 bool HDLBody::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *b) {
567 LLVM_DEBUG(llvm::dbgs() << "In boollitexpr\n");
568 bool v = b->getValue();
569 h_ret = new hNode(v ? "1" : "0", hNode::hdlopsEnum::hLiteral);
570
571 return false;
572 }
573
574 bool HDLBody::VisitDeclRefExpr(DeclRefExpr *expr) {
575 // ... handle expr
576 LLVM_DEBUG(llvm::dbgs() << "In TraverseDeclRefExpr\n");
577
578 ValueDecl *value = expr->getDecl();
579 if (isa<EnumConstantDecl>(value)) {
580 EnumConstantDecl *cd = (EnumConstantDecl *)value;
581 LLVM_DEBUG(llvm::dbgs()
582 << "got enum constant value " << cd->getInitVal() << "\n");
583 h_ret = new hNode(systemc_clang::utils::apint::toString(cd->getInitVal()),
584 hNode::hdlopsEnum::hLiteral);
585 return false;
586 }
587
588 // get a name
589
590 string name = (expr->getNameInfo()).getName().getAsString();
591 LLVM_DEBUG(llvm::dbgs() << "name is " << name << "\n");
592
593 // if this is variable reference has a constant initializer, return that value
594 if (isa<VarDecl>(value) && ((VarDecl *)value)->isConstexpr()) {
595 VarDecl *vard = (VarDecl *)value;
596 Expr *einit = vard->getInit();
597 clang::Expr::EvalResult result;
598 if (einit->EvaluateAsInt(result, vard->getASTContext())) {
599 h_ret =
600 new hNode(systemc_clang::utils::apint::toString(result.Val.getInt()),
601 hNode::hdlopsEnum::hLiteral);
602 return false;
603 }
604 }
605 if (isa<FunctionDecl>(value)) {
606 // ============= CHECK ================
607 /*
608 bool t1 = !(lutil.isSCFunc(name) || lutil.isSCMacro(name));
609 bool t2 = !lutil.isSCByCallExpr(expr);
610
611 if (t1 != t2) {
612 llvm::dbgs() << "@@@@ CHECK isSCFunc failed " << t1 << " t2 " << t2
613 << " name " << name << "\n";
614 assert(0);
615 // std::cin.get();
616 }
617 */
618 // ============= END CHECK ================
619 if (!(lutil.isSCFunc(name) ||
620 lutil.isSCMacro(name))) { // similar to method call, skip builtin
621 FunctionDecl *funval = (FunctionDecl *)value;
622
623 string qualfuncname{value->getQualifiedNameAsString()};
624 lutil.make_ident(qualfuncname);
625 if (add_info)
626 qualfuncname +=
627 ":" + name; // !!! add unqualified name for future hcode processing
628 // methodecls[qualfuncname] =
629 // (FunctionDecl *)value; // add to list of "methods" to be generated
630 // methodecls.insert(make_pair(qualfuncname, (FunctionDecl *)value));
631
632 // create the call expression
633 hNodep hfuncall = new hNode(qualfuncname, hNode::hdlopsEnum::hMethodCall);
634 // don't add this method to methodecls if processing modinit
635 if (!add_info) {
636 string tmpname = FindFname((FunctionDecl *)value);
637 if (tmpname == "") { // isn't in local or global symbol table
638 LLVM_DEBUG(llvm::dbgs() << "adding method " << qualfuncname
639 << " with pointer " << value << " \n");
640 LLVM_DEBUG(methodecls.print(llvm::dbgs()));
641 methodecls.add_entry((CXXMethodDecl *)funval, qualfuncname, hfuncall);
642 } else
643 hfuncall->set(tmpname);
644 }
645 h_ret = hfuncall;
646 return false;
647 } else { // here it is an SCFunc
648 string typname = (expr->getType()).getAsString();
649 if (typname.find("sc_dt::sc_concat") != std::string::npos) {
650 // found concat function call
651 hNodep hconcat = new hNode(name, hNode::hdlopsEnum::hBinop);
652 h_ret = hconcat;
653 return false;
654 }
655 h_ret = new hNode(name, hNode::hdlopsEnum::hBuiltinFunction);
656 return false;
657 // may have other special functions to recognize later
658 }
659 }
660
661 string newname = FindVname(expr->getDecl());
662 LLVM_DEBUG(llvm::dbgs() << "new name is " << newname << "\n");
663 LLVM_DEBUG(expr->getDecl()->dump(llvm::dbgs()));
664
665 h_ret =
666 new hNode(newname.empty() ? name : newname, hNode::hdlopsEnum::hVarref);
667 return false;
668 }
669
670 bool HDLBody::VisitArraySubscriptExpr(ArraySubscriptExpr *expr) {
671 LLVM_DEBUG(llvm::dbgs()
672 << "In TraverseArraySubscriptExpr, base, idx, tree follow\n");
673 LLVM_DEBUG(llvm::dbgs() << "base:\n");
674 LLVM_DEBUG(expr->getBase()->dump(llvm::dbgs(), ast_context_));
675 LLVM_DEBUG(llvm::dbgs() << "idx:\n");
676 LLVM_DEBUG(expr->getIdx()->dump(llvm::dbgs(), ast_context_));
677 LLVM_DEBUG(llvm::dbgs() << "tree:\n");
678 LLVM_DEBUG(expr->dump(llvm::dbgs(), ast_context_));
679 hNodep h_arrexpr = new hNode("ARRAYSUBSCRIPT", hNode::hdlopsEnum::hBinop);
680 TraverseStmt(expr->getLHS());
681 h_arrexpr->child_list.push_back(h_ret);
682 TraverseStmt(expr->getRHS());
683 h_arrexpr->child_list.push_back(h_ret);
684 h_ret = h_arrexpr;
685 return false;
686 }
687
688 bool HDLBody::VisitCXXMemberCallExpr(CXXMemberCallExpr *callexpr) {
689 bool is_explicitly_overridden = false;
690 // this doesn't seem to help
691 LangOptions LangOpts;
692
693 LangOpts.CPlusPlus = true;
694 const PrintingPolicy Policy(LangOpts);
695
696 LLVM_DEBUG(llvm::dbgs()
697 << "In TraverseCXXMemberCallExpr, printing implicit object arg\n");
698 // Retrieves the implicit object argument for the member call.
699 // For example, in "x.f(5)", this returns the sub-expression "x".
700
701 Expr *rawarg = (callexpr->getImplicitObjectArgument());
702 LLVM_DEBUG(llvm::dbgs() << "raw implicitobjectargument follows\n");
703 LLVM_DEBUG(rawarg->dump(llvm::dbgs(), ast_context_));
704
705 Expr *objarg = (callexpr->getImplicitObjectArgument())->IgnoreImplicit();
706 LLVM_DEBUG(
707 llvm::dbgs() << "implicitobjectargument, ignore implicit follows\n");
708 LLVM_DEBUG(objarg->dump(llvm::dbgs(), ast_context_));
709 CXXRecordDecl *cdecl = callexpr->getRecordDecl();
710 const Type *typeformethodclass = cdecl->getTypeForDecl();
711 LLVM_DEBUG(llvm::dbgs() << "Type pointer from RecordDecl is "
712 << typeformethodclass << "\n");
713
714 QualType argtyp;
715 if (dyn_cast<ImplicitCastExpr>(rawarg)) { // cast to a specfic type
716 argtyp = rawarg->getType();
717 is_explicitly_overridden = true;
718 } else {
719 argtyp = objarg->getType();
720 }
721 LLVM_DEBUG(llvm::dbgs() << "type of x in x.f(5) is "
722 << argtyp.getAsString(Policy) << "\n");
723 QualType objtyp = callexpr->getObjectType();
724 LLVM_DEBUG(llvm::dbgs() << "... and object type is "
725 << objtyp.getAsString(Policy) << "\n");
726 string methodname = "NoMethod", qualmethodname = "NoQualMethod";
727
728 CXXMethodDecl *methdcl = callexpr->getMethodDecl();
729 if ((!is_explicitly_overridden) && (overridden_method_map_.size() > 0) &&
730 (overridden_method_map_.find(methdcl) != overridden_method_map_.end())) {
731 methdcl = const_cast<CXXMethodDecl *>(overridden_method_map_[methdcl]);
732 }
733 LLVM_DEBUG(llvm::dbgs() << "methoddecl follows\n");
734 LLVM_DEBUG(methdcl->dump(llvm::dbgs()));
735 if (isa<NamedDecl>(methdcl) && methdcl->getDeclName()) {
736 methodname = methdcl->getNameAsString();
737 qualmethodname = methdcl->getQualifiedNameAsString();
738 // make_ident(qualmethodname);
739 // methodecls[qualmethodname] = methdcl; // put it in the set of
740 // method decls
741
742 LLVM_DEBUG(llvm::dbgs()
743 << "here is method printname " << methodname << " and qual name "
744 << qualmethodname << " and declp " << methdcl << " \n");
745 if (methodname.compare(0, 8, "operator") ==
746 0) { // 0 means compare =, 8 is len("operator")
747 // the conversion we know about, can be skipped
748 LLVM_DEBUG(llvm::dbgs() << "Found operator conversion node\n");
749 TraverseStmt(objarg);
750 return false;
751 }
752 }
753
755 hNode *h_callp = NULL;
756 LLVM_DEBUG(llvm::dbgs() << "found " << methodname << "\n");
757
758 // if type of x in x.f(5) is primitive sc type (sc_in, sc_out, sc_inout,
759 // sc_signal and method name is either read or write, generate a SigAssignL|R
760 // -- FIXME need to make sure it is templated to a primitive type
761
762 // lutil.isSCType(qualmethodname, typeformethodclass);
763 // lutil.checktypematch(qualmethodname, typeformethodclass, lutil.issctype);
764
765 // bool inns_result = sc_ast_matchers::utils::isInNamespace(callexpr,
766 // "sc_core") || sc_ast_matchers::utils::isInNamespace(callexpr, "sc_dt");
767 bool foundsctype = lutil.isSCType(qualmethodname, typeformethodclass);
768 /*
769 bool newfoundsctype =
770 lutil.isSCByCallExpr(callexpr); // || lutil.isSCType(typeformethodclass);
771 if (foundsctype != newfoundsctype) {
772 LLVM_DEBUG(llvm::dbgs()
773 << "CHECK callexpr isSCType nonmatch -- old one returned "
774 << foundsctype << " for " << qualmethodname << "\n");
775 callexpr->dump();
776 assert(0);
777 // std::cin.get();
778 // foundsctype = newfoundsctype; // ADD THIS TO TEST SEGV
779 }
780 */
781
782 // bool foundsctype = lutil.isSCByCallExpr(callexpr);
783
784 if ((methodname == "read") && foundsctype)
785 opc = hNode::hdlopsEnum::hSigAssignR;
786 else if ((methodname == "write") && foundsctype)
787 opc = hNode::hdlopsEnum::hSigAssignL;
788 else if ((methodname == "wait") && thismode == rthread)
789 opc = hNode::hdlopsEnum::hWait;
790 else if (foundsctype) { // operator from simulation library
791 opc = hNode::hdlopsEnum::hBuiltinFunction;
792 } else {
793 opc = hNode::hdlopsEnum::hMethodCall;
794 lutil.make_ident(qualmethodname);
795 if (add_info)
796 qualmethodname += ":" + methodname; // include unqualified name for
797 // future hcode processing !!!
798 // methodecls[qualmethodname] = methdcl; // put it in the set of method
799 // decls
800 h_callp = new hNode(qualmethodname, opc);
801 // don't add this method to methodecls if processing modinit
802 if (!add_info) {
803 string tmpname = FindFname((FunctionDecl *)methdcl);
804 if (tmpname == "") { // isn't in local or global symbol table
805 LLVM_DEBUG(llvm::dbgs() << "adding method " << qualmethodname
806 << " with pointer " << methdcl << " \n");
807 methodecls.print(llvm::dbgs());
808 methodecls.add_entry(methdcl, qualmethodname, h_callp);
809 // string objstr = objtyp.getAsString(Policy);
810 // lutil.make_ident(objstr);
811 // bool a = !isCXXMemberCallExprSystemCCall(callexpr), b
812 // =sc_ast_matchers::utils::isInNamespace(callexpr, "sc_core") ;
813
814 // LLVM_DEBUG(llvm::dbgs() << "is sysc call " << qualmethodname << "
815 // old, new "<< a
816 // << " " << b << " end\n");
817 if (!isCXXMemberCallExprSystemCCall(callexpr))
818 methodecls.methodobjtypemap[methdcl] = typeformethodclass;
819 } else
820 h_callp->set(tmpname);
821 }
822 methodname = qualmethodname;
823 }
824
825 if (h_callp == NULL)
826 h_callp = new hNode(methodname, opc); // list to hold call expr node
827
828 // check for constant expr in wait statement
829 if ((opc == hNode::hdlopsEnum::hWait) && (callexpr->getNumArgs() > 0)) {
830 GetWaitArg(h_callp, callexpr->getArg(0));
831 h_ret = h_callp;
832 return false;
833 }
834
835
836 hNodep save_hret = h_ret;
837 // insert "this" argument if mod init block or recognized as special method
838 // (read|write|wait of sc type), or it is a method but not derived for
839 // scmodule hierarchy
840 if ((add_info) || ((opc != hNode::hdlopsEnum::hMethodCall) ||
841 (opc == hNode::hdlopsEnum::hMethodCall) &&
842 (!isCXXMemberCallExprSystemCCall(callexpr)))) {
843 TraverseStmt(objarg); // traverse the x in x.f(5)
844 if (h_ret && (h_ret != save_hret)) h_callp->child_list.push_back(h_ret);
845 }
846
847 for (auto arg : callexpr->arguments()) {
848 save_hret = h_ret;
849 TraverseStmt(arg);
850 if (h_ret != save_hret) h_callp->child_list.push_back(h_ret);
851 }
852 h_ret = h_callp;
853 return false;
854 }
855
856 bool HDLBody::isLogicalOp(clang::OverloadedOperatorKind opc) {
857 switch (opc) {
858 case OO_Less:
859 case OO_LessEqual:
860 case OO_Greater:
861 case OO_GreaterEqual:
862 case OO_ExclaimEqual:
863 case OO_EqualEqual:
864 return true;
865
866 default:
867 return false;
868 }
869 }
870
871 bool HDLBody::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *opcall) {
872 string operatorname = getOperatorSpelling(opcall->getOperator());
873 string operatortype = (opcall->getType()).getAsString();
874 hNodep h_operop;
875
876 LLVM_DEBUG(llvm::dbgs() << "In TraverseCXXOperatorCallExpr, Operator name is "
877 << operatorname << "\n");
878 LLVM_DEBUG(llvm::dbgs() << "Type name " << operatortype << "\n");
879 LLVM_DEBUG(opcall->getType()->dump(llvm::dbgs(), ast_context_));
880
881 // ========================== CHECK 2=====================
882 const Type *optypepointer = opcall->getType().getTypePtr();
883
884 /*
885 bool t12 =
886 ((operatorname == "=") || lutil.isSCBuiltinType(operatortype) ||
887 lutil.isSCType(operatortype) || (opcall->getType())->isBuiltinType() ||
888 ((operatorname == "<<") &&
889 (operatortype.find("sensitive") != std::string::npos)));
890 bool t22 = ((operatorname == "=") || lutil.isSCByType(optypepointer) ||
891 (opcall->getType())->isBuiltinType() ||
892 ((operatorname == "<<") &&
893 (operatortype.find("sensitive") != std::string::npos)));
894
895 if (t12 != t22) {
896 llvm::dbgs() << "CHECK### 2: t12 != t22\n";
897 assert(0);
898 // std::cin.get();
899 }
900 */
901 // ========================== END CHECK =====================
902 //
903
904 if ((operatorname == "=") ||
905 lutil.isSCBuiltinType(operatortype, optypepointer) ||
906 lutil.isSCType(operatortype, optypepointer) ||
907
908 // if ((operatorname == "=") || lutil.isSCByType(optypepointer ) ||
909 (opcall->getType())->isBuiltinType() ||
910 ((operatorname == "<<") &&
911 (operatortype.find("sensitive") != std::string::npos))) {
912 LLVM_DEBUG(llvm::dbgs() << "Processing operator call type\n");
913 // operator for an SC type
914 if ((operatorname.compare("()") == 0) &&
915 (operatortype.find("subref") != string::npos) &&
916 (opcall->getNumArgs() == 3)) {
917 // bit slice
918 h_operop = new hNode("SLICE", hNode::hdlopsEnum::hBinop);
919 } else {
920 if (operatorname == "[]") // subscript in operator call expre
921 h_operop = new hNode("ARRAYSUBSCRIPT", hNode::hdlopsEnum::hBinop);
922 else if ((operatorname == "++") || (operatorname == "--")) {
923 if (opcall->getNumArgs() == 2)
924 h_operop = new hNode(operatorname, hNode::hdlopsEnum::hPostfix);
925 else
926 h_operop = new hNode(operatorname, hNode::hdlopsEnum::hPrefix);
927 } else {
928 if (opcall->getNumArgs() == 1)
929 h_operop = new hNode(operatorname, hNode::hdlopsEnum::hUnop);
930 else
931 h_operop = new hNode(operatorname, hNode::hdlopsEnum::hBinop);
932
933 if ((operatorname == ",") /*&& (lutil.isSCByCallExpr(opcall))*/ )
934 h_operop->set("concat"); // overloaded comma is concat for sc types
935 //
936 //
937 }
938 }
939 int nargs = (h_operop->getopc() == hNode::hdlopsEnum::hPostfix ||
940 h_operop->getopc() == hNode::hdlopsEnum::hPrefix)
941 ? 1
942 : opcall->getNumArgs();
943 for (int i = 0; i < nargs; i++) {
944 hNodep save_h_ret = h_ret;
945 TraverseStmt(opcall->getArg(i));
946 if (h_ret == save_h_ret)
947 h_operop->child_list.push_back(new hNode(hNode::hdlopsEnum::hUnimpl));
948 else
949 h_operop->child_list.push_back(h_ret);
950 LLVM_DEBUG(llvm::dbgs()
951 << "operator call argument " << i << " follows\n");
952 LLVM_DEBUG(opcall->getArg(i)->dump(llvm::dbgs(), ast_context_));
953 }
954 h_ret = h_operop;
955 return false;
956 }
957
958 LLVM_DEBUG(llvm::dbgs() << "not yet implemented operator call expr, opc is "
959 << clang::getOperatorSpelling(opcall->getOperator())
960 << " num arguments " << opcall->getNumArgs()
961 << " skipping\n");
962 LLVM_DEBUG(opcall->dump(llvm::dbgs(), ast_context_));
963 h_ret = new hNode(hNode::hdlopsEnum::hUnimpl);
964 return false;
965 }
966
967 bool HDLBody::VisitMemberExpr(MemberExpr *memberexpr) {
968 bool founduserclass = false;
969 LLVM_DEBUG(llvm::dbgs() << "In TraverseMemberExpr\n");
970 string nameinfo = (memberexpr->getMemberNameInfo()).getName().getAsString();
971 LLVM_DEBUG(llvm::dbgs() << "name is " << nameinfo
972 << ", base and memberdecl trees follow\n");
973 LLVM_DEBUG(llvm::dbgs() << "base is \n");
974 LLVM_DEBUG(memberexpr->getBase()->dump(llvm::dbgs(), ast_context_););
975 LLVM_DEBUG(llvm::dbgs() << "memberdecl is " << memberexpr->getMemberDecl()
976 << " \n");
977 // if field decl, check if parent is a userdefined type XXXXXX
978 LLVM_DEBUG(memberexpr->getMemberDecl()->dump(llvm::dbgs()));
979 if (FieldDecl *fld = dyn_cast<FieldDecl>(memberexpr->getMemberDecl())) {
980 LLVM_DEBUG(llvm::dbgs() << "and field decl parent record pointer is "
981 << fld->getParent() << "\n");
982 const Type *classrectype = fld->getParent()->getTypeForDecl();
983 LLVM_DEBUG(llvm::dbgs() << "and field decl parent record type is "
984 << classrectype << "\n");
985 if (isUserClass(classrectype)) {
986 LLVM_DEBUG(llvm::dbgs()
987 << "member expr, found user defined class in usertypes "
988 << classrectype << "\n");
989 founduserclass = true;
990 }
991 }
992
993 string thisref = founduserclass ? "hthis##" : "";
994 // traverse the memberexpr base in case it is a nested structure
995 hNodep old_h_ret = h_ret;
996 TraverseStmt(memberexpr->getBase()); // get hcode for the base
997 if (h_ret != old_h_ret) {
998 if (h_ret->h_op == hNode::hdlopsEnum::hVarref) {
999 // concatenate base name in front of field name
1000 hNodep memexprnode = new hNode(thisref + h_ret->h_name + "##" + nameinfo,
1001 hNode::hdlopsEnum::hVarref);
1002 delete h_ret;
1003 h_ret = memexprnode; // replace returned h_ret with single node, field
1004 // names concatenated
1005 return false;
1006 } else {
1007 LLVM_DEBUG(llvm::dbgs()
1008 << "Value returned from member expr base was not Varref\n");
1009 LLVM_DEBUG(h_ret->print(llvm::dbgs()));
1010 string newname = FindVname(memberexpr->getMemberDecl());
1011 LLVM_DEBUG(llvm::dbgs()
1012 << "member with base expr new name is " << newname << "\n");
1013 if ((newname == "") && (thismode != rmodinit)) {
1014 LLVM_DEBUG(llvm::dbgs() << "vname lookup of memberdecl is null, "
1015 "assuming field reference\n");
1016 hNodep hfieldref = new hNode(hNode::hdlopsEnum::hFieldaccess);
1017 hfieldref->append(h_ret);
1018 hfieldref->append(
1019 new hNode(thisref + nameinfo, hNode::hdlopsEnum::hField));
1020 h_ret = hfieldref;
1021 return false;
1022 } else {
1023 hNodep memexprnode =
1024 new hNode(newname == "" ? thisref + nameinfo : thisref + newname,
1025 hNode::hdlopsEnum::hVarref);
1026 memexprnode->child_list.push_back(h_ret);
1027 h_ret = memexprnode;
1028 return false;
1029 }
1030 }
1031 }
1032
1033 string newname = FindVname(memberexpr->getMemberDecl());
1034 LLVM_DEBUG(llvm::dbgs() << "member expr new name is " << newname << "\n");
1035
1036 h_ret = new hNode(newname.empty() ? thisref + nameinfo : thisref + newname,
1037 hNode::hdlopsEnum::hVarref);
1038
1039 return false;
1040 }
1041
1042 bool HDLBody::VisitCallExpr(CallExpr *callexpr) {
1043 hNodep hcall; // = new hNode(hNode::hdlopsEnum::hMethodCall);
1044 hNodep save_hret = h_ret;
1045
1046 if (isa<FunctionDecl>(callexpr->getCalleeDecl()) &&
1047 ((FunctionDecl *)callexpr->getCalleeDecl())->isConstexpr()) {
1048 Expr::EvalResult res;
1049 if (callexpr->EvaluateAsRValue(
1050 res, callexpr->getCalleeDecl()->getASTContext())) {
1051 h_ret = new hNode(systemc_clang::utils::apint::toString(res.Val.getInt()),
1052 hNode::hdlopsEnum::hLiteral);
1053 return false;
1054 }
1055 }
1056
1057 TraverseStmt(callexpr->getCallee());
1058 // unlike methodcall, the function call name will hopefully resolve to a
1059 // declref. in traversedeclref, we create the hnode for the function call
1060 if ((h_ret !=
1061 save_hret) // &&
1062 //(h_ret->getopc() == hNode::hdlopsEnum::hMethodCall)) {
1063 ) {
1064 hcall = h_ret;
1065 } else {
1066 hcall = new hNode(
1067 hNode::hdlopsEnum::hMethodCall); // function name was more complicated
1068 hcall->child_list.push_back(h_ret);
1069 }
1070 for (auto arg : callexpr->arguments()) {
1071 hNodep sret = h_ret;
1072 TraverseStmt(arg);
1073 if (h_ret != sret) {
1074 hcall->child_list.push_back(h_ret);
1075 }
1076 }
1077 h_ret = hcall;
1078 LLVM_DEBUG(llvm::dbgs() << "found a call expr"
1079 << " AST follows\n ");
1080 LLVM_DEBUG(callexpr->dump(llvm::dbgs(), ast_context_););
1081 return false;
1082 }
1083
1084 bool HDLBody::VisitIfStmt(IfStmt *ifs) {
1085 hNodep h_ifstmt, h_ifc = NULL, h_ifthen = NULL, h_ifelse = NULL;
1086 h_ifstmt = new hNode(hNode::hdlopsEnum::hIfStmt);
1087 if (ifs->getConditionVariable()) {
1088 // Variable declarations are not allowed in if conditions
1089 LLVM_DEBUG(llvm::dbgs() << "Variable declarations are not allowed in if "
1090 "conditions, skipping\n");
1091 return false;
1092 } else {
1093 TraverseStmt(ifs->getCond());
1094 h_ifc = h_ret;
1095 }
1096 TraverseStmt(ifs->getThen());
1097 if (h_ret != h_ifc) // unchanged if couldn't translate the then clause
1098 h_ifthen = h_ret;
1099
1100 if (ifs->getElse()) {
1101 TraverseStmt(ifs->getElse());
1102 if ((h_ret != h_ifc) && (h_ret != h_ifthen)) h_ifelse = h_ret;
1103 }
1104 h_ifstmt->child_list.push_back(h_ifc);
1105 h_ifstmt->child_list.push_back(h_ifthen);
1106 if (h_ifelse) h_ifstmt->child_list.push_back(h_ifelse);
1107 h_ret = h_ifstmt;
1108 return false;
1109 }
1110
1111 bool HDLBody::VisitForStmt(ForStmt *fors) {
1112 hNodep h_forstmt, h_forinit, h_forcond, h_forinc, h_forbody;
1113 LLVM_DEBUG(llvm::dbgs() << "For stmt\n");
1114 h_forstmt = new hNode(hNode::hdlopsEnum::hForStmt);
1115 if ((fors->getInit() != NULL) && (isa<CompoundStmt>(fors->getInit())))
1116 LLVM_DEBUG(llvm::dbgs()
1117 << "Compound stmt not handled in for init, skipping\n");
1118 else {
1119 if ((fors->getInit() != NULL) && isa<DeclStmt>(fors->getInit())) {
1120 LLVM_DEBUG(llvm::dbgs() << "for init is a decl stmt\n");
1121 LLVM_DEBUG((fors->getInit())->dump(llvm::dbgs(), ast_context_));
1122 }
1123 TraverseStmt(fors->getInit());
1124 }
1125 h_forinit = (h_ret == NULL) ? new hNode(hNode::hdlopsEnum::hNoop)
1126 : h_ret; // null if in place var decl
1127 TraverseStmt(fors->getCond());
1128 h_forcond = (h_ret == NULL) ? new hNode(hNode::hdlopsEnum::hNoop)
1129 : h_ret; // null if in place if no cond
1130 TraverseStmt(fors->getInc());
1131 h_forinc =(h_ret == NULL) ? new hNode(hNode::hdlopsEnum::hNoop)
1132 : h_ret; // null if in place no inc
1133 LLVM_DEBUG(llvm::dbgs() << "For loop body\n");
1134 LLVM_DEBUG(fors->getBody()->dump(llvm::dbgs(), ast_context_););
1135 TraverseStmt(fors->getBody());
1136 h_forbody = h_ret;
1137 h_forstmt->child_list.push_back(h_forinit);
1138 h_forstmt->child_list.push_back(h_forcond);
1139 h_forstmt->child_list.push_back(h_forinc);
1140 h_forstmt->child_list.push_back(h_forbody);
1141 h_ret = h_forstmt;
1142
1143 return false;
1144 }
1145
1146 bool HDLBody::ProcessSwitchCase(SwitchCase *sc) {
1147 LLVM_DEBUG(llvm::dbgs() << "In ProcessSwitchCase\n");
1148 hNodep hcasep;
1149 hNodep old_hret = h_ret;
1150 if (isa<DefaultStmt>(sc)) {
1151 LLVM_DEBUG(llvm::dbgs() << "Found default stmt in switchcase\n");
1152 hcasep = new hNode(hNode::hdlopsEnum::hSwitchDefault);
1153 TraverseStmt((DefaultStmt *)sc->getSubStmt());
1154 } else {
1155 LLVM_DEBUG(llvm::dbgs() << "Found case stmt in switchcase\n");
1156 hcasep = new hNode(hNode::hdlopsEnum::hSwitchCase);
1157 if (ConstantExpr *expr =
1158 dyn_cast<ConstantExpr>(((CaseStmt *)sc)->getLHS())) {
1159 llvm::APSInt val = expr->getResultAsAPSInt();
1160 hcasep->child_list.push_back(
1162 hNode::hdlopsEnum::hLiteral));
1163 }
1164 TraverseStmt((CaseStmt *)sc->getSubStmt());
1165 }
1166 if (h_ret != old_hret) {
1167 hcasep->child_list.push_back(h_ret);
1168 } else {
1169 hcasep->child_list.push_back(new hNode(hNode::hdlopsEnum::hUnimpl));
1170 }
1171 h_ret = hcasep;
1172 return true;
1173 }
1174
1175 bool HDLBody::VisitSwitchStmt(SwitchStmt *switchs) {
1176 hNodep h_switchstmt;
1177 LLVM_DEBUG(llvm::dbgs() << "Switch stmt body -----\n");
1178 LLVM_DEBUG(switchs->getBody()->dump(llvm::dbgs(), ast_context_););
1179 LLVM_DEBUG(llvm::dbgs() << "End Switch stmt body -----\n");
1180
1181 h_switchstmt = new hNode(hNode::hdlopsEnum::hSwitchStmt);
1182 // Stmt * swinit = dyn_cast<Stmt>(switchs->getInit());
1183 // if (swinit) {
1184 // LLVM_DEBUG(llvm::dbgs() << "switch init not handled, skipping\n");
1185 //}
1186 hNodep old_ret = h_ret;
1187 TraverseStmt(switchs->getCond());
1188 if (h_ret != old_ret) {
1189 h_switchstmt->child_list.push_back(h_ret);
1190 } else
1191 h_switchstmt->child_list.push_back(new hNode(hNode::hdlopsEnum::hUnimpl));
1192
1193 old_ret = h_ret;
1194
1195 TraverseStmt(switchs->getBody());
1196
1197 if (h_ret != old_ret) {
1199 // here need extra code to append non switchcase hcode into previous
1200 // switchcase group, which happens if the switchcase isn't wrapped in
1201 // a compound statement {}.
1202
1203 h_switchstmt->child_list.push_back(h_ret);
1204 }
1205
1206 // for (SwitchCase *sc = switchs->getSwitchCaseList(); sc != NULL;
1207 // sc = sc->getNextSwitchCase()) {
1208 // LLVM_DEBUG(llvm::dbgs() << "Switch case\n");
1209 // LLVM_DEBUG(sc->dump(llvm::dbgs()));
1210 // if (isa<DefaultStmt>(sc)) {
1211 // LLVM_DEBUG(llvm::dbgs() << "Found default stmt in case\n");
1212 // }
1213 // else {
1214 // ProcessSwitchCase(sc);
1215 // h_switchstmt->child_list.push_back(h_ret);
1216 // }
1217 // }
1218 // TraverseStmt(switchs->getBody());
1219 // h_switchbody = h_ret;
1220 // h_switchstmt->child_list.push_back(h_switchinit);
1221
1222 // h_switchstmt->child_list.push_back(h_switchbody);
1223 h_ret = h_switchstmt;
1224
1225 return false;
1226 }
1227
1228 bool HDLBody::VisitWhileStmt(WhileStmt *whiles) {
1229 hNodep h_whilestmt, h_whilecond, h_whilebody;
1230 LLVM_DEBUG(llvm::dbgs() << "While stmt\n");
1231 h_whilestmt = new hNode(hNode::hdlopsEnum::hWhileStmt);
1232 if (whiles->getConditionVariable()) {
1233 LLVM_DEBUG(
1234 llvm::dbgs()
1235 << "Variable declarations not handled in while condition, skipping\n");
1236 } else {
1237 // Get condition
1238 TraverseStmt(whiles->getCond());
1239 h_whilecond = h_ret;
1240 }
1241
1242 // Get the body
1243 TraverseStmt(whiles->getBody());
1244 h_whilebody = h_ret;
1245 h_whilestmt->child_list.push_back(h_whilecond);
1246 h_whilestmt->child_list.push_back(h_whilebody);
1247 h_ret = h_whilestmt;
1248
1249 return false;
1250 }
1251
1252 // unfortunately clang ast doesn't do inheritance on the classes
1253 // so code is duplicated
1254
1255 bool HDLBody::VisitDoStmt(DoStmt *whiles) {
1256 hNodep h_whilestmt, h_whilecond, h_whilebody;
1257 LLVM_DEBUG(llvm::dbgs() << "Do stmt\n");
1258 h_whilestmt = new hNode(hNode::hdlopsEnum::hDoStmt);
1259 // Get condition
1260 TraverseStmt(whiles->getCond());
1261 h_whilecond = h_ret;
1262
1263 // Get the body
1264 TraverseStmt(whiles->getBody());
1265 h_whilebody = h_ret;
1266 h_whilestmt->child_list.push_back(h_whilecond);
1267 h_whilestmt->child_list.push_back(h_whilebody);
1268 h_ret = h_whilestmt;
1269
1270 return false;
1271 }
1272
1273 // these two functions are so clumsy. The data structure should handle
1274 // multi-level symbol tables.
1275
1276 string HDLBody::FindVname(NamedDecl *vard) {
1277 string newname = vname_map.find_entry_newn(
1278 vard, thismode == rthread); // set referenced bit if in thread
1279 if (newname == "")
1281 vard, thismode == rthread); // set referenced bit if in thread
1282 return newname;
1283 }
1284
1285 string HDLBody::FindFname(FunctionDecl *funcd) {
1286 string newname = methodecls.find_entry_newn(
1287 funcd, thismode == rthread); // set referenced bit if in thread
1288 if (newname == "")
1290 funcd, thismode == rthread); // set referenced bit if in thread
1291 return newname;
1292 }
1293
1295 LLVM_DEBUG(llvm::dbgs() << "Vname Dump\n");
1296 // for (auto const &var : vname_map.hdecl_name_map) {
1297 for (auto const &var : vname_map) {
1298 LLVM_DEBUG(llvm::dbgs() << "(" << var.first << "," << var.second.oldn
1299 << ", " << var.second.newn << ")\n");
1300 if (add_info && (var.second.newn.find(gvar_prefix) == std::string::npos)) {
1301 // if this isn't a global variable
1302 // mark this var decl as a renamed var decl and tack on the original name
1303 // used in later processing of hcode
1304 var.second.h_vardeclp->h_op = hNode::hdlopsEnum::hVardeclrn;
1305 var.second.h_vardeclp->child_list.push_back(
1306 new hNode(var.second.oldn, hNode::hdlopsEnum::hLiteral));
1307 }
1308 if (var.second.newn.find(gvar_prefix) == std::string::npos)
1309 // don't add global variable to local list
1310 hvns->child_list.push_back(var.second.h_vardeclp);
1311 }
1312 }
1313
1314
1316 // break up chain of assignments a = b = c = d = 0;
1317 // at entry there is a chain of at least two: a = b = 0;
1318
1319 hNodep hassignchain = new hNode(hNode::hdlopsEnum::hCStmt);
1320 hNodep htmp = hinp; // (= a subtree)
1321 do {
1322 hNodep htmp2 = htmp->child_list[1]; // (= b subtree)
1323 htmp->child_list[1] = htmp2->child_list[0]; // (= a b)
1324 hassignchain->child_list.push_back(htmp);
1325 htmp = htmp2; // (= b subtree)
1326 } while (isAssignOp(htmp->child_list[1]));
1327 hassignchain->child_list.push_back(htmp);
1328 std::reverse(hassignchain->child_list.begin(),
1329 hassignchain->child_list.end());
1330 return hassignchain;
1331 }
1332 void HDLBody::GetWaitArg(hNodep &h_callp, Expr *callarg) {
1333 int64_t waitarg = 0;
1334 if (callarg->isEvaluatable(ast_context_)) {
1335 clang::Expr::EvalResult result{};
1336 callarg->EvaluateAsInt(result, ast_context_);
1337 waitarg = result.Val.getInt().getExtValue();
1338 llvm::dbgs() << " wait arg val: " << waitarg << "\n";
1339 }
1340 hNodep arglit = new hNode( std::to_string(waitarg), hNode::hdlopsEnum::hLiteral);
1341 h_callp->append(arglit);
1342 }
1343
1345 if (hswitchstmt->child_list.size() == 0) return;
1346 hNodep hprev = hswitchstmt->child_list[0]; // should be a switchcase node
1347 for (int i = 1; i < hswitchstmt->child_list.size(); i++) {
1348 if ((hswitchstmt->child_list[i]->getopc() !=
1349 hNode::hdlopsEnum::hSwitchCase) &&
1350 (hswitchstmt->child_list[i]->getopc() !=
1351 hNode::hdlopsEnum::hSwitchDefault)) {
1352 hNodep htmp = new hNode((hswitchstmt->child_list[i])->getname(),
1353 (hswitchstmt->child_list[i])->getopc());
1354 htmp->child_list = (hswitchstmt->child_list[i])->child_list;
1355 hprev->append(htmp);
1356 hswitchstmt->child_list[i]->set(hNode::hdlopsEnum::hLast);
1357 } else
1358 hprev = hswitchstmt->child_list[i];
1359 }
1360 hswitchstmt->child_list.erase(
1361 std::remove_if(
1362 hswitchstmt->child_list.begin(), hswitchstmt->child_list.end(),
1363 [](hNodep hp) { return hp->getopc() == hNode::hdlopsEnum::hLast; }),
1364 hswitchstmt->child_list.end());
1365 }
1366
1367 // CXXMethodDecl *HDLBody::getEMD() {
1368 // return _emd;
1369 // }
1370} // 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:871
bool VisitBinaryOperator(BinaryOperator *expr)
Definition HDLBody.cpp:453
HDLBodyMode thismode
Definition HDLBody.h:102
bool isLogicalOp(clang::OverloadedOperatorKind opc)
Definition HDLBody.cpp:856
bool VisitCaseStmt(CaseStmt *stmt)
Definition HDLBody.cpp:234
string FindFname(FunctionDecl *funcd)
Definition HDLBody.cpp:1285
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:1344
void GetWaitArg(hNodep &h_callp, Expr *callarg)
Definition HDLBody.cpp:1332
bool VisitConditionalOperator(ConditionalOperator *expr)
Definition HDLBody.cpp:543
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:967
string generate_vname(string nm)
Definition HDLBody.h:124
bool VisitUnaryOperator(UnaryOperator *expr)
Definition HDLBody.cpp:515
bool isUserClass(const Type *classrectype)
Definition HDLBody.h:107
bool VisitArraySubscriptExpr(ArraySubscriptExpr *expr)
Definition HDLBody.cpp:670
void AddVnames(hNodep &hvns)
Definition HDLBody.cpp:1294
bool VisitSwitchStmt(SwitchStmt *switchs)
Definition HDLBody.cpp:1175
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:1228
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:1315
bool VisitInitListExpr(InitListExpr *stmt)
Definition HDLBody.cpp:214
bool ProcessSwitchCase(SwitchCase *cases)
Definition HDLBody.cpp:1146
bool VisitDoStmt(DoStmt *whiles)
Definition HDLBody.cpp:1255
bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *b)
Definition HDLBody.cpp:566
bool VisitIfStmt(IfStmt *ifs)
Definition HDLBody.cpp:1084
bool VisitCallExpr(CallExpr *callexpr)
Definition HDLBody.cpp:1042
bool VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *stmt)
Definition HDLBody.cpp:199
bool VisitBreakStmt(BreakStmt *stmt)
Definition HDLBody.cpp:270
string FindVname(NamedDecl *vard)
Definition HDLBody.cpp:1276
bool VisitCXXMemberCallExpr(CXXMemberCallExpr *callexpr)
Definition HDLBody.cpp:688
bool VisitDeclRefExpr(DeclRefExpr *expr)
Definition HDLBody.cpp:574
bool VisitForStmt(ForStmt *fors)
Definition HDLBody.cpp:1111
bool VisitIntegerLiteral(IntegerLiteral *lit)
Definition HDLBody.cpp:558
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