virtual void visit(SgNode* n) { SgLabelStatement* l = isSgLabelStatement(n); if (l) { SgName name = l->get_label(); // The label is in some inner scope, and needs to be moved to the // enclosing function definition SgSymbolTable* st = l->get_scope()->get_symbol_table(); ROSE_ASSERT (st); ROSE_ASSERT (st->find_label(name)); st->remove(st->find_label(name)); name << "__" << ++labelRenameCounter; // cout << "Found label " << l->get_label().getString() << " to rename to " << name.getString() << endl; l->set_label(name); l->set_scope(newScope); SgLabelSymbol* lSym = new SgLabelSymbol(l); lSym->set_parent(symtab); symtab->insert(name, lSym); } }
void RewriteFSM::visitSgFunctionDeclaration(SgFunctionDeclaration *FD) { SgFunctionDefinition *fdef = FD->get_definition(); if (!fdef) { return; } if (debugHooks) { std::cout << "Func decl: " << FD << " " << FD->get_name() << std::endl; } std::string modName = FD->get_name().getString(); HtdInfoAttribute *htd = getHtdInfoAttribute(fdef); bool isStreamingStencil = false; size_t pos = 0; if ((pos = modName.find(StencilStreamPrefix)) != std::string::npos && pos == 0) { isStreamingStencil = true; } #define hostEntryPrefix "__HTC_HOST_ENTRY_" bool isHostEntry = false; if ((pos = modName.find(hostEntryPrefix)) != std::string::npos && pos == 0) { isHostEntry = true; } // Emit a default, unnamed thread group. std::string modWidth = boost::to_upper_copy(modName) + "_HTID_W"; if (isStreamingStencil) { // The streaming version of a stencil must have width 0. htd->appendDefine(modWidth, "0"); } else if (isHostEntry) { htd->appendDefine(modWidth, "1"); } else if (htd->moduleWidth != -1) { htd->appendDefine(modWidth, boost::lexical_cast<std::string>(htd->moduleWidth)); } else { DefaultModuleWidthAttribute *dwAttr = getDefaultModuleWidthAttribute(SageInterface::getGlobalScope(fdef)); if (dwAttr) { htd->appendDefine(modWidth, boost::lexical_cast<std::string>(dwAttr->width)); } else { htd->appendDefine(modWidth, "5"); } } htd->appendModule(modName, "", modWidth); // For streaming stencils, ProcessStencils inserts a canned sequence, // so we bypass generating a normal FSM. if (isStreamingStencil) { return; } // // Create new case body blocks for each state. // The first executable statement starts the first state, and each // label starts a new state. // std::map<SgLabelStatement *, int> labelToState; std::map<int, std::string> stateToName; SgBasicBlock *funcBody = isSgBasicBlock(fdef->get_body()); SgStatementPtrList &stmts = funcBody->get_statements(); std::vector<SgStatement *>::iterator SI, SP; for (SI = stmts.begin(); SI != stmts.end(); ++SI) { if (!isSgDeclarationStatement(*SI)) { break; } } if (SI == stmts.end()) { return; } SP = SI; std::vector<SgBasicBlock *> newBlocks; SgBasicBlock *newbb = SageBuilder::buildBasicBlock(); newBlocks.push_back(newbb); stateToName[1] = "__START"; bool prevIsLabel = false; for (; SI != stmts.end(); ++SI) { SgStatement *stmt = *SI; SgLabelStatement *labstmt = isSgLabelStatement(stmt); if (labstmt) { if (!prevIsLabel) { newbb = SageBuilder::buildBasicBlock(); newBlocks.push_back(newbb); } int snum = newBlocks.size(); labelToState[labstmt] = snum; stateToName[snum] += "__" + labstmt->get_label().getString(); prevIsLabel = true; #if 1 // TODO: these labels can carry preproc infos-- but the unparser // doesn't output them if the label is not actually output. AttachedPreprocessingInfoType *comments = labstmt->getAttachedPreprocessingInfo(); if (comments && comments->size() > 0) { std::cerr << "DEVWARN: losing Preprocinfo on label" << std::endl; SageInterface::dumpPreprocInfo(labstmt); } #endif stmt->unsetOutputInCodeGeneration(); SageInterface::appendStatement(stmt, newbb); } else { prevIsLabel = false; SageInterface::appendStatement(stmt, newbb); } } stmts.erase(SP, stmts.end()); // Add module name to each state name and create enum decl. SgEnumDeclaration *enumDecl = SageBuilder::buildEnumDeclaration("states", fdef); for (int i = 1; i <= newBlocks.size(); i++) { stateToName[i] = modName + stateToName[i]; boost::to_upper(stateToName[i]); SgName nm(stateToName[i]); SgInitializedName *enumerator = SageBuilder::buildInitializedName(nm, SageBuilder::buildIntType(), SageBuilder::buildAssignInitializer(SageBuilder::buildIntVal(i))); enumerator->set_scope(funcBody); enumDecl->append_enumerator(enumerator); // Add the instruction to the htd info. htd->appendInst(nm.getString()); } SageInterface::prependStatement(enumDecl, funcBody); if (!debugHooks) { enumDecl->unsetOutputInCodeGeneration(); } SgGlobal *GS = SageInterface::getGlobalScope(FD); SgVariableDeclaration *declHtValid = HtDeclMgr::buildHtlVarDecl("PR_htValid", GS); SgVariableDeclaration *declHtInst = HtDeclMgr::buildHtlVarDecl("PR_htInst", GS); SgFunctionDeclaration *declHtContinue = HtDeclMgr::buildHtlFuncDecl("HtContinue", GS); SgFunctionDeclaration *declHtAssert = HtDeclMgr::buildHtlFuncDecl("HtAssert", GS); // // Create the finite state machine switch statement "switch (PR_htInst)", // and insert guard "if (PR_htValid)". // SgBasicBlock *newSwitchBody = SageBuilder::buildBasicBlock(); SgExpression *htInstExpr = SageBuilder::buildVarRefExp(declHtInst); SgSwitchStatement *newSwitch = SageBuilder::buildSwitchStatement(htInstExpr, newSwitchBody); SgExpression *htValidExpr = SageBuilder::buildVarRefExp(declHtValid); SgIfStmt *newIfStmt = SageBuilder::buildIfStmt(htValidExpr, SageBuilder::buildBasicBlock(newSwitch), 0); SageInterface::appendStatement(newIfStmt, funcBody); int casenum = 1; foreach (SgBasicBlock *newCaseBody, newBlocks) { SgExpression *caseExpr = SageBuilder::buildEnumVal_nfi(casenum, enumDecl, stateToName[casenum]); SgCaseOptionStmt *newCase = SageBuilder::buildCaseOptionStmt(caseExpr, newCaseBody); SageInterface::appendStatement(newCase, newSwitchBody); casenum++; }