std::unique_ptr<std::vector<CFileEntry>> CSelectWithMatching::select_out(std::unique_ptr<std::vector<CFileEntry>> data){ //select only those files which hash equal on of those in the matching vector std::unique_ptr<std::vector<CFileEntry>> merged_endresult(new std::vector<CFileEntry>); std::for_each(m_matching->begin(), m_matching->end(), [&data, &merged_endresult](CFileEntry& elem){ elem.createHash(); auto range = std::equal_range(data->begin(), data->end(), elem); if(range.first != data->end()){ std::copy(range.first, range.second, std::back_inserter(*merged_endresult)); } }); return std::move(merged_endresult); }
void JuliaOJIT::addModule(std::unique_ptr<Module> M) { #ifndef JL_NDEBUG // validate the relocations for M for (Module::iterator I = M->begin(), E = M->end(); I != E; ) { Function *F = &*I; ++I; if (F->isDeclaration()) { if (F->use_empty()) F->eraseFromParent(); else if (!(isIntrinsicFunction(F) || findUnmangledSymbol(F->getName()) || SectionMemoryManager::getSymbolAddressInProcess( getMangledName(F->getName())))) { std::cerr << "FATAL ERROR: " << "Symbol \"" << F->getName().str() << "\"" << "not found"; abort(); } } } #endif JL_TIMING(LLVM_MODULE_FINISH); // We need a memory manager to allocate memory and resolve symbols for this // new module. Create one that resolves symbols by looking back into the JIT. auto Resolver = orc::createLambdaResolver( [&](const std::string &Name) { // TODO: consider moving the FunctionMover resolver here // Step 0: ObjectLinkingLayer has checked whether it is in the current module // Step 1: See if it's something known to the ExecutionEngine if (auto Sym = findSymbol(Name, true)) { #if JL_LLVM_VERSION >= 40000 // `findSymbol` already eagerly resolved the address // return it directly. return Sym; #else return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); #endif } // Step 2: Search the program symbols if (uint64_t addr = SectionMemoryManager::getSymbolAddressInProcess(Name)) return JL_SymbolInfo(addr, JITSymbolFlags::Exported); #if defined(_OS_LINUX_) if (uint64_t addr = resolve_atomic(Name.c_str())) return JL_SymbolInfo(addr, JITSymbolFlags::Exported); #endif // Return failure code return JL_SymbolInfo(nullptr); }, [](const std::string &S) { return nullptr; } ); SmallVector<std::unique_ptr<Module>,1> Ms; Ms.push_back(std::move(M)); auto modset = CompileLayer.addModuleSet(std::move(Ms), MemMgr, std::move(Resolver)); // Force LLVM to emit the module so that we can register the symbols // in our lookup table. CompileLayer.emitAndFinalize(modset); }
EdgeBasedGraphFactory::EdgeBasedGraphFactory(std::shared_ptr<NodeBasedDynamicGraph> node_based_graph, std::shared_ptr<RestrictionMap> restriction_map, std::unique_ptr<std::vector<NodeID>> barrier_node_list, std::unique_ptr<std::vector<NodeID>> traffic_light_node_list, const std::vector<QueryNode> &node_info_list, const SpeedProfileProperties &speed_profile) : speed_profile(speed_profile), m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()), m_node_info_list(node_info_list), m_node_based_graph(std::move(node_based_graph)), m_restriction_map(std::move(restriction_map)), max_id(0), removed_node_count(0) { // insert into unordered sets for fast lookup m_barrier_nodes.insert(barrier_node_list->begin(), barrier_node_list->end()); m_traffic_lights.insert(traffic_light_node_list->begin(), traffic_light_node_list->end()); }
///<summary> /// コンストラクタ /// UNIX_TIMESTAMPの系列を渡して経過時刻のリストに変換する /// relative_to_firstをfalseにすると生のUNIX_TIMESTAMPの値をそのまま保持する ///</summary> TimeSlotManager::TimeSlotManager(std::unique_ptr<std::vector<time_t>> timeslots, bool relative_to_first) { std::sort(timeslots->begin(), timeslots->end()); if (!relative_to_first) this->timeslots = std::move(timeslots); else { this->timeslots = std::make_unique<std::vector<time_t>>(timeslots->size()); if (timeslots->size() == 0) return; time_t first = timeslots->at(0); for (int i = 0; i < timeslots->size(); i++) { this->timeslots->at(i) = timeslots->at(i) - first; } } }
ModuleHandleT addModule(std::unique_ptr<Module> M) { #ifndef NDEBUG // validate the relocations for M for (Module::iterator I = M->begin(), E = M->end(); I != E; ) { Function *F = &*I; ++I; if (F->isDeclaration()) { if (F->use_empty()) F->eraseFromParent(); else assert(F->isIntrinsic() || findUnmangledSymbol(F->getName()) || SectionMemoryManager::getSymbolAddressInProcess(F->getName())); } } #endif // We need a memory manager to allocate memory and resolve symbols for this // new module. Create one that resolves symbols by looking back into the JIT. auto Resolver = orc::createLambdaResolver( [&](const std::string &Name) { // TODO: consider moving the FunctionMover resolver here // Step 0: ObjectLinkingLayer has checked whether it is in the current module // Step 1: See if it's something known to the ExecutionEngine if (auto Sym = findSymbol(Name, true)) return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); // Step 2: Search the program symbols if (uint64_t addr = SectionMemoryManager::getSymbolAddressInProcess(Name)) return RuntimeDyld::SymbolInfo(addr, JITSymbolFlags::Exported); // Return failure code return RuntimeDyld::SymbolInfo(nullptr); }, [](const std::string &S) { return nullptr; } ); SmallVector<std::unique_ptr<Module>,1> Ms; Ms.push_back(std::move(M)); auto modset = CompileLayer.addModuleSet(std::move(Ms), MemMgr, std::move(Resolver)); // Force LLVM to emit the module so that we can register the symbols // in our lookup table. CompileLayer.emitAndFinalize(modset); return modset; }
std::unique_ptr<std::vector<CFileEntry>> CSelectWithMatching::select_in(std::unique_ptr<std::vector<CFileEntry>> data){ //select only candidate files which are of equal file size like those //files in the matching vector std::unique_ptr<std::vector<CFileEntry>> input_selection(new std::vector<CFileEntry>); input_selection->reserve(m_matching->size()); std::for_each(m_matching->begin(), m_matching->end(), [&data, &input_selection](const CFileEntry& elem){ auto range = std::equal_range(data->begin(), data->end(), elem, [](const CFileEntry& lhs, const CFileEntry& rhs){ return lhs.m_filesize < rhs.m_filesize; }); if(range.first != data->end()){ std::copy(range.first, range.second, std::back_inserter(*input_selection)); } }); std::copy(m_matching->begin(), m_matching->end(), std::back_inserter(*input_selection)); std::sort(input_selection->begin(), input_selection->end(), [](const CFileEntry& lhs, const CFileEntry& rhs){ return lhs.m_filesize < rhs.m_filesize; }); return std::move(input_selection); }
// destructively move the contents of src into dest // this assumes that the targets of the two modules are the same // including the DataLayout and ModuleFlags (for example) // and that there is no module-level assembly static void jl_merge_module(Module *dest, std::unique_ptr<Module> src) { assert(dest != src.get()); for (Module::global_iterator I = src->global_begin(), E = src->global_end(); I != E;) { GlobalVariable *sG = &*I; GlobalValue *dG = dest->getNamedValue(sG->getName()); ++I; // Replace a declaration with the definition: if (dG) { if (sG->isDeclaration()) { sG->replaceAllUsesWith(dG); sG->eraseFromParent(); continue; } else { dG->replaceAllUsesWith(sG); dG->eraseFromParent(); } } // Reparent the global variable: sG->removeFromParent(); dest->getGlobalList().push_back(sG); // Comdat is owned by the Module, recreate it in the new parent: addComdat(sG); } for (Module::iterator I = src->begin(), E = src->end(); I != E;) { Function *sG = &*I; GlobalValue *dG = dest->getNamedValue(sG->getName()); ++I; // Replace a declaration with the definition: if (dG) { if (sG->isDeclaration()) { sG->replaceAllUsesWith(dG); sG->eraseFromParent(); continue; } else { dG->replaceAllUsesWith(sG); dG->eraseFromParent(); } } // Reparent the global variable: sG->removeFromParent(); dest->getFunctionList().push_back(sG); // Comdat is owned by the Module, recreate it in the new parent: addComdat(sG); } for (Module::alias_iterator I = src->alias_begin(), E = src->alias_end(); I != E;) { GlobalAlias *sG = &*I; GlobalValue *dG = dest->getNamedValue(sG->getName()); ++I; if (dG) { if (!dG->isDeclaration()) { // aliases are always definitions, so this test is reversed from the above two sG->replaceAllUsesWith(dG); sG->eraseFromParent(); continue; } else { dG->replaceAllUsesWith(sG); dG->eraseFromParent(); } } sG->removeFromParent(); dest->getAliasList().push_back(sG); } // metadata nodes need to be explicitly merged not just copied // so there are special passes here for each known type of metadata NamedMDNode *sNMD = src->getNamedMetadata("llvm.dbg.cu"); if (sNMD) { NamedMDNode *dNMD = dest->getOrInsertNamedMetadata("llvm.dbg.cu"); #ifdef LLVM35 for (NamedMDNode::op_iterator I = sNMD->op_begin(), E = sNMD->op_end(); I != E; ++I) { dNMD->addOperand(*I); } #else for (unsigned i = 0, l = sNMD->getNumOperands(); i < l; i++) { dNMD->addOperand(sNMD->getOperand(i)); } #endif } }
void CalculateReachingDefs(const std::unique_ptr<clang::CFG>& fn_cfg) { using bb_defs_map = llvm::DenseMap< const clang::CFGBlock*, defs_map >; defs_map all_defs = CollectAllDefs(fn_cfg); stmt_varref_map uses = CollectUses(fn_cfg); /* llvm::outs() << "stmt n uses:\n"; for (auto e : uses) { clang::LangOptions LangOpts; clang::PrintingPolicy Policy(LangOpts); const Stmt* stmt = e.first; stmt->printPretty(llvm::outs(), 0, Policy); llvm::outs() << ":\n"; for (auto u : e.second) { u->printPretty(llvm::outs(), 0, Policy); llvm::outs() << " "; } llvm::outs() << "\n"; } llvm::outs() << "\n";*/ bb_defs_map reach_out; bb_defs_map kills, gens; // local calculations (each block) for gen and kill for (auto itr = fn_cfg->begin(); itr != fn_cfg->end(); ++itr) { const clang::CFGBlock* b = *itr; // calculate gen, kill defs_map g = CalculateGen(b); defs_map k = CalculateKill(b, all_defs); /* llvm::outs() << b->getBlockID() << ": \n"; llvm::outs() << "~~~~~~~~~~gens~~~~~~~~~~~\n"; for (auto e: g) { if(const clang::VarDecl* vdecl = llvm::dyn_cast<clang::VarDecl>(e.first)) { llvm::outs() << vdecl->getNameAsString() << ": "; for (const Stmt* s : e.second) { s->dumpPretty(*ast_ctx); llvm::outs() << " "; } llvm::outs() << "\n"; } } llvm::outs() << "\n~~~~~~~~~~kills~~~~~~~~~~~\n"; for (auto e: k) { if(const clang::VarDecl* vdecl = llvm::dyn_cast<clang::VarDecl>(e.first)) { llvm::outs() << vdecl->getNameAsString() << ": "; for (const Stmt* s : e.second) { s->dumpPretty(*ast_ctx); llvm::outs() << " "; } llvm::outs() << "\n"; } } llvm::outs() << "--------------------\n\n"; */ kills[b] = k; gens[b] = g; reach_out[b] = defs_map(); } // global calculations on the entier cfg bool changed = true; while(changed) { changed = false; for (auto itr = fn_cfg->rbegin(); itr != fn_cfg->rend(); ++itr) { const clang::CFGBlock* b = *itr; auto newreaches = reach_out[b]; defs_map reach_in; for (auto p_itr = b->pred_begin(); p_itr != b->pred_end(); ++p_itr) { const clang::CFGBlock* p = *p_itr; for (auto d : reach_out[p]) { const clang::Decl* def_decl = d.first; for (const clang::Stmt* stmt: d.second) { reach_in[def_decl].insert(stmt); } } } /* llvm::outs() << "processing " << b->getBlockID() << "...\n"; llvm::outs() << "-------------reach_in-----------\n"; print_defs(reach_in); llvm::outs() << "-------------kills-----------\n"; print_defs(kills[b]); llvm::outs() << "-------------gens-----------\n"; print_defs(gens[b]);*/ // newreaches = gen U (reach_in - kill) auto diff = def_diff(reach_in, kills[b]); auto gen_u_diff = def_union(gens[b], diff); newreaches = def_union(newreaches, gen_u_diff); /* llvm::outs() << "-------------diff-----------\n"; print_defs(diff);*/ newreaches = def_union(gens[b], diff); /* llvm::outs() << "-------------newreaches-----------\n"; print_defs(newreaches);*/ if (!equals(newreaches, reach_out[b])) { /* llvm::outs() << b->getBlockID() << ":\n"; llvm::outs() << "~~~~~~~~~~~~~~~newreaches~~~~~~~~~~~\n"; for (auto e : newreaches) { if(const clang::VarDecl* vdecl = llvm::dyn_cast<clang::VarDecl>(e.first)) { llvm::outs() << vdecl->getNameAsString() << ": "; for (const Stmt* s : e.second) { s->dumpPretty(*ast_ctx); llvm::outs() << "\n"; } llvm::outs() << "\n"; } } llvm::outs() << "\n"; llvm::outs() << "~~~~~~~~~~~~~~~reaches~~~~~~~~~~~\n"; for (auto e : reaches[b]) { if(const clang::VarDecl* vdecl = llvm::dyn_cast<clang::VarDecl>(e.first)) { llvm::outs() << vdecl->getNameAsString() << ": "; for (const Stmt* s : e.second) { s->dumpPretty(*ast_ctx); llvm::outs() << "\n"; } llvm::outs() << "\n"; } } llvm::outs() << "\n"; */ reach_out[b] = newreaches; changed = true; } } } // end while /* llvm::outs() << "\n\n~~~~~~~~~~~~~~~~~~reaches~~~~~~~~~~~~~~~~~~~\n"; for (auto r_e : reaches) { llvm::outs() << r_e.first->getBlockID() << ":\n"; llvm::outs() << "--------------------------------------------\n"; for (auto e : r_e.second) { if(const clang::VarDecl* vdecl = llvm::dyn_cast<clang::VarDecl>(e.first)) { llvm::outs() << vdecl->getNameAsString() << ": \n"; for (const Stmt* s : e.second) { s->dumpPretty(*ast_ctx); llvm::outs() << "\n"; } llvm::outs() << "\n"; } } llvm::outs() << "--------------------------------------------\n\n"; }*/ bb_defs_map reach_in; for (auto itr = fn_cfg->rbegin(); itr != fn_cfg->rend(); ++itr) { const clang::CFGBlock* bb = *itr; defs_map d_in; for (auto p_itr = bb->pred_begin(); p_itr != bb->pred_end(); ++p_itr) { const clang::CFGBlock* p = *p_itr; for (auto d : reach_out[p]) { const clang::Decl* def_decl = d.first; std::copy(d.second.begin(), d.second.end(), std::inserter(d_in[def_decl], d_in[def_decl].begin())); } } reach_in[bb] = d_in; } /* llvm::outs() << "\n\n~~~~~~~~~~~~~~~~~~reach_in~~~~~~~~~~~~~~~~~~~\n"; for (auto r_e : reach_in) { llvm::outs() << r_e.first->getBlockID() << ":\n"; llvm::outs() << "--------------------------------------------\n"; for (auto e : r_e.second) { if(const clang::VarDecl* vdecl = llvm::dyn_cast<clang::VarDecl>(e.first)) { llvm::outs() << vdecl->getNameAsString() << ": \n"; for (const Stmt* s : e.second) { s->dumpPretty(*ast_ctx); llvm::outs() << "\n"; } llvm::outs() << "\n"; } } llvm::outs() << "--------------------------------------------\n\n"; }*/ // build use-def chains, need to calculate defs that reach uses locally llvm::DenseMap< const clang::DeclRefExpr*, const_stmt_set > use_def_chain; for (auto itr = fn_cfg->rbegin(); itr != fn_cfg->rend(); ++itr) { const clang::CFGBlock* bb = *itr; // get reach_in defs_map r_in = reach_in[bb]; // go over the block and build use_def_chain for each use for (const clang::CFGElement e : *bb) { switch(e.getKind()) { case clang::CFGElement::Statement: { const Stmt *stmt = e.castAs<CFGStmt>().getStmt(); // for all uses in this stmt, update use_def_chain for (auto u : uses[stmt]) { use_def_chain[u] = r_in[u->getDecl()]; } // if stmt is a def, remove all killed defs from r_in // we determine if the statement is a def by searching for this statement in all_defs for (auto e : all_defs) { if (std::find(e.second.begin(), e.second.end(), stmt) != e.second.end()) { // stmt us a def! const_stmt_set s; s.insert(stmt); r_in[e.first] = s; } } break; } default: llvm_unreachable("cfg element not handled..."); } } } // SourceManager sm = TheRewriter.getSourceMgr(); // print def use info for (auto itr = fn_cfg->rbegin(); itr != fn_cfg->rend(); ++itr) { const clang::CFGBlock* bb = *itr; llvm::outs() << "-----------------------BB#" << bb->getBlockID() << "-----------------------\n"; for (const clang::CFGElement e : *bb) { if (const Stmt *stmt = e.castAs<CFGStmt>().getStmt()) { auto stmt_line = TheRewriter.getSourceMgr().getPresumedLineNumber(stmt->getLocStart()); llvm::outs() << "stmt line#" << stmt_line << ": "; for (auto u : uses[stmt]) { for (auto def_stmt : use_def_chain[u]) { auto def_stmt_line = TheRewriter.getSourceMgr().getPresumedLineNumber(def_stmt->getLocStart()); llvm::outs() << def_stmt_line << " "; } } llvm::outs() << "\n"; } } llvm::outs() << "----------------------------------------------\n\n"; } }
void CalculateControlDependence(const std::unique_ptr<clang::CFG>& fn_cfg) const { std::deque<CFGBlock*> wlist; std::copy(fn_cfg->begin(), fn_cfg->end(), std::back_inserter(wlist)); /* const CFGBlock entry = fn_cfg->getEntry(); const CFGBlock exit = fn_cfg->getExit(); for (CFG::const_iterator itr = fn_cfg->begin(); itr != fn_cfg->end(); ++itr) { const CFGBlock blk = *itr; } while(!wlist.empty()) { CFGBlock* blk = wlist.front(); wlist.pop_front(); // if dataflow state changes, add successors for (const CFGElement e : *blk) { switch(e.getKind()) { case CFGElement::Statement: { break; } default: { llvm_unreachable("CFGElement"); } } } } */ // DominatorTree dt; // AnalysisDeclContextManager adcm; // AnalysisDeclContext adc(&adcm, fdecl); // dt.buildDominatorTree(adc); // fn_cfg.get()->print(llvm::outs(), LangOptions(), true); // llvm::outs() << "\n"; llvm::DominatorTreeBase< clang::CFGBlock > pdomtree(true); pdomtree.recalculate(*(fn_cfg.get())); // pdomtree.print(llvm::outs()); /* CFGBlock* root = pdomtree.getRoot(); llvm::outs() << "root:\n"; root->dump(); llvm::outs() << "\n"; llvm::SmallVector< CFGBlock*, 10 > desc; pdomtree.getDescendants(root, desc); llvm::outs() << "desc:\n"; for (auto p : desc) { p->dump(); } llvm::outs() << "----------------------\n\n"; */ std::deque< dtnb_type* > pre_visit; // topologically sort postdom tree, which is equivalent to preorder traversal pre(pdomtree.getRootNode(), pre_visit); std::reverse(pre_visit.begin(), pre_visit.end()); llvm::outs() << "preorder: "; for (auto bid : pre_visit) { llvm::outs() << bid->getBlock()->getBlockID() << " "; } llvm::outs() << "\n"; // Allen Kennedy algo llvm::DenseMap< dtnb_type*, llvm::SmallPtrSet< dtnb_type*, 20 > > CD; while (!pre_visit.empty()) { dtnb_type* x = pre_visit.front(); pre_visit.pop_front(); for (CFGBlock::const_pred_iterator p_itr = x->getBlock()->pred_begin(); p_itr != x->getBlock()->pred_end(); ++p_itr) { CFGBlock* p = *p_itr; dtnb_type* y = pdomtree.getNode(p); if (y->getIDom() != x) CD[x].insert(y); } for (dtnb_type* z : *x) { for (dtnb_type* y : CD[z]) { if (y->getIDom() != x) CD[x].insert(y); } } } for (auto e : CD) { llvm::outs() << e.first->getBlock()->getBlockID() << ": "; for (auto cd : e.second) { llvm::outs() << cd->getBlock()->getBlockID() << " "; } llvm::outs() << "\n"; } }
void prepare_out() { cur_out.reset(bucket_data_mem::create(65536, 0)); str.next_out = (unsigned char*)cur_out->begin(); str.avail_out = 65536; }
void Viewer::mousePressEvent(QMouseEvent* event) { if (event->modifiers() & Qt::ShiftModifier) { qoglviewer::Vec P; qoglviewer::Vec Q; rayClick(event,P,Q); Vec3 A(P[0],P[1],P[2]); Vec3 B(Q[0],Q[1],Q[2]); drawer_->new_list(); switch(cell_picking) { case 0: { std::vector<Map2::Vertex> selected; cgogn::geometry::picking<Vec3>(map_,vertex_position_, A, B, selected); cgogn_log_info("picking_viewer") << "Selected vertices: "<< selected.size(); if (!selected.empty()) { drawer_->point_size_aa(4.0); drawer_->begin(GL_POINTS); // closest point in red drawer_->color3f(1.0,0.0,0.0); drawer_->vertex3fv(vertex_position_[selected[0]]); // others in yellow drawer_->color3f(1.0,1.0,0.0); for(uint32 i=1u;i<selected.size();++i) drawer_->vertex3fv(vertex_position_[selected[i]]); drawer_->end(); } } break; case 1: { std::vector<Map2::Edge> selected; cgogn::geometry::picking<Vec3>(map_, vertex_position_, A, B, selected); cgogn_log_info("picking_viewer") << "Selected edges: "<< selected.size(); if (!selected.empty()) { drawer_->line_width(2.0); drawer_->begin(GL_LINES); // closest face in red drawer_->color3f(1.0, 0.0, 0.0); cgogn::rendering::add_to_drawer<Vec3>(map_, selected[0], vertex_position_, drawer_.get()); // others in yellow drawer_->color3f(1.0, 1.0, 0.0); for(uint32 i = 1u; i < selected.size(); ++i) cgogn::rendering::add_to_drawer<Vec3>(map_, selected[i], vertex_position_, drawer_.get()); drawer_->end(); } } break; case 2: { std::vector<Map2::Face> selected; cgogn::geometry::picking<Vec3>(map_, vertex_position_, A, B, selected); cgogn_log_info("picking_viewer") << "Selected faces: "<< selected.size(); if (!selected.empty()) { drawer_->line_width(2.0); drawer_->begin(GL_LINES); // closest face in red drawer_->color3f(1.0, 0.0, 0.0); cgogn::rendering::add_to_drawer<Vec3>(map_, selected[0], vertex_position_, drawer_.get()); // others in yellow drawer_->color3f(1.0, 1.0, 0.0); for(uint32 i = 1u; i < selected.size(); ++i) cgogn::rendering::add_to_drawer<Vec3>(map_, selected[i], vertex_position_, drawer_.get()); drawer_->end(); } } break; case 3: { std::vector<Map2::Volume> selected; cgogn::geometry::picking<Vec3>(map_, vertex_position_, A, B, selected); cgogn_log_info("picking_viewer") << "Selected volumes: "<< selected.size(); if (!selected.empty()) { drawer_->line_width(2.0); drawer_->begin(GL_LINES); // closest face in red drawer_->color3f(1.0, 0.0, 0.0); cgogn::rendering::add_to_drawer<Vec3>(map_, selected[0], vertex_position_, drawer_.get()); // others in yellow drawer_->color3f(1.0, 1.0, 0.0); for(uint32 i = 1u; i < selected.size(); ++i) cgogn::rendering::add_to_drawer<Vec3>(map_, selected[i], vertex_position_, drawer_.get()); drawer_->end(); } } break; } drawer_->line_width(4.0); drawer_->begin(GL_LINES); drawer_->color3f(1.0, 0.0, 1.0); drawer_->vertex3fv(A); drawer_->vertex3fv(B); drawer_->end(); drawer_->end_list(); } QOGLViewer::mousePressEvent(event); }