//-------------------------------------------------------------------------------------- bool LoadDDSDataFromFile(const std::string & fileName, std::unique_ptr<uint8_t[]>& ddsData, DDS_HEADER** header, uint8_t** bitData, size_t* bitSize ) { int file = -1; bool ret = false; errno_t err = _sopen_s(&file, fileName.c_str(), _O_BINARY | _O_RDONLY, _SH_DENYNO, _S_IREAD | _S_IWRITE); if (err != 0) { PRINT_ERROR("Loading '%s' failed : cannot open the file ! (errno = %i)\n", fileName.c_str(), err); return false; } __int64 fileSize = _filelength(file); // File is too big for 32-bit allocation, so reject read if (fileSize > ULONG_MAX) { PRINT_ERROR("Loading '%s' failed : the file is too big!\n", fileName.c_str()); goto EXIT_PROC; } // Need at least enough data to fill the header and magic number to be a valid DDS if (fileSize < (sizeof(DDS_HEADER) + sizeof(DWORD))) { PRINT_ERROR("Loading '%s' failed : the file is too small!\n", fileName.c_str()); goto EXIT_PROC; } // create enough space for the file data ddsData.reset(new uint8_t[fileSize]); if (!ddsData) { PRINT_ERROR("Loading '%s' failed : out of memory!\n", fileName.c_str()); goto EXIT_PROC; } // read the data in uint32_t bytesread = 0; if ((bytesread = _read(file, ddsData.get(), (uint32_t)fileSize)) != fileSize) { PRINT_ERROR("Loading '%s' failed : read error (%li/%li byte(s) read)!\n", fileName.c_str(), bytesread, fileSize); goto EXIT_PROC; } // DDS files always start with the same magic number ("DDS ") uint32_t dwMagicNumber = *(const uint32_t*)(ddsData.get()); if (dwMagicNumber != DDS_MAGIC) { PRINT_ERROR("Loading '%s' failed : the file does not contain the DDS signature!\n", fileName.c_str()); goto EXIT_PROC; } DDS_HEADER* hdr = reinterpret_cast<DDS_HEADER*>(ddsData.get() + sizeof(uint32_t)); // Verify header to validate DDS file if (hdr->dwSize != sizeof(DDS_HEADER) || hdr->ddspf.dwSize != sizeof(DDS_PIXELFORMAT)) { PRINT_ERROR("Loading '%s' failed : wrong DDS header!\n", fileName.c_str()); goto EXIT_PROC; } ptrdiff_t offset = sizeof(uint32_t) + sizeof(DDS_HEADER); if (hdr->ddspf.dwFlags & DDS_FOURCC) { // Check for DX10 extension if (MAKEFOURCC('D', 'X', '1', '0') == hdr->ddspf.dwFourCC) { // Must be long enough for both headers and magic value if (fileSize < (sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10))) { PRINT_ERROR("Loading '%s' failed : the file should have the DXT10 header!\n", fileName.c_str()); goto EXIT_PROC; } offset += sizeof(DDS_HEADER_DXT10); } } // setup the pointers in the process request *header = hdr; *bitData = ddsData.get() + offset; *bitSize = fileSize - offset; ret = true; EXIT_PROC: if (file != -1) _close(file); return ret; }
T& ref() { assert(v); return * v.get(); }
inline JSONElement* JSONElement::Null(){ return jNull.get(); }
incounter* get_incounter() { return in.get(); }
bool operator!() const { return v.get() == nullptr; }
void PathDiagnosticConsumer::HandlePathDiagnostic( std::unique_ptr<PathDiagnostic> D) { if (!D || D->path.empty()) return; // We need to flatten the locations (convert Stmt* to locations) because // the referenced statements may be freed by the time the diagnostics // are emitted. D->flattenLocations(); // If the PathDiagnosticConsumer does not support diagnostics that // cross file boundaries, prune out such diagnostics now. if (!supportsCrossFileDiagnostics()) { // Verify that the entire path is from the same FileID. FileID FID; const SourceManager &SMgr = D->path.front()->getLocation().getManager(); SmallVector<const PathPieces *, 5> WorkList; WorkList.push_back(&D->path); SmallString<128> buf; llvm::raw_svector_ostream warning(buf); warning << "warning: Path diagnostic report is not generated. Current " << "output format does not support diagnostics that cross file " << "boundaries. Refer to --analyzer-output for valid output " << "formats\n"; while (!WorkList.empty()) { const PathPieces &path = *WorkList.pop_back_val(); for (const auto &I : path) { const PathDiagnosticPiece *piece = I.get(); FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc(); if (FID.isInvalid()) { FID = SMgr.getFileID(L); } else if (SMgr.getFileID(L) != FID) { llvm::errs() << warning.str(); return; } // Check the source ranges. ArrayRef<SourceRange> Ranges = piece->getRanges(); for (const auto &I : Ranges) { SourceLocation L = SMgr.getExpansionLoc(I.getBegin()); if (!L.isFileID() || SMgr.getFileID(L) != FID) { llvm::errs() << warning.str(); return; } L = SMgr.getExpansionLoc(I.getEnd()); if (!L.isFileID() || SMgr.getFileID(L) != FID) { llvm::errs() << warning.str(); return; } } if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece)) WorkList.push_back(&call->path); else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece)) WorkList.push_back(¯o->subPieces); } } if (FID.isInvalid()) return; // FIXME: Emit a warning? } // Profile the node to see if we already have something matching it llvm::FoldingSetNodeID profile; D->Profile(profile); void *InsertPos = nullptr; if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) { // Keep the PathDiagnostic with the shorter path. // Note, the enclosing routine is called in deterministic order, so the // results will be consistent between runs (no reason to break ties if the // size is the same). const unsigned orig_size = orig->full_size(); const unsigned new_size = D->full_size(); if (orig_size <= new_size) return; assert(orig != D.get()); Diags.RemoveNode(orig); delete orig; } Diags.InsertNode(D.release()); }
bool mapbuffer::add_submap( const tripoint &p, std::unique_ptr<submap> &sm ) { const bool result = add_submap( p, sm.get() ); sm.release(); return result; }
std::unique_lock<std::mutex> wait_for_data() { std::unique_lock<std::mutex> head_lock(head_mutex); data_cond.wait(head_lock, [&]{return head.get() != queue::get_tail();}); return std::move(head_lock); }
queue():head(new node),tail(head.get()) {}
void TestInterface::echoIOBuf(std::unique_ptr<folly::IOBuf>& ret, std::unique_ptr<folly::IOBuf> buf) { ret = std::move(buf); folly::io::Appender cursor(ret.get(), kEchoSuffix.size()); cursor.push(folly::StringPiece(kEchoSuffix.data(), kEchoSuffix.size())); }
void empty() { std::lock_guard<std::mutex> head_lock(head_mutex); return (head.get(0 == get_tail())); }
Worldmap* get_worldmap() { return worldmap.get(); }
void Subprocess::spawnInternal( std::unique_ptr<const char*[]> argv, const char* executable, Options& options, const std::vector<std::string>* env, int errFd) { // Parent work, pre-fork: create pipes std::vector<int> childFds; // Close all of the childFds as we leave this scope SCOPE_EXIT { // These are only pipes, closing them shouldn't fail for (int cfd : childFds) { CHECK_ERR(::close(cfd)); } }; int r; for (auto& p : options.fdActions_) { if (p.second == PIPE_IN || p.second == PIPE_OUT) { int fds[2]; // We're setting both ends of the pipe as close-on-exec. The child // doesn't need to reset the flag on its end, as we always dup2() the fd, // and dup2() fds don't share the close-on-exec flag. #if FOLLY_HAVE_PIPE2 // If possible, set close-on-exec atomically. Otherwise, a concurrent // Subprocess invocation can fork() between "pipe" and "fnctl", // causing FDs to leak. r = ::pipe2(fds, O_CLOEXEC); checkUnixError(r, "pipe2"); #else r = ::pipe(fds); checkUnixError(r, "pipe"); r = fcntl(fds[0], F_SETFD, FD_CLOEXEC); checkUnixError(r, "set FD_CLOEXEC"); r = fcntl(fds[1], F_SETFD, FD_CLOEXEC); checkUnixError(r, "set FD_CLOEXEC"); #endif pipes_.emplace_back(); Pipe& pipe = pipes_.back(); pipe.direction = p.second; int cfd; if (p.second == PIPE_IN) { // Child gets reading end pipe.pipe = folly::File(fds[1], /*owns_fd=*/ true); cfd = fds[0]; } else { pipe.pipe = folly::File(fds[0], /*owns_fd=*/ true); cfd = fds[1]; } p.second = cfd; // ensure it gets dup2()ed pipe.childFd = p.first; childFds.push_back(cfd); } } // This should already be sorted, as options.fdActions_ is DCHECK(std::is_sorted(pipes_.begin(), pipes_.end())); // Note that the const casts below are legit, per // http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html char** argVec = const_cast<char**>(argv.get()); // Set up environment std::unique_ptr<const char*[]> envHolder; char** envVec; if (env) { envHolder = cloneStrings(*env); envVec = const_cast<char**>(envHolder.get()); } else { envVec = environ; } // Block all signals around vfork; see http://ewontfix.com/7/. // // As the child may run in the same address space as the parent until // the actual execve() system call, any (custom) signal handlers that // the parent has might alter parent's memory if invoked in the child, // with undefined results. So we block all signals in the parent before // vfork(), which will cause them to be blocked in the child as well (we // rely on the fact that Linux, just like all sane implementations, only // clones the calling thread). Then, in the child, we reset all signals // to their default dispositions (while still blocked), and unblock them // (so the exec()ed process inherits the parent's signal mask) // // The parent also unblocks all signals as soon as vfork() returns. sigset_t allBlocked; r = sigfillset(&allBlocked); checkUnixError(r, "sigfillset"); sigset_t oldSignals; r = pthread_sigmask(SIG_SETMASK, &allBlocked, &oldSignals); checkPosixError(r, "pthread_sigmask"); SCOPE_EXIT { // Restore signal mask r = pthread_sigmask(SIG_SETMASK, &oldSignals, nullptr); CHECK_EQ(r, 0) << "pthread_sigmask: " << errnoStr(r); // shouldn't fail }; // Call c_str() here, as it's not necessarily safe after fork. const char* childDir = options.childDir_.empty() ? nullptr : options.childDir_.c_str(); pid_t pid = vfork(); if (pid == 0) { int errnoValue = prepareChild(options, &oldSignals, childDir); if (errnoValue != 0) { childError(errFd, kChildFailure, errnoValue); } errnoValue = runChild(executable, argVec, envVec, options); // If we get here, exec() failed. childError(errFd, kExecFailure, errnoValue); } // In parent. Make sure vfork() succeeded. checkUnixError(pid, errno, "vfork"); // Child is alive. We have to be very careful about throwing after this // point. We are inside the constructor, so if we throw the Subprocess // object will have never existed, and the destructor will never be called. // // We should only throw if we got an error via the errFd, and we know the // child has exited and can be immediately waited for. In all other cases, // we have no way of cleaning up the child. pid_ = pid; returnCode_ = ProcessReturnCode(RV_RUNNING); }
beast::insight::Group::ptr const& group (std::string const& name) override { return m_groups->get (name); }
/// This is the predicate function used to check to see if the "Test" portion of /// the program is miscompiled by the code generator under test. If so, return /// true. In any case, both module arguments are deleted. /// static bool TestCodeGenerator(BugDriver &BD, std::unique_ptr<Module> Test, std::unique_ptr<Module> Safe, std::string &Error) { CleanupAndPrepareModules(BD, Test, Safe.get()); SmallString<128> TestModuleBC; int TestModuleFD; std::error_code EC = sys::fs::createTemporaryFile("bugpoint.test", "bc", TestModuleFD, TestModuleBC); if (EC) { errs() << BD.getToolName() << "Error making unique filename: " << EC.message() << "\n"; exit(1); } if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test.get())) { errs() << "Error writing bitcode to `" << TestModuleBC.str() << "'\nExiting."; exit(1); } FileRemover TestModuleBCRemover(TestModuleBC.str(), !SaveTemps); // Make the shared library SmallString<128> SafeModuleBC; int SafeModuleFD; EC = sys::fs::createTemporaryFile("bugpoint.safe", "bc", SafeModuleFD, SafeModuleBC); if (EC) { errs() << BD.getToolName() << "Error making unique filename: " << EC.message() << "\n"; exit(1); } if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe.get())) { errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting."; exit(1); } FileRemover SafeModuleBCRemover(SafeModuleBC.str(), !SaveTemps); std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error); if (!Error.empty()) return false; FileRemover SharedObjectRemover(SharedObject, !SaveTemps); // Run the code generator on the `Test' code, loading the shared library. // The function returns whether or not the new output differs from reference. bool Result = BD.diffProgram(BD.getProgram(), TestModuleBC.str(), SharedObject, false, &Error); if (!Error.empty()) return false; if (Result) errs() << ": still failing!\n"; else errs() << ": didn't fail.\n"; return Result; }
void fun(std::promise<std::string> pr, std::unique_ptr<int> uptr) { std::cout << (void *)(uptr.get()) << std::endl; std::cout << "Worker sending.\n"; pr.set_value("Message from thread."); }
static void test_grid() { /* An empty grid behaves the same as a control so test here. */ test_control<gui2::grid>(); //std::cerr << __func__ << ": Detailed test.\n"; /* Test the child part here. */ gui2::grid grid(2 ,2); add_widget(grid, new gui2::label(), "(1,1)", 0, 0); add_widget(grid, new gui2::label(), "(1,2)", 0, 1); add_widget(grid, new gui2::label(), "(2,1)", 1, 0); add_widget(grid, new gui2::label(), "(2,2)", 1, 1); const std::unique_ptr<gui2::iteration::walker_base> visitor(grid.create_walker()); /***** LABEL 1,1 *****/ BOOST_CHECK_EQUAL(visitor->at_end(gui2::iteration::walker_base::child), false); BOOST_REQUIRE_NE(visitor->get(gui2::iteration::walker_base::child), static_cast<void*>(nullptr)); BOOST_CHECK_EQUAL(visitor->get(gui2::iteration::walker_base::child)->id(), "(1,1)"); /***** LABEL 2,1 *****/ BOOST_CHECK_EQUAL(visitor->next(gui2::iteration::walker_base::child), gui2::iteration::walker_base::valid); BOOST_CHECK_EQUAL(visitor->at_end(gui2::iteration::walker_base::child), false); BOOST_REQUIRE_NE(visitor->get(gui2::iteration::walker_base::child), static_cast<void*>(nullptr)); BOOST_CHECK_EQUAL(visitor->get(gui2::iteration::walker_base::child)->id(), "(2,1)"); /***** LABEL 1,2 *****/ BOOST_CHECK_EQUAL(visitor->next(gui2::iteration::walker_base::child), gui2::iteration::walker_base::valid); BOOST_CHECK_EQUAL(visitor->at_end(gui2::iteration::walker_base::child), false); BOOST_REQUIRE_NE(visitor->get(gui2::iteration::walker_base::child), static_cast<void*>(nullptr)); BOOST_CHECK_EQUAL(visitor->get(gui2::iteration::walker_base::child)->id(), "(1,2)"); /***** LABEL 2,2 *****/ BOOST_CHECK_EQUAL(visitor->next(gui2::iteration::walker_base::child), gui2::iteration::walker_base::valid); BOOST_CHECK_EQUAL(visitor->at_end(gui2::iteration::walker_base::child), false); BOOST_REQUIRE_NE(visitor->get(gui2::iteration::walker_base::child), static_cast<void*>(nullptr)); BOOST_CHECK_EQUAL(visitor->get(gui2::iteration::walker_base::child)->id(), "(2,2)"); /***** END *****/ BOOST_CHECK_EQUAL(visitor->next(gui2::iteration::walker_base::child), gui2::iteration::walker_base::invalid); BOOST_CHECK_EQUAL(visitor->at_end(gui2::iteration::walker_base::child), true); BOOST_CHECK_EQUAL(visitor->get(gui2::iteration::walker_base::child), static_cast<void*>(nullptr)); /***** POST END *****/ BOOST_CHECK_EQUAL(visitor->next(gui2::iteration::walker_base::child), gui2::iteration::walker_base::fail); }
Iterator* operator->() { return impl.get(); }
parameter_base* get_parameter() const final override { return m_parameter.get(); }
SearchModel* GetSearchModel() { static std::unique_ptr<SearchModel> model(new SearchModel(0)); return model.get(); }
T* data() const { return m_data.get(); }
/** * Setups the game environment and enters * the titlescreen or game loops. */ static int do_gameloop(const std::vector<std::string>& args) { srand(time(nullptr)); commandline_options cmdline_opts = commandline_options(args); game_config::wesnoth_program_dir = filesystem::directory_name(args[0]); int finished = process_command_args(cmdline_opts); if(finished != -1) { return finished; } const std::unique_ptr<game_launcher> game( new game_launcher(cmdline_opts,args[0].c_str())); const int start_ticks = SDL_GetTicks(); init_locale(); bool res; // do initialize fonts before reading the game config, to have game // config error messages displayed. fonts will be re-initialized later // when the language is read from the game config. res = font::load_font_config(); if(res == false) { std::cerr << "could not initialize fonts\n"; // The most common symptom of a bogus data dir path -- warn the user. warn_early_init_failure(); return 1; } res = game->init_language(); if(res == false) { std::cerr << "could not initialize the language\n"; return 1; } res = game->init_video(); if(res == false) { std::cerr << "could not initialize display\n"; return 1; } res = image::update_from_preferences(); if(res == false) { std::cerr << "could not initialize image preferences\n"; return 1; } if(preferences::joystick_support_enabled()) { res = game->init_joystick(); if(res == false) { std::cerr << "could not initialize joystick\n"; } } check_fpu(); const cursor::manager cursor_manager; cursor::set(cursor::WAIT); #if (defined(_X11) && !defined(__APPLE__)) || defined(_WIN32) SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); #endif gui2::init(); const gui2::event::tmanager gui_event_manager; game_config_manager config_manager(cmdline_opts, game->video(), game->jump_to_editor()); gui2::tloadscreen::display(game->video(), [&res, &config_manager]() { gui2::tloadscreen::progress("load config"); res = config_manager.init_game_config(game_config_manager::NO_FORCE_RELOAD); if(res == false) { std::cerr << "could not initialize game config\n"; return; } gui2::tloadscreen::progress("init fonts"); res = font::load_font_config(); if(res == false) { std::cerr << "could not re-initialize fonts for the current language\n"; return; } gui2::tloadscreen::progress("refresh addons"); refresh_addon_version_info_cache(); }); if(res == false) { return 1; } LOG_CONFIG << "time elapsed: "<< (SDL_GetTicks() - start_ticks) << " ms\n"; plugins_manager plugins_man(new application_lua_kernel(&game->video())); plugins_context::Reg const callbacks[] = { { "play_multiplayer", std::bind(&game_launcher::play_multiplayer, game.get(), game_launcher::MP_CONNECT)}, }; plugins_context::aReg const accessors[] = { { "command_line", std::bind(&commandline_options::to_config, &cmdline_opts)}, }; plugins_context plugins("titlescreen", callbacks, accessors); plugins.set_callback("exit", [](const config& cfg) { safe_exit(cfg["code"].to_int(0)); }, false); for (;;) { // reset the TC, since a game can modify it, and it may be used // by images in add-ons or campaigns dialogs image::set_team_colors(); statistics::fresh_stats(); if (!game->is_loading()) { const config &cfg = config_manager.game_config().child("titlescreen_music"); if (cfg) { sound::play_music_repeatedly(game_config::title_music); for (const config &i : cfg.child_range("music")) { sound::play_music_config(i); } sound::commit_music_changes(); } else { sound::empty_playlist(); sound::stop_music(); } } handle_lua_script_args(&*game,cmdline_opts); plugins.play_slice(); plugins.play_slice(); if(cmdline_opts.unit_test) { if(cmdline_opts.timeout) { std::cerr << "The wesnoth built-in timeout feature has been removed.\n" << std::endl; std::cerr << "Please use a platform-specific script which will kill the overtime process instead.\n" << std::endl; std::cerr << "For examples in bash, or in windows cmd, see the forums, or the wesnoth repository." << std::endl; std::cerr << "The bash script is called `run_wml_tests`, the windows script is part of the VC project.\n" << std::endl; } int worker_result = game->unit_test(); std::cerr << ((worker_result == 0) ? "PASS TEST " : "FAIL TEST ") << ((worker_result == 3) ? "(INVALID REPLAY)" : "") << ((worker_result == 4) ? "(ERRORED REPLAY)" : "") << ": "<<*cmdline_opts.unit_test << std::endl; return worker_result; } if(game->play_test() == false) { return 0; } if(game->play_screenshot_mode() == false) { return 0; } if(game->play_render_image_mode() == false) { return 0; } //Start directly a campaign if(game->goto_campaign() == false){ if (game->jump_to_campaign_id().empty()) continue; //Go to main menu else return 1; //we got an error starting the campaign from command line } //Start directly a multiplayer //Eventually with a specified server if(game->goto_multiplayer() == false){ continue; //Go to main menu } //Start directly a commandline multiplayer game if(game->play_multiplayer_commandline() == false) { return 0; } if (game->goto_editor() == false) { return 0; } preferences::load_hotkeys(); const font::floating_label_context label_manager; cursor::set(cursor::NORMAL); game_launcher::RELOAD_GAME_DATA should_reload = game_launcher::RELOAD_DATA; // If loading a game, skip the titlescreen entirely if(game->is_loading()) { if(!game->load_game()) { game->clear_loaded_game(); } game->launch_game(should_reload); continue; } gui2::ttitle_screen::tresult res = gui2::ttitle_screen::display(*game); switch(res) { case gui2::ttitle_screen::QUIT_GAME: LOG_GENERAL << "quitting game...\n"; return 0; case gui2::ttitle_screen::MP_CONNECT: game_config::debug = game_config::mp_debug; if(!game->play_multiplayer(game_launcher::MP_CONNECT)) { continue; } break; case gui2::ttitle_screen::MP_HOST: game_config::debug = game_config::mp_debug; if(!game->play_multiplayer(game_launcher::MP_HOST)) { continue; } break; case gui2::ttitle_screen::MP_LOCAL: game_config::debug = game_config::mp_debug; if(!game->play_multiplayer(game_launcher::MP_LOCAL)) { continue; } break; case gui2::ttitle_screen::RELOAD_GAME_DATA: gui2::tloadscreen::display(game->video(), [&config_manager]() { config_manager.reload_changed_game_config(); image::flush_cache(); }); break; case gui2::ttitle_screen::MAP_EDITOR: game->start_editor(); break; case gui2::ttitle_screen::SHOW_ABOUT: gui2::tend_credits::display(game->video()); break; case gui2::ttitle_screen::LAUNCH_GAME: game->launch_game(should_reload); break; case gui2::ttitle_screen::REDRAW_BACKGROUND: // Do nothing break; } } }
operator bool() const { return v.get() != nullptr; };
ConstrainedFileStream::ConstrainedFileStream(std::unique_ptr<std::streambuf> buf) : std::istream(buf.get()) , mBuf(std::move(buf)) { }
T* get() { return v.get(); }
virtual value_type get() const override final { return ::cranberries::apply(expr_, gen_->get()); }
ssize_t WindowsUdpSocket::Send(const void* data, size_t len) { return sendto(sock_, reinterpret_cast<const char*>(data), len, 0, reinterpret_cast<sockaddr*>(addr_.get()), addr_size_); }
/// Get the specified modules ready for code generator testing. /// static void CleanupAndPrepareModules(BugDriver &BD, std::unique_ptr<Module> &Test, Module *Safe) { // Clean up the modules, removing extra cruft that we don't need anymore... Test = BD.performFinalCleanups(Test.get()); // If we are executing the JIT, we have several nasty issues to take care of. if (!BD.isExecutingJIT()) return; // First, if the main function is in the Safe module, we must add a stub to // the Test module to call into it. Thus, we create a new function `main' // which just calls the old one. if (Function *oldMain = Safe->getFunction("main")) if (!oldMain->isDeclaration()) { // Rename it oldMain->setName("llvm_bugpoint_old_main"); // Create a NEW `main' function with same type in the test module. Function *newMain = Function::Create(oldMain->getFunctionType(), GlobalValue::ExternalLinkage, "main", Test.get()); // Create an `oldmain' prototype in the test module, which will // corresponds to the real main function in the same module. Function *oldMainProto = Function::Create(oldMain->getFunctionType(), GlobalValue::ExternalLinkage, oldMain->getName(), Test.get()); // Set up and remember the argument list for the main function. std::vector<Value*> args; for (Function::arg_iterator I = newMain->arg_begin(), E = newMain->arg_end(), OI = oldMain->arg_begin(); I != E; ++I, ++OI) { I->setName(OI->getName()); // Copy argument names from oldMain args.push_back(&*I); } // Call the old main function and return its result BasicBlock *BB = BasicBlock::Create(Safe->getContext(), "entry", newMain); CallInst *call = CallInst::Create(oldMainProto, args, "", BB); // If the type of old function wasn't void, return value of call ReturnInst::Create(Safe->getContext(), call, BB); } // The second nasty issue we must deal with in the JIT is that the Safe // module cannot directly reference any functions defined in the test // module. Instead, we use a JIT API call to dynamically resolve the // symbol. // Add the resolver to the Safe module. // Prototype: void *getPointerToNamedFunction(const char* Name) Constant *resolverFunc = Safe->getOrInsertFunction("getPointerToNamedFunction", Type::getInt8PtrTy(Safe->getContext()), Type::getInt8PtrTy(Safe->getContext()), (Type *)nullptr); // Use the function we just added to get addresses of functions we need. for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) { if (F->isDeclaration() && !F->use_empty() && &*F != resolverFunc && !F->isIntrinsic() /* ignore intrinsics */) { Function *TestFn = Test->getFunction(F->getName()); // Don't forward functions which are external in the test module too. if (TestFn && !TestFn->isDeclaration()) { // 1. Add a string constant with its name to the global file Constant *InitArray = ConstantDataArray::getString(F->getContext(), F->getName()); GlobalVariable *funcName = new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/, GlobalValue::InternalLinkage, InitArray, F->getName() + "_name"); // 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an // sbyte* so it matches the signature of the resolver function. // GetElementPtr *funcName, ulong 0, ulong 0 std::vector<Constant*> GEPargs(2, Constant::getNullValue(Type::getInt32Ty(F->getContext()))); Value *GEP = ConstantExpr::getGetElementPtr(InitArray->getType(), funcName, GEPargs); std::vector<Value*> ResolverArgs; ResolverArgs.push_back(GEP); // Rewrite uses of F in global initializers, etc. to uses of a wrapper // function that dynamically resolves the calls to F via our JIT API if (!F->use_empty()) { // Create a new global to hold the cached function pointer. Constant *NullPtr = ConstantPointerNull::get(F->getType()); GlobalVariable *Cache = new GlobalVariable(*F->getParent(), F->getType(), false, GlobalValue::InternalLinkage, NullPtr,F->getName()+".fpcache"); // Construct a new stub function that will re-route calls to F FunctionType *FuncTy = F->getFunctionType(); Function *FuncWrapper = Function::Create(FuncTy, GlobalValue::InternalLinkage, F->getName() + "_wrapper", F->getParent()); BasicBlock *EntryBB = BasicBlock::Create(F->getContext(), "entry", FuncWrapper); BasicBlock *DoCallBB = BasicBlock::Create(F->getContext(), "usecache", FuncWrapper); BasicBlock *LookupBB = BasicBlock::Create(F->getContext(), "lookupfp", FuncWrapper); // Check to see if we already looked up the value. Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB); Value *IsNull = new ICmpInst(*EntryBB, ICmpInst::ICMP_EQ, CachedVal, NullPtr, "isNull"); BranchInst::Create(LookupBB, DoCallBB, IsNull, EntryBB); // Resolve the call to function F via the JIT API: // // call resolver(GetElementPtr...) CallInst *Resolver = CallInst::Create(resolverFunc, ResolverArgs, "resolver", LookupBB); // Cast the result from the resolver to correctly-typed function. CastInst *CastedResolver = new BitCastInst(Resolver, PointerType::getUnqual(F->getFunctionType()), "resolverCast", LookupBB); // Save the value in our cache. new StoreInst(CastedResolver, Cache, LookupBB); BranchInst::Create(DoCallBB, LookupBB); PHINode *FuncPtr = PHINode::Create(NullPtr->getType(), 2, "fp", DoCallBB); FuncPtr->addIncoming(CastedResolver, LookupBB); FuncPtr->addIncoming(CachedVal, EntryBB); // Save the argument list. std::vector<Value*> Args; for (Argument &A : FuncWrapper->args()) Args.push_back(&A); // Pass on the arguments to the real function, return its result if (F->getReturnType()->isVoidTy()) { CallInst::Create(FuncPtr, Args, "", DoCallBB); ReturnInst::Create(F->getContext(), DoCallBB); } else { CallInst *Call = CallInst::Create(FuncPtr, Args, "retval", DoCallBB); ReturnInst::Create(F->getContext(),Call, DoCallBB); } // Use the wrapper function instead of the old function F->replaceAllUsesWith(FuncWrapper); } } } } if (verifyModule(*Test) || verifyModule(*Safe)) { errs() << "Bugpoint has a bug, which corrupted a module!!\n"; abort(); } }
void StackFrameList::Merge (std::unique_ptr<StackFrameList>& curr_ap, lldb::StackFrameListSP& prev_sp) { Mutex::Locker curr_locker (curr_ap.get() ? &curr_ap->m_mutex : NULL); Mutex::Locker prev_locker (prev_sp.get() ? &prev_sp->m_mutex : NULL); #if defined (DEBUG_STACK_FRAMES) StreamFile s(stdout, false); s.PutCString("\n\nStackFrameList::Merge():\nPrev:\n"); if (prev_sp.get()) prev_sp->Dump (&s); else s.PutCString ("NULL"); s.PutCString("\nCurr:\n"); if (curr_ap.get()) curr_ap->Dump (&s); else s.PutCString ("NULL"); s.EOL(); #endif if (curr_ap.get() == NULL || curr_ap->GetNumFrames (false) == 0) { #if defined (DEBUG_STACK_FRAMES) s.PutCString("No current frames, leave previous frames alone...\n"); #endif curr_ap.release(); return; } if (prev_sp.get() == NULL || prev_sp->GetNumFrames (false) == 0) { #if defined (DEBUG_STACK_FRAMES) s.PutCString("No previous frames, so use current frames...\n"); #endif // We either don't have any previous frames, or since we have more than // one current frames it means we have all the frames and can safely // replace our previous frames. prev_sp.reset (curr_ap.release()); return; } const uint32_t num_curr_frames = curr_ap->GetNumFrames (false); if (num_curr_frames > 1) { #if defined (DEBUG_STACK_FRAMES) s.PutCString("We have more than one current frame, so use current frames...\n"); #endif // We have more than one current frames it means we have all the frames // and can safely replace our previous frames. prev_sp.reset (curr_ap.release()); #if defined (DEBUG_STACK_FRAMES) s.PutCString("\nMerged:\n"); prev_sp->Dump (&s); #endif return; } StackFrameSP prev_frame_zero_sp(prev_sp->GetFrameAtIndex (0)); StackFrameSP curr_frame_zero_sp(curr_ap->GetFrameAtIndex (0)); StackID curr_stack_id (curr_frame_zero_sp->GetStackID()); StackID prev_stack_id (prev_frame_zero_sp->GetStackID()); #if defined (DEBUG_STACK_FRAMES) const uint32_t num_prev_frames = prev_sp->GetNumFrames (false); s.Printf("\n%u previous frames with one current frame\n", num_prev_frames); #endif // We have only a single current frame // Our previous stack frames only had a single frame as well... if (curr_stack_id == prev_stack_id) { #if defined (DEBUG_STACK_FRAMES) s.Printf("\nPrevious frame #0 is same as current frame #0, merge the cached data\n"); #endif curr_frame_zero_sp->UpdateCurrentFrameFromPreviousFrame (*prev_frame_zero_sp); // prev_frame_zero_sp->UpdatePreviousFrameFromCurrentFrame (*curr_frame_zero_sp); // prev_sp->SetFrameAtIndex (0, prev_frame_zero_sp); } else if (curr_stack_id < prev_stack_id) { #if defined (DEBUG_STACK_FRAMES) s.Printf("\nCurrent frame #0 has a stack ID that is less than the previous frame #0, insert current frame zero in front of previous\n"); #endif prev_sp->m_frames.insert (prev_sp->m_frames.begin(), curr_frame_zero_sp); } curr_ap.release(); #if defined (DEBUG_STACK_FRAMES) s.PutCString("\nMerged:\n"); prev_sp->Dump (&s); #endif }
_T *ptr() const { return _M_ptr.get(); }