Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,23 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
add_clang_executable(find-all-symbols
FindAllSymbolsMain.cpp
)
target_link_libraries(find-all-symbols
PRIVATE
clangAST
clangASTMatchers
clangBasic
clangFrontend
clangLex
clangTooling
findAllSymbols
)
install(TARGETS find-all-symbols
RUNTIME DESTINATION bin)
install(PROGRAMS run-find-all-symbols.py
DESTINATION share/clang
COMPONENT find-all-symbols)

View File

@@ -0,0 +1,152 @@
//===-- FindAllSymbolsMain.cpp - find all symbols tool ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "FindAllSymbolsAction.h"
#include "STLPostfixHeaderMap.h"
#include "SymbolInfo.h"
#include "SymbolReporter.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <mutex>
#include <set>
#include <string>
#include <system_error>
#include <vector>
using namespace clang::tooling;
using namespace llvm;
using SymbolInfo = clang::find_all_symbols::SymbolInfo;
// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static cl::OptionCategory FindAllSymbolsCategory("find_all_symbols options");
// CommonOptionsParser declares HelpMessage with a description of the common
// command-line options related to the compilation database and input files.
// It's nice to have this help message in all tools.
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nMore help text...");
static cl::opt<std::string> OutputDir("output-dir", cl::desc(R"(
The output directory for saving the results.)"),
cl::init("."),
cl::cat(FindAllSymbolsCategory));
static cl::opt<std::string> MergeDir("merge-dir", cl::desc(R"(
The directory for merging symbols.)"),
cl::init(""),
cl::cat(FindAllSymbolsCategory));
namespace clang {
namespace find_all_symbols {
class YamlReporter : public SymbolReporter {
public:
void reportSymbols(StringRef FileName,
const SymbolInfo::SignalMap &Symbols) override {
int FD;
SmallString<128> ResultPath;
llvm::sys::fs::createUniqueFile(
OutputDir + "/" + llvm::sys::path::filename(FileName) + "-%%%%%%.yaml",
FD, ResultPath);
llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true);
WriteSymbolInfosToStream(OS, Symbols);
}
};
bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) {
std::error_code EC;
SymbolInfo::SignalMap Symbols;
std::mutex SymbolMutex;
auto AddSymbols = [&](ArrayRef<SymbolAndSignals> NewSymbols) {
// Synchronize set accesses.
std::unique_lock<std::mutex> LockGuard(SymbolMutex);
for (const auto &Symbol : NewSymbols) {
Symbols[Symbol.Symbol] += Symbol.Signals;
}
};
// Load all symbol files in MergeDir.
{
llvm::ThreadPool Pool;
for (llvm::sys::fs::directory_iterator Dir(MergeDir, EC), DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
// Parse YAML files in parallel.
Pool.async(
[&AddSymbols](std::string Path) {
auto Buffer = llvm::MemoryBuffer::getFile(Path);
if (!Buffer) {
llvm::errs() << "Can't open " << Path << "\n";
return;
}
std::vector<SymbolAndSignals> Symbols =
ReadSymbolInfosFromYAML(Buffer.get()->getBuffer());
for (auto &Symbol : Symbols) {
// Only count one occurrence per file, to avoid spam.
Symbol.Signals.Seen = std::min(Symbol.Signals.Seen, 1u);
Symbol.Signals.Used = std::min(Symbol.Signals.Used, 1u);
}
// FIXME: Merge without creating such a heavy contention point.
AddSymbols(Symbols);
},
Dir->path());
}
}
llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None);
if (EC) {
llvm::errs() << "Can't open '" << OutputFile << "': " << EC.message()
<< '\n';
return false;
}
WriteSymbolInfosToStream(OS, Symbols);
return true;
}
} // namespace clang
} // namespace find_all_symbols
int main(int argc, const char **argv) {
CommonOptionsParser OptionsParser(argc, argv, FindAllSymbolsCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
std::vector<std::string> sources = OptionsParser.getSourcePathList();
if (sources.empty()) {
llvm::errs() << "Must specify at least one one source file.\n";
return 1;
}
if (!MergeDir.empty()) {
clang::find_all_symbols::Merge(MergeDir, sources[0]);
return 0;
}
clang::find_all_symbols::YamlReporter Reporter;
auto Factory =
llvm::make_unique<clang::find_all_symbols::FindAllSymbolsActionFactory>(
&Reporter, clang::find_all_symbols::getSTLPostfixHeaderMap());
return Tool.run(Factory.get());
}

View File

@@ -0,0 +1,124 @@
#!/usr/bin/env python
#
#=- run-find-all-symbols.py - Parallel find-all-symbols runner -*- python -*-=#
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===------------------------------------------------------------------------===#
"""
Parallel find-all-symbols runner
================================
Runs find-all-symbols over all files in a compilation database.
Example invocations.
- Run find-all-symbols on all files in the current working directory.
run-find-all-symbols.py <source-file>
Compilation database setup:
http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
"""
import argparse
import json
import multiprocessing
import os
import Queue
import shutil
import subprocess
import sys
import tempfile
import threading
def find_compilation_database(path):
"""Adjusts the directory until a compilation database is found."""
result = './'
while not os.path.isfile(os.path.join(result, path)):
if os.path.realpath(result) == '/':
print 'Error: could not find compilation database.'
sys.exit(1)
result += '../'
return os.path.realpath(result)
def MergeSymbols(directory, args):
"""Merge all symbol files (yaml) in a given directaory into a single file."""
invocation = [args.binary, '-merge-dir='+directory, args.saving_path]
subprocess.call(invocation)
print 'Merge is finished. Saving results in ' + args.saving_path
def run_find_all_symbols(args, tmpdir, build_path, queue):
"""Takes filenames out of queue and runs find-all-symbols on them."""
while True:
name = queue.get()
invocation = [args.binary, name, '-output-dir='+tmpdir, '-p='+build_path]
sys.stdout.write(' '.join(invocation) + '\n')
subprocess.call(invocation)
queue.task_done()
def main():
parser = argparse.ArgumentParser(description='Runs find-all-symbols over all'
'files in a compilation database.')
parser.add_argument('-binary', metavar='PATH',
default='./bin/find-all-symbols',
help='path to find-all-symbols binary')
parser.add_argument('-j', type=int, default=0,
help='number of instances to be run in parallel.')
parser.add_argument('-p', dest='build_path',
help='path used to read a compilation database.')
parser.add_argument('-saving-path', default='./find_all_symbols_db.yaml',
help='result saving path')
args = parser.parse_args()
db_path = 'compile_commands.json'
if args.build_path is not None:
build_path = args.build_path
else:
build_path = find_compilation_database(db_path)
tmpdir = tempfile.mkdtemp()
# Load the database and extract all files.
database = json.load(open(os.path.join(build_path, db_path)))
files = [entry['file'] for entry in database]
max_task = args.j
if max_task == 0:
max_task = multiprocessing.cpu_count()
try:
# Spin up a bunch of tidy-launching threads.
queue = Queue.Queue(max_task)
for _ in range(max_task):
t = threading.Thread(target=run_find_all_symbols,
args=(args, tmpdir, build_path, queue))
t.daemon = True
t.start()
# Fill the queue with files.
for name in files:
queue.put(name)
# Wait for all threads to be done.
queue.join()
MergeSymbols(tmpdir, args)
except KeyboardInterrupt:
# This is a sad hack. Unfortunately subprocess goes
# bonkers with ctrl-c and we start forking merrily.
print '\nCtrl-C detected, goodbye.'
os.kill(0, 9)
if __name__ == '__main__':
main()