void BlockSummary::ComputeAssertNames() { BlockCFG *cfg = GetBlockCFG(m_id); Assert(cfg); // the assertion names need the filename of the containing function. Location *loc = cfg->GetPointLocation(cfg->GetEntryPoint()); // keep track of the last kind/index to be generated for an assertion. // the index space should be different for each assertion kind so that // different assertions do not interfere with one another. we can get this // with a simple counter because the assertions are sorted by kind. AssertKind last_kind = ASK_None; size_t last_index = 0; for (size_t ind = 0; m_assert_list && ind < m_assert_list->Size(); ind++) { AssertInfo &info = m_assert_list->At(ind); Assert(!info.name_buf); // only compute indexes for assertions which need to be checked. if (info.cls != ASC_Check) continue; // reset the index if this is a new kind of assertion. if (info.kind != last_kind) { last_kind = info.kind; last_index = 0; } last_index++; info.name_buf = new Buffer(256); BufferOutStream out(info.name_buf); out << AssertKindString(last_kind) << "$" << loc->FileName()->Value() << "$" << m_id->Function()->Value() << "$" << (m_id->Kind() == B_Loop ? m_id->Loop()->Value() : "func") << "$" << last_index << '\0'; } cfg->DecRef(); }
// split a single loop from the existing body. this creates a new CFG // with cloned points and edges for the loop's execution, and fixes up // the points and edges in base_cfg to add a Loop() summary edge and remove // the CFG cycle. BlockCFG* SplitSingleLoop(PPoint loophead, const Vector<PPoint> &all_loops, BlockCFG *base_cfg) { // make a temporary name for the loop. char loop_name[100]; snprintf(loop_name, sizeof(loop_name), "scratch#%d", loophead); Variable *function_info = base_cfg->GetId()->BaseVar(); // make an ID for the split loop. function_info->IncRef(); String *loop_info = String::Make(loop_name); BlockId *loop_id = BlockId::Make(B_Loop, function_info, loop_info); // make a CFG for the split loop. BlockCFG *loop_cfg = BlockCFG::Make(loop_id); CopyCFGLocationsVariables(base_cfg, loop_cfg); PPointListHash remapping; Vector<size_t> old_entry_indexes; Vector<size_t> old_exit_indexes; Vector<size_t> old_back_indexes; CloneLoopBody(base_cfg, loophead, &remapping, loop_cfg, &old_entry_indexes, &old_exit_indexes, &old_back_indexes); // fixup the old CFG first. we need to perform the following steps: // - create a new point with a Loop() edge going to the head. // - add the new point to the body of any loop also containing the head. // - change all loop entry edges to go to the new point instead of the head. // - delete all backedges on the loop by pointing them to point 0. Location *loop_head_loc = base_cfg->GetPointLocation(loophead); loop_head_loc->IncRef(); PPoint summary_point = base_cfg->AddPoint(loop_head_loc); loop_id->IncRef(); PEdge *summary_edge = PEdge::MakeLoop(summary_point, loophead, loop_id); base_cfg->AddEdge(summary_edge); // mark the new summary point as being reachable from the entry point. entry_reach_table->Insert(summary_point); // add the new summary point to the body of any other loop which // already contains the head of this loop in its body. for (size_t lind = 0; lind < all_loops.Size(); lind++) { if (body_table->Lookup(PPointPair(all_loops[lind], loophead))) { body_table->Insert(PPointPair(all_loops[lind], summary_point)); body_list_table->Insert(all_loops[lind], summary_point); } } for (size_t oind = 0; oind < old_entry_indexes.Size(); oind++) { size_t entry_index = old_entry_indexes[oind]; PEdge *old_edge = base_cfg->GetEdge(entry_index); PPoint source = old_edge->GetSource(); Assert(old_edge->GetTarget() == loophead); PEdge *new_edge = PEdge::ChangeEdge(old_edge, source, summary_point); base_cfg->SetEdge(entry_index, new_edge); } for (size_t oind = 0; oind < old_back_indexes.Size(); oind++) { size_t back_index = old_back_indexes[oind]; PEdge *old_edge = base_cfg->GetEdge(back_index); PPoint source = old_edge->GetSource(); Assert(old_edge->GetTarget() == loophead); PEdge *new_edge = PEdge::ChangeEdge(old_edge, source, 0); base_cfg->SetEdge(back_index, new_edge); } // fixup the new CFG second. we need to perform the following steps: // - mark the cloned head as the entry point. // - create a new point as the exit point. // - for each backedge in the original loop, redirect to the exit point. PPoint split_entry = remapping.LookupSingle(loophead); // find the exit location associated with this loop head, if there is one. size_t headind = 0; for (; headind < base_cfg->GetLoopHeadCount(); headind++) { if (base_cfg->GetLoopHead(headind).point == loophead) break; } Assert(headind < base_cfg->GetLoopHeadCount()); Location *end_location = base_cfg->GetLoopHead(headind).end_location; // if there isn't an end location (goto loop in the original source), // just use the location of the loop head itself. if (!end_location) end_location = loop_head_loc; end_location->IncRef(); PPoint split_exit = loop_cfg->AddPoint(end_location); for (size_t oind = 0; oind < old_back_indexes.Size(); oind++) { size_t back_index = old_back_indexes[oind]; PEdge *old_edge = base_cfg->GetEdge(back_index); PPoint source = old_edge->GetSource(); // we should have already dropped the target of this edge. Assert(old_edge->GetTarget() == 0); PPoint new_source = remapping.LookupSingle(source); PEdge *new_edge = PEdge::ChangeEdge(old_edge, new_source, split_exit); loop_cfg->AddEdge(new_edge); } // set the entry/exit points of the loop CFG. loop_cfg->SetEntryPoint(split_entry); loop_cfg->SetExitPoint(split_exit); // trim any unreachable portions of the loop CFG, collapse skips // and sort the points. TrimUnreachable(loop_cfg, true); TopoSortCFG(loop_cfg); // set the end location of the loop to the point in the body with the // highest line number. the GCC frontend does not have information // about the end location of loop bodies. Location *highest = end_location; for (PPoint point = 1; point <= loop_cfg->GetPointCount(); point++) { Location *loc = loop_cfg->GetPointLocation(point); if (loc->FileName() == highest->FileName() && loc->Line() > highest->Line()) highest = loc; } highest->IncRef(); loop_cfg->SetPointLocation(loop_cfg->GetExitPoint(), highest); return loop_cfg; }