Remove files from vendor/llvm-project/master which are unused, and never

merged to contrib.
This commit is contained in:
Dimitry Andric 2020-01-17 20:27:24 +00:00
parent c80d8fac37
commit 7cc9cf2bf0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/llvm-project/master/; revision=356841
50 changed files with 0 additions and 3682 deletions

View File

@ -1,18 +0,0 @@
set(LLVM_LINK_COMPONENTS Support)
add_clang_library(clangTransformer
RangeSelector.cpp
RewriteRule.cpp
SourceCode.cpp
SourceCodeBuilders.cpp
Stencil.cpp
Transformer.cpp
LINK_LIBS
clangAST
clangASTMatchers
clangBasic
clangLex
clangToolingCore
clangToolingRefactoring
)

View File

@ -1,23 +0,0 @@
set(LLVM_LINK_COMPONENTS BitWriter Core Support TransformUtils)
if(NOT CLANG_BUILT_STANDALONE)
set(tablegen_deps intrinsics_gen)
endif()
add_clang_tool(clang-offload-wrapper
ClangOffloadWrapper.cpp
DEPENDS
${tablegen_deps}
)
set(CLANG_OFFLOAD_WRAPPER_LIB_DEPS
clangBasic
)
add_dependencies(clang clang-offload-wrapper)
clang_target_link_libraries(clang-offload-wrapper
PRIVATE
${CLANG_OFFLOAD_WRAPPER_LIB_DEPS}
)

View File

@ -1,371 +0,0 @@
//===-- clang-offload-wrapper/ClangOffloadWrapper.cpp -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implementation of the offload wrapper tool. It takes offload target binaries
/// as input and creates wrapper bitcode file containing target binaries
/// packaged as data. Wrapper bitcode also includes initialization code which
/// registers target binaries in offloading runtime at program startup.
///
//===----------------------------------------------------------------------===//
#include "clang/Basic/Version.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include <cassert>
#include <cstdint>
using namespace llvm;
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
// Mark all our options with this category, everything else (except for -version
// and -help) will be hidden.
static cl::OptionCategory
ClangOffloadWrapperCategory("clang-offload-wrapper options");
static cl::opt<std::string> Output("o", cl::Required,
cl::desc("Output filename"),
cl::value_desc("filename"),
cl::cat(ClangOffloadWrapperCategory));
static cl::list<std::string> Inputs(cl::Positional, cl::OneOrMore,
cl::desc("<input files>"),
cl::cat(ClangOffloadWrapperCategory));
static cl::opt<std::string>
Target("target", cl::Required,
cl::desc("Target triple for the output module"),
cl::value_desc("triple"), cl::cat(ClangOffloadWrapperCategory));
namespace {
class BinaryWrapper {
LLVMContext C;
Module M;
StructType *EntryTy = nullptr;
StructType *ImageTy = nullptr;
StructType *DescTy = nullptr;
private:
IntegerType *getSizeTTy() {
switch (M.getDataLayout().getPointerTypeSize(Type::getInt8PtrTy(C))) {
case 4u:
return Type::getInt32Ty(C);
case 8u:
return Type::getInt64Ty(C);
}
llvm_unreachable("unsupported pointer type size");
}
// struct __tgt_offload_entry {
// void *addr;
// char *name;
// size_t size;
// int32_t flags;
// int32_t reserved;
// };
StructType *getEntryTy() {
if (!EntryTy)
EntryTy = StructType::create("__tgt_offload_entry", Type::getInt8PtrTy(C),
Type::getInt8PtrTy(C), getSizeTTy(),
Type::getInt32Ty(C), Type::getInt32Ty(C));
return EntryTy;
}
PointerType *getEntryPtrTy() { return PointerType::getUnqual(getEntryTy()); }
// struct __tgt_device_image {
// void *ImageStart;
// void *ImageEnd;
// __tgt_offload_entry *EntriesBegin;
// __tgt_offload_entry *EntriesEnd;
// };
StructType *getDeviceImageTy() {
if (!ImageTy)
ImageTy = StructType::create("__tgt_device_image", Type::getInt8PtrTy(C),
Type::getInt8PtrTy(C), getEntryPtrTy(),
getEntryPtrTy());
return ImageTy;
}
PointerType *getDeviceImagePtrTy() {
return PointerType::getUnqual(getDeviceImageTy());
}
// struct __tgt_bin_desc {
// int32_t NumDeviceImages;
// __tgt_device_image *DeviceImages;
// __tgt_offload_entry *HostEntriesBegin;
// __tgt_offload_entry *HostEntriesEnd;
// };
StructType *getBinDescTy() {
if (!DescTy)
DescTy = StructType::create("__tgt_bin_desc", Type::getInt32Ty(C),
getDeviceImagePtrTy(), getEntryPtrTy(),
getEntryPtrTy());
return DescTy;
}
PointerType *getBinDescPtrTy() {
return PointerType::getUnqual(getBinDescTy());
}
/// Creates binary descriptor for the given device images. Binary descriptor
/// is an object that is passed to the offloading runtime at program startup
/// and it describes all device images available in the executable or shared
/// library. It is defined as follows
///
/// __attribute__((visibility("hidden")))
/// extern __tgt_offload_entry *__start_omp_offloading_entries;
/// __attribute__((visibility("hidden")))
/// extern __tgt_offload_entry *__stop_omp_offloading_entries;
///
/// static const char Image0[] = { <Bufs.front() contents> };
/// ...
/// static const char ImageN[] = { <Bufs.back() contents> };
///
/// static const __tgt_device_image Images[] = {
/// {
/// Image0, /*ImageStart*/
/// Image0 + sizeof(Image0), /*ImageEnd*/
/// __start_omp_offloading_entries, /*EntriesBegin*/
/// __stop_omp_offloading_entries /*EntriesEnd*/
/// },
/// ...
/// {
/// ImageN, /*ImageStart*/
/// ImageN + sizeof(ImageN), /*ImageEnd*/
/// __start_omp_offloading_entries, /*EntriesBegin*/
/// __stop_omp_offloading_entries /*EntriesEnd*/
/// }
/// };
///
/// static const __tgt_bin_desc BinDesc = {
/// sizeof(Images) / sizeof(Images[0]), /*NumDeviceImages*/
/// Images, /*DeviceImages*/
/// __start_omp_offloading_entries, /*HostEntriesBegin*/
/// __stop_omp_offloading_entries /*HostEntriesEnd*/
/// };
///
/// Global variable that represents BinDesc is returned.
GlobalVariable *createBinDesc(ArrayRef<ArrayRef<char>> Bufs) {
// Create external begin/end symbols for the offload entries table.
auto *EntriesB = new GlobalVariable(
M, getEntryTy(), /*isConstant*/ true, GlobalValue::ExternalLinkage,
/*Initializer*/ nullptr, "__start_omp_offloading_entries");
EntriesB->setVisibility(GlobalValue::HiddenVisibility);
auto *EntriesE = new GlobalVariable(
M, getEntryTy(), /*isConstant*/ true, GlobalValue::ExternalLinkage,
/*Initializer*/ nullptr, "__stop_omp_offloading_entries");
EntriesE->setVisibility(GlobalValue::HiddenVisibility);
// We assume that external begin/end symbols that we have created above will
// be defined by the linker. But linker will do that only if linker inputs
// have section with "omp_offloading_entries" name which is not guaranteed.
// So, we just create dummy zero sized object in the offload entries section
// to force linker to define those symbols.
auto *DummyInit =
ConstantAggregateZero::get(ArrayType::get(getEntryTy(), 0u));
auto *DummyEntry = new GlobalVariable(
M, DummyInit->getType(), true, GlobalVariable::ExternalLinkage,
DummyInit, "__dummy.omp_offloading.entry");
DummyEntry->setSection("omp_offloading_entries");
DummyEntry->setVisibility(GlobalValue::HiddenVisibility);
auto *Zero = ConstantInt::get(getSizeTTy(), 0u);
Constant *ZeroZero[] = {Zero, Zero};
// Create initializer for the images array.
SmallVector<Constant *, 4u> ImagesInits;
ImagesInits.reserve(Bufs.size());
for (ArrayRef<char> Buf : Bufs) {
auto *Data = ConstantDataArray::get(C, Buf);
auto *Image = new GlobalVariable(M, Data->getType(), /*isConstant*/ true,
GlobalVariable::InternalLinkage, Data,
".omp_offloading.device_image");
Image->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
auto *Size = ConstantInt::get(getSizeTTy(), Buf.size());
Constant *ZeroSize[] = {Zero, Size};
auto *ImageB = ConstantExpr::getGetElementPtr(Image->getValueType(),
Image, ZeroZero);
auto *ImageE = ConstantExpr::getGetElementPtr(Image->getValueType(),
Image, ZeroSize);
ImagesInits.push_back(ConstantStruct::get(getDeviceImageTy(), ImageB,
ImageE, EntriesB, EntriesE));
}
// Then create images array.
auto *ImagesData = ConstantArray::get(
ArrayType::get(getDeviceImageTy(), ImagesInits.size()), ImagesInits);
auto *Images =
new GlobalVariable(M, ImagesData->getType(), /*isConstant*/ true,
GlobalValue::InternalLinkage, ImagesData,
".omp_offloading.device_images");
Images->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
auto *ImagesB = ConstantExpr::getGetElementPtr(Images->getValueType(),
Images, ZeroZero);
// And finally create the binary descriptor object.
auto *DescInit = ConstantStruct::get(
getBinDescTy(),
ConstantInt::get(Type::getInt32Ty(C), ImagesInits.size()), ImagesB,
EntriesB, EntriesE);
return new GlobalVariable(M, DescInit->getType(), /*isConstant*/ true,
GlobalValue::InternalLinkage, DescInit,
".omp_offloading.descriptor");
}
void createRegisterFunction(GlobalVariable *BinDesc) {
auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
auto *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage,
".omp_offloading.descriptor_reg", &M);
Func->setSection(".text.startup");
// Get __tgt_register_lib function declaration.
auto *RegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(),
/*isVarArg*/ false);
FunctionCallee RegFuncC =
M.getOrInsertFunction("__tgt_register_lib", RegFuncTy);
// Construct function body
IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func));
Builder.CreateCall(RegFuncC, BinDesc);
Builder.CreateRetVoid();
// Add this function to constructors.
appendToGlobalCtors(M, Func, 0);
}
void createUnregisterFunction(GlobalVariable *BinDesc) {
auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false);
auto *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage,
".omp_offloading.descriptor_unreg", &M);
Func->setSection(".text.startup");
// Get __tgt_unregister_lib function declaration.
auto *UnRegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(),
/*isVarArg*/ false);
FunctionCallee UnRegFuncC =
M.getOrInsertFunction("__tgt_unregister_lib", UnRegFuncTy);
// Construct function body
IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func));
Builder.CreateCall(UnRegFuncC, BinDesc);
Builder.CreateRetVoid();
// Add this function to global destructors.
appendToGlobalDtors(M, Func, 0);
}
public:
BinaryWrapper(StringRef Target) : M("offload.wrapper.object", C) {
M.setTargetTriple(Target);
}
const Module &wrapBinaries(ArrayRef<ArrayRef<char>> Binaries) {
GlobalVariable *Desc = createBinDesc(Binaries);
assert(Desc && "no binary descriptor");
createRegisterFunction(Desc);
createUnregisterFunction(Desc);
return M;
}
};
} // anonymous namespace
int main(int argc, const char **argv) {
sys::PrintStackTraceOnErrorSignal(argv[0]);
cl::HideUnrelatedOptions(ClangOffloadWrapperCategory);
cl::SetVersionPrinter([](raw_ostream &OS) {
OS << clang::getClangToolFullVersion("clang-offload-wrapper") << '\n';
});
cl::ParseCommandLineOptions(
argc, argv,
"A tool to create a wrapper bitcode for offload target binaries. Takes "
"offload\ntarget binaries as input and produces bitcode file containing "
"target binaries packaged\nas data and initialization code which "
"registers target binaries in offload runtime.\n");
if (Help) {
cl::PrintHelpMessage();
return 0;
}
auto reportError = [argv](Error E) {
logAllUnhandledErrors(std::move(E), WithColor::error(errs(), argv[0]));
};
if (Triple(Target).getArch() == Triple::UnknownArch) {
reportError(createStringError(
errc::invalid_argument, "'" + Target + "': unsupported target triple"));
return 1;
}
// Read device binaries.
SmallVector<std::unique_ptr<MemoryBuffer>, 4u> Buffers;
SmallVector<ArrayRef<char>, 4u> Images;
Buffers.reserve(Inputs.size());
Images.reserve(Inputs.size());
for (const std::string &File : Inputs) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
MemoryBuffer::getFileOrSTDIN(File);
if (!BufOrErr) {
reportError(createFileError(File, BufOrErr.getError()));
return 1;
}
const std::unique_ptr<MemoryBuffer> &Buf =
Buffers.emplace_back(std::move(*BufOrErr));
Images.emplace_back(Buf->getBufferStart(), Buf->getBufferSize());
}
// Create the output file to write the resulting bitcode to.
std::error_code EC;
ToolOutputFile Out(Output, EC, sys::fs::OF_None);
if (EC) {
reportError(createFileError(Output, EC));
return 1;
}
// Create a wrapper for device binaries and write its bitcode to the file.
WriteBitcodeToFile(BinaryWrapper(Target).wrapBinaries(
makeArrayRef(Images.data(), Images.size())),
Out.os());
if (Out.os().has_error()) {
reportError(createFileError(Output, Out.os().error()));
return 1;
}
// Success.
Out.keep();
return 0;
}

View File

@ -1,55 +0,0 @@
#!/bin/bash
# The lines that we're looking to symbolize look like this:
#0 ./a.out(_foo+0x3e6) [0x55a52e64c696]
# ... which come from the backtrace_symbols() symbolisation function used by
# default in Scudo's implementation of GWP-ASan.
while read -r line; do
# Check that this line needs symbolization.
should_symbolize="$(echo $line |\
grep -E '^[ ]*\#.*\(.*\+0x[0-9a-f]+\) \[0x[0-9a-f]+\]$')"
if [ -z "$should_symbolize" ]; then
echo "$line"
continue
fi
# Carve up the input line into sections.
binary_name="$(echo $line | grep -oE ' .*\(' | rev | cut -c2- | rev |\
cut -c2-)"
function_name="$(echo $line | grep -oE '\([^+]*' | cut -c2-)"
function_offset="$(echo $line | grep -oE '\(.*\)' | grep -oE '\+.*\)' |\
cut -c2- | rev | cut -c2- | rev)"
frame_number="$(echo $line | grep -oE '\#[0-9]+ ')"
if [ -z "$function_name" ]; then
# If the offset is binary-relative, just resolve that.
symbolized="$(echo $function_offset | addr2line -e $binary_name)"
else
# Otherwise, the offset is function-relative. Get the address of the
# function, and add it to the offset, then symbolize.
function_addr="0x$(echo $function_offset |\
nm --defined-only $binary_name 2> /dev/null |\
grep -E " $function_name$" | cut -d' ' -f1)"
# Check that we could get the function address from nm.
if [ -z "$function_addr" ]; then
echo "$line"
continue
fi
# Add the function address and offset to get the offset into the binary.
binary_offset="$(printf "0x%X" "$((function_addr+function_offset))")"
symbolized="$(echo $binary_offset | addr2line -e $binary_name)"
fi
# Check that it symbolized properly. If it didn't, output the old line.
echo $symbolized | grep -E ".*\?.*:" > /dev/null
if [ "$?" -eq "0" ]; then
echo "$line"
continue
else
echo "${frame_number}${symbolized}"
fi
done

View File

@ -1 +0,0 @@
add_subdirectory(gwp_asan)

View File

@ -1,20 +0,0 @@
# Build the stack trace compressor fuzzer. This will require Clang >= 6.0.0, as
# -fsanitize=fuzzer-no-link was not a valid command line flag prior to this.
if (LLVM_USE_SANITIZE_COVERAGE)
add_executable(stack_trace_compressor_fuzzer
../../lib/gwp_asan/stack_trace_compressor.cpp
../../lib/gwp_asan/stack_trace_compressor.h
stack_trace_compressor_fuzzer.cpp)
set_target_properties(
stack_trace_compressor_fuzzer PROPERTIES FOLDER "Fuzzers")
target_compile_options(
stack_trace_compressor_fuzzer PRIVATE -fsanitize=fuzzer-no-link)
set_target_properties(
stack_trace_compressor_fuzzer PROPERTIES LINK_FLAGS -fsanitize=fuzzer)
target_include_directories(
stack_trace_compressor_fuzzer PRIVATE ../../lib/)
if (TARGET gwp_asan)
add_dependencies(gwp_asan stack_trace_compressor_fuzzer)
endif()
endif()

View File

@ -1,49 +0,0 @@
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include "gwp_asan/stack_trace_compressor.h"
constexpr size_t kBytesForLargestVarInt = (sizeof(uintptr_t) * 8) / 7 + 1;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
size_t BufferSize = kBytesForLargestVarInt * Size / sizeof(uintptr_t);
std::vector<uint8_t> Buffer(BufferSize);
std::vector<uint8_t> Buffer2(BufferSize);
// Unpack the fuzz bytes.
gwp_asan::compression::unpack(Data, Size,
reinterpret_cast<uintptr_t *>(Buffer2.data()),
BufferSize / sizeof(uintptr_t));
// Pack the fuzz bytes.
size_t BytesWritten = gwp_asan::compression::pack(
reinterpret_cast<const uintptr_t *>(Data), Size / sizeof(uintptr_t),
Buffer.data(), BufferSize);
// Unpack the compressed buffer.
size_t DecodedElements = gwp_asan::compression::unpack(
Buffer.data(), BytesWritten,
reinterpret_cast<uintptr_t *>(Buffer2.data()),
BufferSize / sizeof(uintptr_t));
// Ensure that every element was encoded and decoded properly.
if (DecodedElements != Size / sizeof(uintptr_t))
abort();
// Ensure that the compression and uncompression resulted in the same trace.
const uintptr_t *FuzzPtrs = reinterpret_cast<const uintptr_t *>(Data);
const uintptr_t *DecodedPtrs =
reinterpret_cast<const uintptr_t *>(Buffer2.data());
for (size_t i = 0; i < Size / sizeof(uintptr_t); ++i) {
if (FuzzPtrs[i] != DecodedPtrs[i]) {
fprintf(stderr, "FuzzPtrs[%zu] != DecodedPtrs[%zu] (0x%zx vs. 0x%zx)", i,
i, FuzzPtrs[i], DecodedPtrs[i]);
abort();
}
}
return 0;
}

View File

@ -1,399 +0,0 @@
set(LIBCXX_LIB_CMAKEFILES_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}" PARENT_SCOPE)
# Get sources
set(LIBCXX_SOURCES
algorithm.cpp
any.cpp
bind.cpp
charconv.cpp
chrono.cpp
condition_variable.cpp
condition_variable_destructor.cpp
debug.cpp
exception.cpp
functional.cpp
future.cpp
hash.cpp
include/apple_availability.h
include/atomic_support.h
include/config_elast.h
include/refstring.h
ios.cpp
iostream.cpp
locale.cpp
memory.cpp
mutex.cpp
mutex_destructor.cpp
new.cpp
optional.cpp
random.cpp
regex.cpp
shared_mutex.cpp
stdexcept.cpp
string.cpp
strstream.cpp
support/runtime/exception_fallback.ipp
support/runtime/exception_glibcxx.ipp
support/runtime/exception_libcxxabi.ipp
support/runtime/exception_libcxxrt.ipp
support/runtime/exception_msvc.ipp
support/runtime/exception_pointer_cxxabi.ipp
support/runtime/exception_pointer_glibcxx.ipp
support/runtime/exception_pointer_msvc.ipp
support/runtime/exception_pointer_unimplemented.ipp
support/runtime/new_handler_fallback.ipp
support/runtime/stdexcept_default.ipp
support/runtime/stdexcept_vcruntime.ipp
system_error.cpp
thread.cpp
typeinfo.cpp
utility.cpp
valarray.cpp
variant.cpp
vector.cpp
)
if(WIN32)
list(APPEND LIBCXX_SOURCES
support/win32/locale_win32.cpp
support/win32/support.cpp
support/win32/thread_win32.cpp
)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
list(APPEND LIBCXX_SOURCES
support/solaris/mbsnrtowcs.inc
support/solaris/wcsnrtombs.inc
support/solaris/xlocale.cpp
)
endif()
if (LIBCXX_ENABLE_FILESYSTEM)
list(APPEND LIBCXX_SOURCES
filesystem/filesystem_common.h
filesystem/operations.cpp
filesystem/directory_iterator.cpp
)
# Filesystem uses __int128_t, which requires a definition of __muloi4 when
# compiled with UBSAN. This definition is not provided by libgcc_s, but is
# provided by compiler-rt. So we need to disable it to avoid having multiple
# definitions. See filesystem/int128_builtins.cpp.
if (NOT LIBCXX_USE_COMPILER_RT)
list(APPEND LIBCXX_SOURCES
filesystem/int128_builtins.cpp
)
endif()
endif()
# Add all the headers to the project for IDEs.
if (LIBCXX_CONFIGURE_IDE)
file(GLOB_RECURSE LIBCXX_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/*)
if(WIN32)
file( GLOB LIBCXX_WIN32_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/support/win32/*.h)
list(APPEND LIBCXX_HEADERS ${LIBCXX_WIN32_HEADERS})
endif()
# Force them all into the headers dir on MSVC, otherwise they end up at
# project scope because they don't have extensions.
if (MSVC_IDE)
source_group("Header Files" FILES ${LIBCXX_HEADERS})
endif()
endif()
if(NOT LIBCXX_INSTALL_LIBRARY)
set(exclude_from_all EXCLUDE_FROM_ALL)
endif()
# If LIBCXX_CXX_ABI_LIBRARY_PATH is defined we want to add it to the search path.
add_link_flags_if(LIBCXX_CXX_ABI_LIBRARY_PATH
"${CMAKE_LIBRARY_PATH_FLAG}${LIBCXX_CXX_ABI_LIBRARY_PATH}")
if (LIBCXX_GENERATE_COVERAGE AND NOT LIBCXX_COVERAGE_LIBRARY)
find_compiler_rt_library(profile LIBCXX_COVERAGE_LIBRARY)
endif()
add_library_flags_if(LIBCXX_COVERAGE_LIBRARY "${LIBCXX_COVERAGE_LIBRARY}")
if (APPLE AND LLVM_USE_SANITIZER)
if (("${LLVM_USE_SANITIZER}" STREQUAL "Address") OR
("${LLVM_USE_SANITIZER}" STREQUAL "Address;Undefined") OR
("${LLVM_USE_SANITIZER}" STREQUAL "Undefined;Address"))
set(LIBFILE "libclang_rt.asan_osx_dynamic.dylib")
elseif("${LLVM_USE_SANITIZER}" STREQUAL "Undefined")
set(LIBFILE "libclang_rt.ubsan_osx_dynamic.dylib")
elseif("${LLVM_USE_SANITIZER}" STREQUAL "Thread")
set(LIBFILE "libclang_rt.tsan_osx_dynamic.dylib")
else()
message(WARNING "LLVM_USE_SANITIZER=${LLVM_USE_SANITIZER} is not supported on OS X")
endif()
if (LIBFILE)
find_compiler_rt_dir(LIBDIR)
if (NOT IS_DIRECTORY "${LIBDIR}")
message(FATAL_ERROR "Cannot find compiler-rt directory on OS X required for LLVM_USE_SANITIZER")
endif()
set(LIBCXX_SANITIZER_LIBRARY "${LIBDIR}/${LIBFILE}")
set(LIBCXX_SANITIZER_LIBRARY "${LIBCXX_SANITIZER_LIBRARY}" PARENT_SCOPE)
message(STATUS "Manually linking compiler-rt library: ${LIBCXX_SANITIZER_LIBRARY}")
add_library_flags("${LIBCXX_SANITIZER_LIBRARY}")
add_link_flags("-Wl,-rpath,${LIBDIR}")
endif()
endif()
if (LIBCXX_ENABLE_PARALLEL_ALGORITHMS AND NOT TARGET pstl::ParallelSTL)
message(FATAL_ERROR "Could not find ParallelSTL")
endif()
function(cxx_set_common_defines name)
if(LIBCXX_CXX_ABI_HEADER_TARGET)
add_dependencies(${name} ${LIBCXX_CXX_ABI_HEADER_TARGET})
endif()
if (LIBCXX_ENABLE_PARALLEL_ALGORITHMS)
target_link_libraries(${name} PUBLIC pstl::ParallelSTL)
endif()
endfunction()
split_list(LIBCXX_COMPILE_FLAGS)
split_list(LIBCXX_LINK_FLAGS)
# Build the shared library.
if (LIBCXX_ENABLE_SHARED)
add_library(cxx_shared SHARED ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS})
if(COMMAND llvm_setup_rpath)
llvm_setup_rpath(cxx_shared)
endif()
target_link_libraries(cxx_shared PRIVATE ${LIBCXX_LIBRARIES})
set_target_properties(cxx_shared
PROPERTIES
COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}"
LINK_FLAGS "${LIBCXX_LINK_FLAGS}"
OUTPUT_NAME "c++"
VERSION "${LIBCXX_ABI_VERSION}.0"
SOVERSION "${LIBCXX_ABI_VERSION}"
DEFINE_SYMBOL ""
)
cxx_add_common_build_flags(cxx_shared)
cxx_set_common_defines(cxx_shared)
# Link against LLVM libunwind
if (LIBCXXABI_USE_LLVM_UNWINDER)
if (NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_shared OR HAVE_LIBUNWIND))
target_link_libraries(cxx_shared PUBLIC unwind_shared)
elseif (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_static OR HAVE_LIBUNWIND))
# libunwind is already included in libc++abi
else()
target_link_libraries(cxx_shared PUBLIC unwind)
endif()
endif()
# Link against libc++abi
if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY)
if (APPLE)
target_link_libraries(cxx_shared PRIVATE "-Wl,-force_load" "${LIBCXX_CXX_STATIC_ABI_LIBRARY}")
else()
target_link_libraries(cxx_shared PRIVATE "-Wl,--whole-archive,-Bstatic" "${LIBCXX_CXX_STATIC_ABI_LIBRARY}" "-Wl,-Bdynamic,--no-whole-archive")
endif()
else()
target_link_libraries(cxx_shared PUBLIC "${LIBCXX_CXX_SHARED_ABI_LIBRARY}")
endif()
# Maybe re-export symbols from libc++abi
if (APPLE AND (LIBCXX_CXX_ABI_LIBNAME STREQUAL "libcxxabi" OR
LIBCXX_CXX_ABI_LIBNAME STREQUAL "default")
AND NOT DEFINED LIBCXX_OSX_REEXPORT_LIBCXXABI_SYMBOLS)
set(LIBCXX_OSX_REEXPORT_LIBCXXABI_SYMBOLS ON)
endif()
if (LIBCXX_OSX_REEXPORT_LIBCXXABI_SYMBOLS)
if ("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(armv6|armv7|armv7s)$")
set(RE_EXPORT_LIST "${CMAKE_CURRENT_SOURCE_DIR}/../lib/libc++sjlj-abi.v${LIBCXX_LIBCPPABI_VERSION}.exp")
else()
set(RE_EXPORT_LIST "${CMAKE_CURRENT_SOURCE_DIR}/../lib/libc++abi.v${LIBCXX_LIBCPPABI_VERSION}.exp")
endif()
target_link_libraries(cxx_shared PRIVATE
"-Wl,-unexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/libc++unexp.exp"
"-Wl,-reexported_symbols_list,${RE_EXPORT_LIST}"
"-Wl,-force_symbols_not_weak_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/notweak.exp"
"-Wl,-force_symbols_weak_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/weak.exp")
if (NOT LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS)
target_link_libraries(cxx_shared PRIVATE "-Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/libc++abi-new-delete.exp")
endif()
endif()
# Generate a linker script in place of a libc++.so symlink.
if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT)
include(DefineLinkerScript)
define_linker_script(cxx_shared)
endif()
list(APPEND LIBCXX_BUILD_TARGETS "cxx_shared")
if(WIN32 AND NOT MINGW AND NOT "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
# Since we most likely do not have a mt.exe replacement, disable the
# manifest bundling. This allows a normal cmake invocation to pass which
# will attempt to use the manifest tool to generate the bundled manifest
set_target_properties(cxx_shared PROPERTIES
APPEND_STRING PROPERTY LINK_FLAGS " /MANIFEST:NO")
endif()
endif()
# Build the static library.
if (LIBCXX_ENABLE_STATIC)
add_library(cxx_static STATIC ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS})
target_link_libraries(cxx_static PRIVATE ${LIBCXX_LIBRARIES})
set(CMAKE_STATIC_LIBRARY_PREFIX "lib")
set_target_properties(cxx_static
PROPERTIES
COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}"
LINK_FLAGS "${LIBCXX_LINK_FLAGS}"
OUTPUT_NAME "c++"
)
cxx_add_common_build_flags(cxx_static)
cxx_set_common_defines(cxx_static)
if (LIBCXX_HERMETIC_STATIC_LIBRARY)
# If the hermetic library doesn't define the operator new/delete functions
# then its code shouldn't declare them with hidden visibility. They might
# actually be provided by a shared library at link time.
if (LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS)
append_flags_if_supported(CXX_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete-hidden)
endif()
target_compile_options(cxx_static PRIVATE ${CXX_STATIC_LIBRARY_FLAGS})
target_compile_definitions(cxx_static PRIVATE _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
endif()
list(APPEND LIBCXX_BUILD_TARGETS "cxx_static")
# Attempt to merge the libc++.a archive and the ABI library archive into one.
if (LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY)
set(MERGE_ARCHIVES_SEARCH_PATHS "")
if (LIBCXX_CXX_ABI_LIBRARY_PATH)
set(MERGE_ARCHIVES_SEARCH_PATHS "-L${LIBCXX_CXX_ABI_LIBRARY_PATH}")
endif()
if (TARGET "${LIBCXX_CXX_STATIC_ABI_LIBRARY}" OR HAVE_LIBCXXABI)
set(MERGE_ARCHIVES_ABI_TARGET "$<TARGET_LINKER_FILE:${LIBCXX_CXX_STATIC_ABI_LIBRARY}>")
else()
set(MERGE_ARCHIVES_ABI_TARGET
"${CMAKE_STATIC_LIBRARY_PREFIX}${LIBCXX_CXX_STATIC_ABI_LIBRARY}${CMAKE_STATIC_LIBRARY_SUFFIX}")
endif()
if (APPLE)
set(MERGE_ARCHIVES_LIBTOOL "--use-libtool" "--libtool" "${CMAKE_LIBTOOL}")
endif()
add_custom_command(TARGET cxx_static POST_BUILD
COMMAND
${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/merge_archives.py
ARGS
-o $<TARGET_LINKER_FILE:cxx_static>
--ar "${CMAKE_AR}"
${MERGE_ARCHIVES_LIBTOOL}
"$<TARGET_LINKER_FILE:cxx_static>"
"${MERGE_ARCHIVES_ABI_TARGET}"
"${MERGE_ARCHIVES_SEARCH_PATHS}"
WORKING_DIRECTORY ${LIBCXX_BUILD_DIR}
)
endif()
endif()
# Add a meta-target for both libraries.
add_custom_target(cxx DEPENDS cxx-headers ${LIBCXX_BUILD_TARGETS})
if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY)
set(LIBCXX_EXPERIMENTAL_SOURCES
experimental/memory_resource.cpp
)
add_library(cxx_experimental STATIC ${LIBCXX_EXPERIMENTAL_SOURCES})
if (LIBCXX_ENABLE_SHARED)
target_link_libraries(cxx_experimental PRIVATE cxx_shared)
else()
target_link_libraries(cxx_experimental PRIVATE cxx_static)
endif()
set_target_properties(cxx_experimental
PROPERTIES
COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}"
OUTPUT_NAME "c++experimental"
)
cxx_add_common_build_flags(cxx_experimental)
# Overwrite the previously-set Standard flag with -std=c++14 if supported
check_flag_supported(-std=c++14)
if (NOT MSVC AND LIBCXX_SUPPORTS_STD_EQ_CXX14_FLAG)
target_compile_options(cxx_experimental PRIVATE "-std=c++14")
endif()
endif()
if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY)
file(GLOB LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES ../test/support/external_threads.cpp)
if (LIBCXX_ENABLE_SHARED)
add_library(cxx_external_threads SHARED ${LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES})
else()
add_library(cxx_external_threads STATIC ${LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES})
endif()
set_target_properties(cxx_external_threads
PROPERTIES
LINK_FLAGS "${LIBCXX_LINK_FLAGS}"
COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}"
OUTPUT_NAME "c++external_threads"
)
endif()
if (LIBCXX_INSTALL_LIBRARY)
if (LIBCXX_INSTALL_SHARED_LIBRARY)
install(TARGETS cxx_shared
ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}bin COMPONENT cxx)
endif()
if (LIBCXX_INSTALL_STATIC_LIBRARY)
install(TARGETS cxx_static
ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}bin COMPONENT cxx)
endif()
if(LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY)
install(TARGETS ${LIBCXX_INSTALL_TARGETS} ${experimental_lib}
LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}bin COMPONENT cxx)
endif()
# NOTE: This install command must go after the cxx install command otherwise
# it will not be executed after the library symlinks are installed.
if (LIBCXX_ENABLE_SHARED AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT)
# Replace the libc++ filename with $<TARGET_LINKER_FILE:cxx>
# after we required CMake 3.0.
install(FILES "${LIBCXX_LIBRARY_DIR}/libc++${CMAKE_SHARED_LIBRARY_SUFFIX}"
DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR}
COMPONENT libcxx)
endif()
endif()
if (NOT CMAKE_CONFIGURATION_TYPES AND (LIBCXX_INSTALL_LIBRARY OR
LIBCXX_INSTALL_HEADERS))
if(LIBCXX_INSTALL_LIBRARY)
set(lib_install_target cxx)
endif()
if (LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY)
set(experimental_lib_install_target cxx_experimental)
endif()
if(LIBCXX_INSTALL_HEADERS)
set(header_install_target install-cxx-headers)
endif()
add_custom_target(install-cxx
DEPENDS ${lib_install_target}
${experimental_lib_install_target}
${header_install_target}
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=cxx
-P "${LIBCXX_BINARY_DIR}/cmake_install.cmake")
add_custom_target(install-cxx-stripped
DEPENDS ${lib_install_target}
${experimental_lib_install_target}
${header_install_target}
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=cxx
-DCMAKE_INSTALL_DO_STRIP=1
-P "${LIBCXX_BINARY_DIR}/cmake_install.cmake")
add_custom_target(install-libcxx DEPENDS install-cxx)
endif()

View File

@ -1,225 +0,0 @@
# Check if lld is built as a standalone project.
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
project(lld)
cmake_minimum_required(VERSION 3.4.3)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(LLD_BUILT_STANDALONE TRUE)
find_program(LLVM_CONFIG_PATH "llvm-config" DOC "Path to llvm-config binary")
if(NOT LLVM_CONFIG_PATH)
message(FATAL_ERROR "llvm-config not found: specify LLVM_CONFIG_PATH")
endif()
execute_process(COMMAND "${LLVM_CONFIG_PATH}"
"--obj-root"
"--includedir"
"--cmakedir"
"--src-root"
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE LLVM_CONFIG_OUTPUT
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(HAD_ERROR)
message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}")
endif()
string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" LLVM_CONFIG_OUTPUT "${LLVM_CONFIG_OUTPUT}")
list(GET LLVM_CONFIG_OUTPUT 0 OBJ_ROOT)
list(GET LLVM_CONFIG_OUTPUT 1 MAIN_INCLUDE_DIR)
list(GET LLVM_CONFIG_OUTPUT 2 LLVM_CMAKE_PATH)
list(GET LLVM_CONFIG_OUTPUT 3 MAIN_SRC_DIR)
set(LLVM_OBJ_ROOT ${OBJ_ROOT} CACHE PATH "path to LLVM build tree")
set(LLVM_MAIN_INCLUDE_DIR ${MAIN_INCLUDE_DIR} CACHE PATH "path to llvm/include")
set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree")
file(TO_CMAKE_PATH ${LLVM_OBJ_ROOT} LLVM_BINARY_DIR)
if(NOT EXISTS "${LLVM_CMAKE_PATH}/LLVMConfig.cmake")
message(FATAL_ERROR "LLVMConfig.cmake not found")
endif()
include("${LLVM_CMAKE_PATH}/LLVMConfig.cmake")
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
include_directories("${LLVM_BINARY_DIR}/include" ${LLVM_INCLUDE_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX})
set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin)
find_program(LLVM_TABLEGEN_EXE "llvm-tblgen" ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH)
include(AddLLVM)
include(TableGen)
include(HandleLLVMOptions)
if(LLVM_INCLUDE_TESTS)
include(FindPythonInterp)
if(NOT PYTHONINTERP_FOUND)
message(FATAL_ERROR
"Unable to find Python interpreter, required for testing.
Please install Python or specify the PYTHON_EXECUTABLE CMake variable.")
endif()
if(${PYTHON_VERSION_STRING} VERSION_LESS 2.7)
message(FATAL_ERROR "Python 2.7 or newer is required")
endif()
# Check prebuilt llvm/utils.
if(EXISTS ${LLVM_TOOLS_BINARY_DIR}/FileCheck${CMAKE_EXECUTABLE_SUFFIX}
AND EXISTS ${LLVM_TOOLS_BINARY_DIR}/not${CMAKE_EXECUTABLE_SUFFIX})
set(LLVM_UTILS_PROVIDED ON)
endif()
if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
# Note: path not really used, except for checking if lit was found
set(LLVM_LIT ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
if(NOT LLVM_UTILS_PROVIDED)
add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/FileCheck utils/FileCheck)
add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/not utils/not)
set(LLVM_UTILS_PROVIDED ON)
set(LLD_TEST_DEPS FileCheck not)
endif()
set(UNITTEST_DIR ${LLVM_MAIN_SRC_DIR}/utils/unittest)
if(EXISTS ${UNITTEST_DIR}/googletest/include/gtest/gtest.h
AND NOT EXISTS ${LLVM_LIBRARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX}
AND EXISTS ${UNITTEST_DIR}/CMakeLists.txt)
add_subdirectory(${UNITTEST_DIR} utils/unittest)
endif()
else()
# Seek installed Lit.
find_program(LLVM_LIT
NAMES llvm-lit lit.py lit
PATHS "${LLVM_MAIN_SRC_DIR}/utils/lit"
DOC "Path to lit.py")
endif()
if(LLVM_LIT)
# Define the default arguments to use with 'lit', and an option for the user
# to override.
set(LIT_ARGS_DEFAULT "-sv")
if (MSVC OR XCODE)
set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
endif()
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
# On Win32 hosts, provide an option to specify the path to the GnuWin32 tools.
if(WIN32 AND NOT CYGWIN)
set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools")
endif()
else()
set(LLVM_INCLUDE_TESTS OFF)
endif()
endif()
endif()
set(LLD_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LLD_INCLUDE_DIR ${LLD_SOURCE_DIR}/include )
set(LLD_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
# Compute the LLD version from the LLVM version.
string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" LLD_VERSION
${PACKAGE_VERSION})
message(STATUS "LLD version: ${LLD_VERSION}")
string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" LLD_VERSION_MAJOR
${LLD_VERSION})
string(REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" LLD_VERSION_MINOR
${LLD_VERSION})
# Determine LLD revision and repository.
# TODO: Figure out a way to get the revision and the repository on windows.
if ( NOT CMAKE_SYSTEM_NAME MATCHES "Windows" )
execute_process(COMMAND ${CMAKE_SOURCE_DIR}/utils/GetSourceVersion ${LLD_SOURCE_DIR}
OUTPUT_VARIABLE LLD_REVISION)
execute_process(COMMAND ${CMAKE_SOURCE_DIR}/utils/GetRepositoryPath ${LLD_SOURCE_DIR}
OUTPUT_VARIABLE LLD_REPOSITORY)
if ( LLD_REPOSITORY )
# Replace newline characters with spaces
string(REGEX REPLACE "(\r?\n)+" " " LLD_REPOSITORY ${LLD_REPOSITORY})
# Remove leading spaces
STRING(REGEX REPLACE "^[ \t\r\n]+" "" LLD_REPOSITORY "${LLD_REPOSITORY}" )
# Remove trailing spaces
string(REGEX REPLACE "(\ )+$" "" LLD_REPOSITORY ${LLD_REPOSITORY})
endif()
if ( LLD_REVISION )
# Replace newline characters with spaces
string(REGEX REPLACE "(\r?\n)+" " " LLD_REVISION ${LLD_REVISION})
# Remove leading spaces
STRING(REGEX REPLACE "^[ \t\r\n]+" "" LLD_REVISION "${LLD_REVISION}" )
# Remove trailing spaces
string(REGEX REPLACE "(\ )+$" "" LLD_REVISION ${LLD_REVISION})
endif()
endif ()
# Configure the Version.inc file.
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/include/lld/Common/Version.inc.in
${CMAKE_CURRENT_BINARY_DIR}/include/lld/Common/Version.inc)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "In-source builds are not allowed. CMake would overwrite "
"the makefiles distributed with LLVM. Please create a directory and run cmake "
"from there, passing the path to this source directory as the last argument. "
"This process created the file `CMakeCache.txt' and the directory "
"`CMakeFiles'. Please delete them.")
endif()
list (APPEND CMAKE_MODULE_PATH "${LLD_SOURCE_DIR}/cmake/modules")
include(AddLLD)
option(LLD_USE_VTUNE
"Enable VTune user task tracking."
OFF)
if (LLD_USE_VTUNE)
find_package(VTune)
if (VTUNE_FOUND)
include_directories(${VTune_INCLUDE_DIRS})
list(APPEND LLVM_COMMON_LIBS ${VTune_LIBRARIES})
add_definitions(-DLLD_HAS_VTUNE)
endif()
endif()
option(LLD_BUILD_TOOLS
"Build the lld tools. If OFF, just generate build targets." ON)
if (MSVC)
add_definitions(-wd4530) # Suppress 'warning C4530: C++ exception handler used, but unwind semantics are not enabled.'
add_definitions(-wd4062) # Suppress 'warning C4062: enumerator X in switch of enum Y is not handled' from system header.
endif()
include_directories(BEFORE
${CMAKE_CURRENT_BINARY_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/include
)
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
install(DIRECTORY include/
DESTINATION include
FILES_MATCHING
PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
endif()
add_subdirectory(Common)
add_subdirectory(lib)
add_subdirectory(tools/lld)
if (LLVM_INCLUDE_TESTS)
add_subdirectory(test)
add_subdirectory(unittests)
endif()
add_subdirectory(docs)
add_subdirectory(COFF)
add_subdirectory(ELF)
add_subdirectory(MinGW)
add_subdirectory(wasm)

View File

@ -1,50 +0,0 @@
set(LLVM_TARGET_DEFINITIONS Options.td)
tablegen(LLVM Options.inc -gen-opt-parser-defs)
add_public_tablegen_target(COFFOptionsTableGen)
if(NOT LLD_BUILT_STANDALONE)
set(tablegen_deps intrinsics_gen)
endif()
add_lld_library(lldCOFF
Chunks.cpp
DebugTypes.cpp
DLL.cpp
Driver.cpp
DriverUtils.cpp
ICF.cpp
InputFiles.cpp
LTO.cpp
MapFile.cpp
MarkLive.cpp
MinGW.cpp
PDB.cpp
SymbolTable.cpp
Symbols.cpp
Writer.cpp
LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
BinaryFormat
Core
DebugInfoCodeView
DebugInfoDWARF
DebugInfoMSF
DebugInfoPDB
Demangle
LibDriver
LTO
MC
Object
Option
Support
WindowsManifest
LINK_LIBS
lldCommon
${LLVM_PTHREAD_LIB}
DEPENDS
COFFOptionsTableGen
${tablegen_deps}
)

View File

@ -1,62 +0,0 @@
if(NOT LLD_BUILT_STANDALONE)
set(tablegen_deps intrinsics_gen)
endif()
find_first_existing_vc_file("${LLVM_MAIN_SRC_DIR}" llvm_vc)
find_first_existing_vc_file("${LLD_SOURCE_DIR}" lld_vc)
set(version_inc "${CMAKE_CURRENT_BINARY_DIR}/VCSVersion.inc")
set(generate_vcs_version_script "${LLVM_CMAKE_PATH}/GenerateVersionFromVCS.cmake")
if(lld_vc)
set(lld_source_dir ${LLD_SOURCE_DIR})
endif()
add_custom_command(OUTPUT "${version_inc}"
DEPENDS "${lld_vc}" "${generate_vcs_version_script}"
COMMAND ${CMAKE_COMMAND} "-DNAMES=LLD"
"-DLLD_SOURCE_DIR=${LLD_SOURCE_DIR}"
"-DHEADER_FILE=${version_inc}"
-P "${generate_vcs_version_script}")
# Mark the generated header as being generated.
set_source_files_properties("${version_inc}"
PROPERTIES GENERATED TRUE
HEADER_FILE_ONLY TRUE)
set_property(SOURCE Version.cpp APPEND PROPERTY
COMPILE_DEFINITIONS "HAVE_VCS_VERSION_INC")
add_lld_library(lldCommon
Args.cpp
DWARF.cpp
ErrorHandler.cpp
Filesystem.cpp
Memory.cpp
Reproduce.cpp
Strings.cpp
TargetOptionsCommandFlags.cpp
Threads.cpp
Timer.cpp
VCSVersion.inc
Version.cpp
ADDITIONAL_HEADER_DIRS
${LLD_INCLUDE_DIR}/lld/Common
LINK_COMPONENTS
Codegen
Core
DebugInfoDWARF
Demangle
MC
Option
Support
Target
LINK_LIBS
${LLVM_PTHREAD_LIB}
DEPENDS
${tablegen_deps}
)

View File

@ -1,68 +0,0 @@
set(LLVM_TARGET_DEFINITIONS Options.td)
tablegen(LLVM Options.inc -gen-opt-parser-defs)
add_public_tablegen_target(ELFOptionsTableGen)
if(NOT LLD_BUILT_STANDALONE)
set(tablegen_deps intrinsics_gen)
endif()
add_lld_library(lldELF
AArch64ErrataFix.cpp
Arch/AArch64.cpp
Arch/AMDGPU.cpp
Arch/ARM.cpp
Arch/AVR.cpp
Arch/Hexagon.cpp
Arch/Mips.cpp
Arch/MipsArchTree.cpp
Arch/MSP430.cpp
Arch/PPC.cpp
Arch/PPC64.cpp
Arch/RISCV.cpp
Arch/SPARCV9.cpp
Arch/X86.cpp
Arch/X86_64.cpp
ARMErrataFix.cpp
CallGraphSort.cpp
DWARF.cpp
Driver.cpp
DriverUtils.cpp
EhFrame.cpp
ICF.cpp
InputFiles.cpp
InputSection.cpp
LTO.cpp
LinkerScript.cpp
MapFile.cpp
MarkLive.cpp
OutputSections.cpp
Relocations.cpp
ScriptLexer.cpp
ScriptParser.cpp
SymbolTable.cpp
Symbols.cpp
SyntheticSections.cpp
Target.cpp
Thunks.cpp
Writer.cpp
LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
BinaryFormat
BitWriter
Core
DebugInfoDWARF
LTO
MC
Object
Option
Support
LINK_LIBS
lldCommon
${LLVM_PTHREAD_LIB}
DEPENDS
ELFOptionsTableGen
${tablegen_deps}
)

View File

@ -1,8 +0,0 @@
if (LLVM_ENABLE_SPHINX)
include(AddSphinxTarget)
if (SPHINX_FOUND)
if (${SPHINX_OUTPUT_HTML})
add_sphinx_target(html lld)
endif()
endif()
endif()

View File

@ -1,3 +0,0 @@
add_subdirectory(Core)
add_subdirectory(Driver)
add_subdirectory(ReaderWriter)

View File

@ -1,28 +0,0 @@
if(NOT LLD_BUILT_STANDALONE)
set(tablegen_deps intrinsics_gen)
endif()
add_lld_library(lldCore
DefinedAtom.cpp
Error.cpp
File.cpp
LinkingContext.cpp
Reader.cpp
Resolver.cpp
SymbolTable.cpp
Writer.cpp
ADDITIONAL_HEADER_DIRS
${LLD_INCLUDE_DIR}/lld/Core
LINK_COMPONENTS
BinaryFormat
MC
Support
LINK_LIBS
${LLVM_PTHREAD_LIB}
DEPENDS
${tablegen_deps}
)

View File

@ -1,23 +0,0 @@
set(LLVM_TARGET_DEFINITIONS DarwinLdOptions.td)
tablegen(LLVM DarwinLdOptions.inc -gen-opt-parser-defs)
add_public_tablegen_target(DriverOptionsTableGen)
add_lld_library(lldDriver
DarwinLdDriver.cpp
ADDITIONAL_HEADER_DIRS
${LLD_INCLUDE_DIR}/lld/Driver
LINK_COMPONENTS
Option
Support
LINK_LIBS
lldCommon
lldCore
lldMachO
lldReaderWriter
lldYAML
)
add_dependencies(lldDriver DriverOptionsTableGen)

View File

@ -1,20 +0,0 @@
add_subdirectory(MachO)
add_subdirectory(YAML)
if (MSVC)
add_definitions(-wd4062) # Suppress 'warning C4062: Enumerator has no associated handler in a switch statement.'
endif()
add_lld_library(lldReaderWriter
FileArchive.cpp
ADDITIONAL_HEADER_DIRS
${LLD_INCLUDE_DIR}/lld/ReaderWriter
LINK_COMPONENTS
Object
Support
LINK_LIBS
lldCore
)

View File

@ -1,35 +0,0 @@
add_lld_library(lldMachO
ArchHandler.cpp
ArchHandler_arm.cpp
ArchHandler_arm64.cpp
ArchHandler_x86.cpp
ArchHandler_x86_64.cpp
CompactUnwindPass.cpp
GOTPass.cpp
LayoutPass.cpp
MachOLinkingContext.cpp
MachONormalizedFileBinaryReader.cpp
MachONormalizedFileBinaryWriter.cpp
MachONormalizedFileFromAtoms.cpp
MachONormalizedFileToAtoms.cpp
MachONormalizedFileYAML.cpp
ObjCPass.cpp
ShimPass.cpp
StubsPass.cpp
TLVPass.cpp
WriterMachO.cpp
LINK_COMPONENTS
DebugInfoDWARF
Demangle
Object
Support
LINK_LIBS
lldCommon
lldCore
lldYAML
${LLVM_PTHREAD_LIB}
)
include_directories(.)

View File

@ -1,9 +0,0 @@
add_lld_library(lldYAML
ReaderWriterYAML.cpp
LINK_COMPONENTS
Support
LINK_LIBS
lldCore
)

View File

@ -1,28 +0,0 @@
set(LLVM_LINK_COMPONENTS
Support
)
add_lld_tool(lld
lld.cpp
)
target_link_libraries(lld
PRIVATE
lldCommon
lldCOFF
lldDriver
lldELF
lldMinGW
lldWasm
)
install(TARGETS lld
RUNTIME DESTINATION bin)
if(NOT LLD_SYMLINKS_TO_CREATE)
set(LLD_SYMLINKS_TO_CREATE lld-link ld.lld ld64.lld wasm-ld)
endif()
foreach(link ${LLD_SYMLINKS_TO_CREATE})
add_lld_symlink(${link} lld)
endforeach()

View File

@ -1,11 +0,0 @@
add_lldb_library(lldbPluginABISysV_arc PLUGIN
ABISysV_arc.cpp
LINK_LIBS
lldbCore
lldbSymbol
lldbTarget
lldbPluginProcessUtility
LINK_COMPONENTS
Support
)

View File

@ -1,10 +0,0 @@
set(LLVM_LINK_COMPONENTS
Object
Support
TextAPI
ObjectYAML
)
add_llvm_tool(llvm-ifs
llvm-ifs.cpp
)

View File

@ -1,21 +0,0 @@
;===- ./tools/llvm-ifs/LLVMBuild.txt ---------------------------*- Conf -*--===;
;
; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
; See https://llvm.org/LICENSE.txt for license information.
; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Tool
name = llvm-ifs
parent = Tools
required_libraries = Object Support TextAPI

View File

@ -1,532 +0,0 @@
//===- llvm-ifs.cpp -------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===-----------------------------------------------------------------------===/
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ObjectYAML/yaml2obj.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TextAPI/MachO/InterfaceFile.h"
#include "llvm/TextAPI/MachO/TextAPIReader.h"
#include "llvm/TextAPI/MachO/TextAPIWriter.h"
#include <set>
#include <string>
using namespace llvm;
using namespace llvm::yaml;
using namespace llvm::MachO;
#define DEBUG_TYPE "llvm-ifs"
namespace {
const VersionTuple IFSVersionCurrent(1, 2);
}
static cl::opt<std::string> Action("action", cl::desc("<llvm-ifs action>"),
cl::value_desc("write-ifs | write-bin"),
cl::init("write-ifs"));
static cl::opt<std::string> ForceFormat("force-format",
cl::desc("<force object format>"),
cl::value_desc("ELF | TBD"),
cl::init(""));
static cl::list<std::string> InputFilenames(cl::Positional,
cl::desc("<input ifs files>"),
cl::ZeroOrMore);
static cl::opt<std::string> OutputFilename("o", cl::desc("<output file>"),
cl::value_desc("path"));
enum class IFSSymbolType {
NoType = 0,
Object,
Func,
// Type information is 4 bits, so 16 is safely out of range.
Unknown = 16,
};
std::string getTypeName(IFSSymbolType Type) {
switch (Type) {
case IFSSymbolType::NoType:
return "NoType";
case IFSSymbolType::Func:
return "Func";
case IFSSymbolType::Object:
return "Object";
case IFSSymbolType::Unknown:
return "Unknown";
}
llvm_unreachable("Unexpected ifs symbol type.");
}
struct IFSSymbol {
IFSSymbol(std::string SymbolName) : Name(SymbolName) {}
std::string Name;
uint64_t Size;
IFSSymbolType Type;
bool Weak;
Optional<std::string> Warning;
bool operator<(const IFSSymbol &RHS) const { return Name < RHS.Name; }
};
namespace llvm {
namespace yaml {
/// YAML traits for IFSSymbolType.
template <> struct ScalarEnumerationTraits<IFSSymbolType> {
static void enumeration(IO &IO, IFSSymbolType &SymbolType) {
IO.enumCase(SymbolType, "NoType", IFSSymbolType::NoType);
IO.enumCase(SymbolType, "Func", IFSSymbolType::Func);
IO.enumCase(SymbolType, "Object", IFSSymbolType::Object);
IO.enumCase(SymbolType, "Unknown", IFSSymbolType::Unknown);
// Treat other symbol types as noise, and map to Unknown.
if (!IO.outputting() && IO.matchEnumFallback())
SymbolType = IFSSymbolType::Unknown;
}
};
template <> struct ScalarTraits<VersionTuple> {
static void output(const VersionTuple &Value, void *,
llvm::raw_ostream &Out) {
Out << Value.getAsString();
}
static StringRef input(StringRef Scalar, void *, VersionTuple &Value) {
if (Value.tryParse(Scalar))
return StringRef("Can't parse version: invalid version format.");
if (Value > IFSVersionCurrent)
return StringRef("Unsupported IFS version.");
// Returning empty StringRef indicates successful parse.
return StringRef();
}
// Don't place quotation marks around version value.
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
};
/// YAML traits for IFSSymbol.
template <> struct MappingTraits<IFSSymbol> {
static void mapping(IO &IO, IFSSymbol &Symbol) {
IO.mapRequired("Type", Symbol.Type);
// The need for symbol size depends on the symbol type.
if (Symbol.Type == IFSSymbolType::NoType)
IO.mapOptional("Size", Symbol.Size, (uint64_t)0);
else if (Symbol.Type == IFSSymbolType::Func)
Symbol.Size = 0;
else
IO.mapRequired("Size", Symbol.Size);
IO.mapOptional("Weak", Symbol.Weak, false);
IO.mapOptional("Warning", Symbol.Warning);
}
// Compacts symbol information into a single line.
static const bool flow = true;
};
/// YAML traits for set of IFSSymbols.
template <> struct CustomMappingTraits<std::set<IFSSymbol>> {
static void inputOne(IO &IO, StringRef Key, std::set<IFSSymbol> &Set) {
std::string Name = Key.str();
IFSSymbol Sym(Name);
IO.mapRequired(Name.c_str(), Sym);
Set.insert(Sym);
}
static void output(IO &IO, std::set<IFSSymbol> &Set) {
for (auto &Sym : Set)
IO.mapRequired(Sym.Name.c_str(), const_cast<IFSSymbol &>(Sym));
}
};
} // namespace yaml
} // namespace llvm
// A cumulative representation of ELF stubs.
// Both textual and binary stubs will read into and write from this object.
class IFSStub {
// TODO: Add support for symbol versioning.
public:
VersionTuple IfsVersion;
std::string Triple;
std::string ObjectFileFormat;
Optional<std::string> SOName;
std::vector<std::string> NeededLibs;
std::set<IFSSymbol> Symbols;
IFSStub() = default;
IFSStub(const IFSStub &Stub)
: IfsVersion(Stub.IfsVersion), Triple(Stub.Triple),
ObjectFileFormat(Stub.ObjectFileFormat), SOName(Stub.SOName),
NeededLibs(Stub.NeededLibs), Symbols(Stub.Symbols) {}
IFSStub(IFSStub &&Stub)
: IfsVersion(std::move(Stub.IfsVersion)), Triple(std::move(Stub.Triple)),
ObjectFileFormat(std::move(Stub.ObjectFileFormat)),
SOName(std::move(Stub.SOName)), NeededLibs(std::move(Stub.NeededLibs)),
Symbols(std::move(Stub.Symbols)) {}
};
namespace llvm {
namespace yaml {
/// YAML traits for IFSStub objects.
template <> struct MappingTraits<IFSStub> {
static void mapping(IO &IO, IFSStub &Stub) {
if (!IO.mapTag("!experimental-ifs-v1", true))
IO.setError("Not a .ifs YAML file.");
IO.mapRequired("IfsVersion", Stub.IfsVersion);
IO.mapOptional("Triple", Stub.Triple);
IO.mapOptional("ObjectFileFormat", Stub.ObjectFileFormat);
IO.mapOptional("SOName", Stub.SOName);
IO.mapOptional("NeededLibs", Stub.NeededLibs);
IO.mapRequired("Symbols", Stub.Symbols);
}
};
} // namespace yaml
} // namespace llvm
static Expected<std::unique_ptr<IFSStub>> readInputFile(StringRef FilePath) {
// Read in file.
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
MemoryBuffer::getFileOrSTDIN(FilePath);
if (!BufOrError)
return createStringError(BufOrError.getError(), "Could not open `%s`",
FilePath.data());
std::unique_ptr<MemoryBuffer> FileReadBuffer = std::move(*BufOrError);
yaml::Input YamlIn(FileReadBuffer->getBuffer());
std::unique_ptr<IFSStub> Stub(new IFSStub());
YamlIn >> *Stub;
if (std::error_code Err = YamlIn.error())
return createStringError(Err, "Failed reading Interface Stub File.");
return std::move(Stub);
}
int writeTbdStub(const llvm::Triple &T, const std::set<IFSSymbol> &Symbols,
const StringRef Format, raw_ostream &Out) {
auto PlatformKindOrError =
[](const llvm::Triple &T) -> llvm::Expected<llvm::MachO::PlatformKind> {
if (T.isMacOSX())
return llvm::MachO::PlatformKind::macOS;
if (T.isTvOS())
return llvm::MachO::PlatformKind::tvOS;
if (T.isWatchOS())
return llvm::MachO::PlatformKind::watchOS;
// Note: put isiOS last because tvOS and watchOS are also iOS according
// to the Triple.
if (T.isiOS())
return llvm::MachO::PlatformKind::iOS;
// TODO: Add an option for ForceTriple, but keep ForceFormat for now.
if (ForceFormat == "TBD")
return llvm::MachO::PlatformKind::macOS;
return createStringError(errc::not_supported, "Invalid Platform.\n");
}(T);
if (!PlatformKindOrError)
return -1;
PlatformKind Plat = PlatformKindOrError.get();
TargetList Targets({Target(llvm::MachO::mapToArchitecture(T), Plat)});
InterfaceFile File;
File.setFileType(FileType::TBD_V3); // Only supporting v3 for now.
File.addTargets(Targets);
for (const auto &Symbol : Symbols) {
auto Name = Symbol.Name;
auto Kind = SymbolKind::GlobalSymbol;
switch (Symbol.Type) {
default:
case IFSSymbolType::NoType:
Kind = SymbolKind::GlobalSymbol;
break;
case IFSSymbolType::Object:
Kind = SymbolKind::GlobalSymbol;
break;
case IFSSymbolType::Func:
Kind = SymbolKind::GlobalSymbol;
break;
}
if (Symbol.Weak)
File.addSymbol(Kind, Name, Targets, SymbolFlags::WeakDefined);
else
File.addSymbol(Kind, Name, Targets);
}
SmallString<4096> Buffer;
raw_svector_ostream OS(Buffer);
if (Error Result = TextAPIWriter::writeToStream(OS, File))
return -1;
Out << OS.str();
return 0;
}
int writeElfStub(const llvm::Triple &T, const std::set<IFSSymbol> &Symbols,
const StringRef Format, raw_ostream &Out) {
SmallString<0> Storage;
Storage.clear();
raw_svector_ostream OS(Storage);
OS << "--- !ELF\n";
OS << "FileHeader:\n";
OS << " Class: ELFCLASS";
OS << (T.isArch64Bit() ? "64" : "32");
OS << "\n";
OS << " Data: ELFDATA2";
OS << (T.isLittleEndian() ? "LSB" : "MSB");
OS << "\n";
OS << " Type: ET_DYN\n";
OS << " Machine: "
<< llvm::StringSwitch<llvm::StringRef>(T.getArchName())
.Case("x86_64", "EM_X86_64")
.Case("i386", "EM_386")
.Case("i686", "EM_386")
.Case("aarch64", "EM_AARCH64")
.Case("amdgcn", "EM_AMDGPU")
.Case("r600", "EM_AMDGPU")
.Case("arm", "EM_ARM")
.Case("thumb", "EM_ARM")
.Case("avr", "EM_AVR")
.Case("mips", "EM_MIPS")
.Case("mipsel", "EM_MIPS")
.Case("mips64", "EM_MIPS")
.Case("mips64el", "EM_MIPS")
.Case("msp430", "EM_MSP430")
.Case("ppc", "EM_PPC")
.Case("ppc64", "EM_PPC64")
.Case("ppc64le", "EM_PPC64")
.Case("x86", T.isOSIAMCU() ? "EM_IAMCU" : "EM_386")
.Case("x86_64", "EM_X86_64")
.Default("EM_NONE")
<< "\nSections:"
<< "\n - Name: .text"
<< "\n Type: SHT_PROGBITS"
<< "\n - Name: .data"
<< "\n Type: SHT_PROGBITS"
<< "\n - Name: .rodata"
<< "\n Type: SHT_PROGBITS"
<< "\nSymbols:\n";
for (const auto &Symbol : Symbols) {
OS << " - Name: " << Symbol.Name << "\n"
<< " Type: STT_";
switch (Symbol.Type) {
default:
case IFSSymbolType::NoType:
OS << "NOTYPE";
break;
case IFSSymbolType::Object:
OS << "OBJECT";
break;
case IFSSymbolType::Func:
OS << "FUNC";
break;
}
OS << "\n Section: .text"
<< "\n Binding: STB_" << (Symbol.Weak ? "WEAK" : "GLOBAL")
<< "\n";
}
OS << "...\n";
std::string YamlStr = OS.str();
// Only or debugging. Not an offical format.
LLVM_DEBUG({
if (ForceFormat == "ELFOBJYAML") {
Out << YamlStr;
return 0;
}
});
yaml::Input YIn(YamlStr);
auto ErrHandler = [](const Twine &Msg) {
WithColor::error(errs(), "llvm-ifs") << Msg << "\n";
};
return convertYAML(YIn, Out, ErrHandler) ? 0 : 1;
}
int writeIfso(const IFSStub &Stub, bool IsWriteIfs, raw_ostream &Out) {
if (IsWriteIfs) {
yaml::Output YamlOut(Out, NULL, /*WrapColumn =*/0);
YamlOut << const_cast<IFSStub &>(Stub);
return 0;
}
std::string ObjectFileFormat =
ForceFormat.empty() ? Stub.ObjectFileFormat : ForceFormat;
if (ObjectFileFormat == "ELF" || ForceFormat == "ELFOBJYAML")
return writeElfStub(llvm::Triple(Stub.Triple), Stub.Symbols,
Stub.ObjectFileFormat, Out);
if (ObjectFileFormat == "TBD")
return writeTbdStub(llvm::Triple(Stub.Triple), Stub.Symbols,
Stub.ObjectFileFormat, Out);
WithColor::error()
<< "Invalid ObjectFileFormat: Only ELF and TBD are supported.\n";
return -1;
}
// New Interface Stubs Yaml Format:
// --- !experimental-ifs-v1
// IfsVersion: 1.0
// Triple: <llvm triple>
// ObjectFileFormat: <ELF | others not yet supported>
// Symbols:
// _ZSymbolName: { Type: <type> }
// ...
int main(int argc, char *argv[]) {
// Parse arguments.
cl::ParseCommandLineOptions(argc, argv);
if (InputFilenames.empty())
InputFilenames.push_back("-");
IFSStub Stub;
std::map<std::string, IFSSymbol> SymbolMap;
std::string PreviousInputFilePath = "";
for (const std::string &InputFilePath : InputFilenames) {
Expected<std::unique_ptr<IFSStub>> StubOrErr = readInputFile(InputFilePath);
if (!StubOrErr) {
WithColor::error() << StubOrErr.takeError() << "\n";
return -1;
}
std::unique_ptr<IFSStub> TargetStub = std::move(StubOrErr.get());
if (Stub.Triple.empty()) {
PreviousInputFilePath = InputFilePath;
Stub.IfsVersion = TargetStub->IfsVersion;
Stub.Triple = TargetStub->Triple;
Stub.ObjectFileFormat = TargetStub->ObjectFileFormat;
Stub.SOName = TargetStub->SOName;
Stub.NeededLibs = TargetStub->NeededLibs;
} else {
if (Stub.IfsVersion != TargetStub->IfsVersion) {
if (Stub.IfsVersion.getMajor() != IFSVersionCurrent.getMajor()) {
WithColor::error()
<< "Interface Stub: IfsVersion Mismatch."
<< "\nFilenames: " << PreviousInputFilePath << " "
<< InputFilePath << "\nIfsVersion Values: " << Stub.IfsVersion
<< " " << TargetStub->IfsVersion << "\n";
return -1;
}
if (TargetStub->IfsVersion > Stub.IfsVersion)
Stub.IfsVersion = TargetStub->IfsVersion;
}
if (Stub.ObjectFileFormat != TargetStub->ObjectFileFormat) {
WithColor::error() << "Interface Stub: ObjectFileFormat Mismatch."
<< "\nFilenames: " << PreviousInputFilePath << " "
<< InputFilePath << "\nObjectFileFormat Values: "
<< Stub.ObjectFileFormat << " "
<< TargetStub->ObjectFileFormat << "\n";
return -1;
}
if (Stub.Triple != TargetStub->Triple) {
WithColor::error() << "Interface Stub: Triple Mismatch."
<< "\nFilenames: " << PreviousInputFilePath << " "
<< InputFilePath
<< "\nTriple Values: " << Stub.Triple << " "
<< TargetStub->Triple << "\n";
return -1;
}
if (Stub.SOName != TargetStub->SOName) {
WithColor::error() << "Interface Stub: SOName Mismatch."
<< "\nFilenames: " << PreviousInputFilePath << " "
<< InputFilePath
<< "\nSOName Values: " << Stub.SOName << " "
<< TargetStub->SOName << "\n";
return -1;
}
if (Stub.NeededLibs != TargetStub->NeededLibs) {
WithColor::error() << "Interface Stub: NeededLibs Mismatch."
<< "\nFilenames: " << PreviousInputFilePath << " "
<< InputFilePath << "\n";
return -1;
}
}
for (auto Symbol : TargetStub->Symbols) {
auto SI = SymbolMap.find(Symbol.Name);
if (SI == SymbolMap.end()) {
SymbolMap.insert(
std::pair<std::string, IFSSymbol>(Symbol.Name, Symbol));
continue;
}
assert(Symbol.Name == SI->second.Name && "Symbol Names Must Match.");
// Check conflicts:
if (Symbol.Type != SI->second.Type) {
WithColor::error() << "Interface Stub: Type Mismatch for "
<< Symbol.Name << ".\nFilename: " << InputFilePath
<< "\nType Values: " << getTypeName(SI->second.Type)
<< " " << getTypeName(Symbol.Type) << "\n";
return -1;
}
if (Symbol.Size != SI->second.Size) {
WithColor::error() << "Interface Stub: Size Mismatch for "
<< Symbol.Name << ".\nFilename: " << InputFilePath
<< "\nSize Values: " << SI->second.Size << " "
<< Symbol.Size << "\n";
return -1;
}
if (Symbol.Weak != SI->second.Weak) {
// TODO: Add conflict resolution for Weak vs non-Weak.
WithColor::error() << "Interface Stub: Weak Mismatch for "
<< Symbol.Name << ".\nFilename: " << InputFilePath
<< "\nWeak Values: " << SI->second.Weak << " "
<< Symbol.Weak << "\n";
return -1;
}
// TODO: Not checking Warning. Will be dropped.
}
PreviousInputFilePath = InputFilePath;
}
if (Stub.IfsVersion != IFSVersionCurrent)
if (Stub.IfsVersion.getMajor() != IFSVersionCurrent.getMajor()) {
WithColor::error() << "Interface Stub: Bad IfsVersion: "
<< Stub.IfsVersion << ", llvm-ifs supported version: "
<< IFSVersionCurrent << ".\n";
return -1;
}
for (auto &Entry : SymbolMap)
Stub.Symbols.insert(Entry.second);
std::error_code SysErr;
// Open file for writing.
raw_fd_ostream Out(OutputFilename, SysErr);
if (SysErr) {
WithColor::error() << "Couldn't open " << OutputFilename
<< " for writing.\n";
return -1;
}
return writeIfso(Stub, (Action == "write-ifs"), Out);
}

View File

@ -1,26 +0,0 @@
set(LLVM_LINK_COMPONENTS
AllTargetsAsmParsers
AllTargetsCodeGens
AllTargetsDescs
AllTargetsInfos
Core
IRReader
Support
Target
TransformUtils
)
add_llvm_tool(llvm-reduce
llvm-reduce.cpp
TestRunner.cpp
deltas/Delta.cpp
deltas/ReduceFunctions.cpp
deltas/ReduceGlobalVars.cpp
deltas/ReduceMetadata.cpp
deltas/ReduceArguments.cpp
deltas/ReduceBasicBlocks.cpp
deltas/ReduceInstructions.cpp
DEPENDS
intrinsics_gen
)

View File

@ -1,36 +0,0 @@
//===- DeltaManager.h - Runs Delta Passes to reduce Input -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file calls each specialized Delta pass in order to reduce the input IR
// file.
//
//===----------------------------------------------------------------------===//
#include "TestRunner.h"
#include "deltas/Delta.h"
#include "deltas/ReduceArguments.h"
#include "deltas/ReduceBasicBlocks.h"
#include "deltas/ReduceFunctions.h"
#include "deltas/ReduceGlobalVars.h"
#include "deltas/ReduceMetadata.h"
#include "deltas/ReduceInstructions.h"
namespace llvm {
// TODO: Add CLI option to run only specified Passes (for unit tests)
inline void runDeltaPasses(TestRunner &Tester) {
reduceFunctionsDeltaPass(Tester);
reduceBasicBlocksDeltaPass(Tester);
reduceGlobalsDeltaPass(Tester);
reduceMetadataDeltaPass(Tester);
reduceArgumentsDeltaPass(Tester);
reduceInstructionsDeltaPass(Tester);
// TODO: Implement the remaining Delta Passes
}
} // namespace llvm

View File

@ -1,24 +0,0 @@
;===- ./tools/llvm-reduce/LLVMBuild.txt ------------------------*- Conf -*--===;
;
; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
; See https://llvm.org/LICENSE.txt for license information.
; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Tool
name = llvm-reduce
parent = Tools
required_libraries =
BitReader
IRReader
all-targets

View File

@ -1,42 +0,0 @@
//===-- TestRunner.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "TestRunner.h"
using namespace llvm;
TestRunner::TestRunner(StringRef TestName, const std::vector<std::string> &TestArgs)
: TestName(TestName), TestArgs(TestArgs) {
}
/// Runs the interestingness test, passes file to be tested as first argument
/// and other specified test arguments after that.
int TestRunner::run(StringRef Filename) {
std::vector<StringRef> ProgramArgs;
ProgramArgs.push_back(TestName);
for (const auto &Arg : TestArgs)
ProgramArgs.push_back(Arg);
ProgramArgs.push_back(Filename);
std::string ErrMsg;
int Result = sys::ExecuteAndWait(
TestName, ProgramArgs, /*Env=*/None, /*Redirects=*/None,
/*SecondsToWait=*/0, /*MemoryLimit=*/0, &ErrMsg);
if (Result < 0) {
Error E = make_error<StringError>("Error running interesting-ness test: " +
ErrMsg,
inconvertibleErrorCode());
errs() << toString(std::move(E));
exit(1);
}
return !Result;
}

View File

@ -1,46 +0,0 @@
//===-- tools/llvm-reduce/TestRunner.h ---------------------------*- C++ -*-===/
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMREDUCE_TESTRUNNER_H
#define LLVM_TOOLS_LLVMREDUCE_TESTRUNNER_H
#include "llvm/ADT/SmallString.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include <vector>
namespace llvm {
// This class contains all the info necessary for running the provided
// interesting-ness test, as well as the most reduced module and its
// respective filename.
class TestRunner {
public:
TestRunner(StringRef TestName, const std::vector<std::string> &TestArgs);
/// Runs the interesting-ness test for the specified file
/// @returns 0 if test was successful, 1 if otherwise
int run(StringRef Filename);
/// Returns the most reduced version of the original testcase
Module *getProgram() const { return Program.get(); }
void setProgram(std::unique_ptr<Module> P) { Program = std::move(P); }
private:
StringRef TestName;
const std::vector<std::string> &TestArgs;
std::unique_ptr<Module> Program;
};
} // namespace llvm
#endif

View File

@ -1,162 +0,0 @@
//===- Delta.cpp - Delta Debugging Algorithm Implementation ---------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the implementation for the Delta Debugging Algorithm:
// it splits a given set of Targets (i.e. Functions, Instructions, BBs, etc.)
// into chunks and tries to reduce the number chunks that are interesting.
//
//===----------------------------------------------------------------------===//
#include "Delta.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <fstream>
#include <set>
using namespace llvm;
bool IsReduced(Module &M, TestRunner &Test, SmallString<128> &CurrentFilepath) {
// Write Module to tmp file
int FD;
std::error_code EC =
sys::fs::createTemporaryFile("llvm-reduce", "ll", FD, CurrentFilepath);
if (EC) {
errs() << "Error making unique filename: " << EC.message() << "!\n";
exit(1);
}
ToolOutputFile Out(CurrentFilepath, FD);
M.print(Out.os(), /*AnnotationWriter=*/nullptr);
Out.os().close();
if (Out.os().has_error()) {
errs() << "Error emitting bitcode to file '" << CurrentFilepath << "'!\n";
exit(1);
}
// Current Chunks aren't interesting
return Test.run(CurrentFilepath);
}
/// Counts the amount of lines for a given file
static int getLines(StringRef Filepath) {
int Lines = 0;
std::string CurrLine;
std::ifstream FileStream(Filepath);
while (std::getline(FileStream, CurrLine))
++Lines;
return Lines;
}
/// Splits Chunks in half and prints them.
/// If unable to split (when chunk size is 1) returns false.
static bool increaseGranularity(std::vector<Chunk> &Chunks) {
errs() << "Increasing granularity...";
std::vector<Chunk> NewChunks;
bool SplitOne = false;
for (auto &C : Chunks) {
if (C.end - C.begin == 0)
NewChunks.push_back(C);
else {
int Half = (C.begin + C.end) / 2;
NewChunks.push_back({C.begin, Half});
NewChunks.push_back({Half + 1, C.end});
SplitOne = true;
}
}
if (SplitOne) {
Chunks = NewChunks;
errs() << "Success! New Chunks:\n";
for (auto C : Chunks) {
errs() << '\t';
C.print();
errs() << '\n';
}
}
return SplitOne;
}
/// Runs the Delta Debugging algorithm, splits the code into chunks and
/// reduces the amount of chunks that are considered interesting by the
/// given test.
void llvm::runDeltaPass(
TestRunner &Test, int Targets,
std::function<void(const std::vector<Chunk> &, Module *)>
ExtractChunksFromModule) {
assert(Targets >= 0);
if (!Targets) {
errs() << "\nNothing to reduce\n";
return;
}
if (Module *Program = Test.getProgram()) {
SmallString<128> CurrentFilepath;
if (!IsReduced(*Program, Test, CurrentFilepath)) {
errs() << "\nInput isn't interesting! Verify interesting-ness test\n";
exit(1);
}
}
std::vector<Chunk> Chunks = {{1, Targets}};
std::set<Chunk> UninterestingChunks;
std::unique_ptr<Module> ReducedProgram;
if (!increaseGranularity(Chunks)) {
errs() << "\nAlready at minimum size. Cannot reduce anymore.\n";
return;
}
do {
UninterestingChunks = {};
for (int I = Chunks.size() - 1; I >= 0; --I) {
std::vector<Chunk> CurrentChunks;
for (auto C : Chunks)
if (!UninterestingChunks.count(C) && C != Chunks[I])
CurrentChunks.push_back(C);
if (CurrentChunks.empty())
continue;
// Clone module before hacking it up..
std::unique_ptr<Module> Clone = CloneModule(*Test.getProgram());
// Generate Module with only Targets inside Current Chunks
ExtractChunksFromModule(CurrentChunks, Clone.get());
errs() << "Ignoring: ";
Chunks[I].print();
for (auto C : UninterestingChunks)
C.print();
SmallString<128> CurrentFilepath;
if (!IsReduced(*Clone, Test, CurrentFilepath)) {
errs() << "\n";
continue;
}
UninterestingChunks.insert(Chunks[I]);
ReducedProgram = std::move(Clone);
errs() << " **** SUCCESS | lines: " << getLines(CurrentFilepath) << "\n";
}
// Delete uninteresting chunks
erase_if(Chunks, [&UninterestingChunks](const Chunk &C) {
return UninterestingChunks.count(C);
});
} while (!UninterestingChunks.empty() || increaseGranularity(Chunks));
// If we reduced the testcase replace it
if (ReducedProgram)
Test.setProgram(std::move(ReducedProgram));
errs() << "Couldn't increase anymore.\n";
}

View File

@ -1,76 +0,0 @@
//===- Delta.h - Delta Debugging Algorithm Implementation -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the implementation for the Delta Debugging Algorithm:
// it splits a given set of Targets (i.e. Functions, Instructions, BBs, etc.)
// into chunks and tries to reduce the number chunks that are interesting.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMREDUCE_LLVMREDUCE_DELTA_H
#define LLVM_TOOLS_LLVMREDUCE_LLVMREDUCE_DELTA_H
#include "TestRunner.h"
#include <vector>
#include <utility>
#include <functional>
namespace llvm {
struct Chunk {
int begin;
int end;
/// Helper function to verify if a given Target-index is inside the Chunk
bool contains(int Index) const { return Index >= begin && Index <= end; }
void print() const {
errs() << "[" << begin;
if (end - begin != 0)
errs() << "," << end;
errs() << "]";
}
/// Operator when populating CurrentChunks in Generic Delta Pass
friend bool operator!=(const Chunk &C1, const Chunk &C2) {
return C1.begin != C2.begin || C1.end != C2.end;
}
/// Operator used for sets
friend bool operator<(const Chunk &C1, const Chunk &C2) {
return std::tie(C1.begin, C1.end) < std::tie(C2.begin, C2.end);
}
};
/// This function implements the Delta Debugging algorithm, it receives a
/// number of Targets (e.g. Functions, Instructions, Basic Blocks, etc.) and
/// splits them in half; these chunks of targets are then tested while ignoring
/// one chunk, if a chunk is proven to be uninteresting (i.e. fails the test)
/// it is removed from consideration. The algorithm will attempt to split the
/// Chunks in half and start the process again until it can't split chunks
/// anymore.
///
/// This function is intended to be called by each specialized delta pass (e.g.
/// RemoveFunctions) and receives three key parameters:
/// * Test: The main TestRunner instance which is used to run the provided
/// interesting-ness test, as well as to store and access the reduced Program.
/// * Targets: The amount of Targets that are going to be reduced by the
/// algorithm, for example, the RemoveGlobalVars pass would send the amount of
/// initialized GVs.
/// * ExtractChunksFromModule: A function used to tailor the main program so it
/// only contains Targets that are inside Chunks of the given iteration.
/// Note: This function is implemented by each specialized Delta pass
///
/// Other implementations of the Delta Debugging algorithm can also be found in
/// the CReduce, Delta, and Lithium projects.
void runDeltaPass(TestRunner &Test, int Targets,
std::function<void(const std::vector<Chunk> &, Module *)>
ExtractChunksFromModule);
} // namespace llvm
#endif

View File

@ -1,125 +0,0 @@
//===- ReduceArguments.cpp - Specialized Delta Pass -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce uninteresting Arguments from defined functions.
//
//===----------------------------------------------------------------------===//
#include "ReduceArguments.h"
#include "Delta.h"
#include "llvm/ADT/SmallVector.h"
#include <set>
#include <vector>
using namespace llvm;
/// Goes over OldF calls and replaces them with a call to NewF
static void replaceFunctionCalls(Function &OldF, Function &NewF,
const std::set<int> &ArgIndexesToKeep) {
const auto &Users = OldF.users();
for (auto I = Users.begin(), E = Users.end(); I != E; )
if (auto *CI = dyn_cast<CallInst>(*I++)) {
SmallVector<Value *, 8> Args;
for (auto ArgI = CI->arg_begin(), E = CI->arg_end(); ArgI != E; ++ArgI)
if (ArgIndexesToKeep.count(ArgI - CI->arg_begin()))
Args.push_back(*ArgI);
CallInst *NewCI = CallInst::Create(&NewF, Args);
NewCI->setCallingConv(NewF.getCallingConv());
if (!CI->use_empty())
CI->replaceAllUsesWith(NewCI);
ReplaceInstWithInst(CI, NewCI);
}
}
/// Removes out-of-chunk arguments from functions, and modifies their calls
/// accordingly. It also removes allocations of out-of-chunk arguments.
static void extractArgumentsFromModule(std::vector<Chunk> ChunksToKeep,
Module *Program) {
int I = 0, ArgCount = 0;
std::set<Argument *> ArgsToKeep;
std::vector<Function *> Funcs;
// Get inside-chunk arguments, as well as their parent function
for (auto &F : *Program)
if (!F.isDeclaration()) {
Funcs.push_back(&F);
for (auto &A : F.args())
if (I < (int)ChunksToKeep.size()) {
if (ChunksToKeep[I].contains(++ArgCount))
ArgsToKeep.insert(&A);
if (ChunksToKeep[I].end == ArgCount)
++I;
}
}
for (auto *F : Funcs) {
ValueToValueMapTy VMap;
std::vector<Instruction *> InstToDelete;
for (auto &A : F->args())
if (!ArgsToKeep.count(&A)) {
// By adding undesired arguments to the VMap, CloneFunction will remove
// them from the resulting Function
VMap[&A] = UndefValue::get(A.getType());
for (auto *U : A.users())
if (auto *I = dyn_cast<Instruction>(*&U))
InstToDelete.push_back(I);
}
// Delete any instruction that uses the argument
for (auto *I : InstToDelete) {
I->replaceAllUsesWith(UndefValue::get(I->getType()));
I->eraseFromParent();
}
// No arguments to reduce
if (VMap.empty())
continue;
std::set<int> ArgIndexesToKeep;
int ArgI = 0;
for (auto &Arg : F->args())
if (ArgsToKeep.count(&Arg))
ArgIndexesToKeep.insert(++ArgI);
auto *ClonedFunc = CloneFunction(F, VMap);
// In order to preserve function order, we move Clone after old Function
ClonedFunc->removeFromParent();
Program->getFunctionList().insertAfter(F->getIterator(), ClonedFunc);
replaceFunctionCalls(*F, *ClonedFunc, ArgIndexesToKeep);
// Rename Cloned Function to Old's name
std::string FName = F->getName();
F->eraseFromParent();
ClonedFunc->setName(FName);
}
}
/// Counts the amount of arguments in non-declaration functions and prints their
/// respective name, index, and parent function name
static int countArguments(Module *Program) {
// TODO: Silence index with --quiet flag
outs() << "----------------------------\n";
outs() << "Param Index Reference:\n";
int ArgsCount = 0;
for (auto &F : *Program)
if (!F.isDeclaration() && F.arg_size()) {
outs() << " " << F.getName() << "\n";
for (auto &A : F.args())
outs() << "\t" << ++ArgsCount << ": " << A.getName() << "\n";
outs() << "----------------------------\n";
}
return ArgsCount;
}
void llvm::reduceArgumentsDeltaPass(TestRunner &Test) {
outs() << "*** Reducing Arguments...\n";
int ArgCount = countArguments(Test.getProgram());
runDeltaPass(Test, ArgCount, extractArgumentsFromModule);
}

View File

@ -1,21 +0,0 @@
//===- ReduceArguments.h - Specialized Delta Pass -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce uninteresting Arguments from defined functions.
//
//===----------------------------------------------------------------------===//
#include "Delta.h"
#include "llvm/IR/Argument.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
namespace llvm {
void reduceArgumentsDeltaPass(TestRunner &Test);
} // namespace llvm

View File

@ -1,146 +0,0 @@
//===- ReduceArguments.cpp - Specialized Delta Pass -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce uninteresting Arguments from defined functions.
//
//===----------------------------------------------------------------------===//
#include "ReduceBasicBlocks.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include <vector>
using namespace llvm;
/// Replaces BB Terminator with one that only contains Chunk BBs
static void replaceBranchTerminator(BasicBlock &BB,
std::set<BasicBlock *> BBsToKeep) {
auto Term = BB.getTerminator();
std::vector<BasicBlock *> ChunkSucessors;
for (auto Succ : successors(&BB))
if (BBsToKeep.count(Succ))
ChunkSucessors.push_back(Succ);
// BB only references Chunk BBs
if (ChunkSucessors.size() == Term->getNumSuccessors())
return;
bool IsBranch = isa<BranchInst>(Term);
Value *Address = nullptr;
if (auto IndBI = dyn_cast<IndirectBrInst>(Term))
Address = IndBI->getAddress();
Term->eraseFromParent();
if (ChunkSucessors.empty()) {
ReturnInst::Create(BB.getContext(), nullptr, &BB);
return;
}
if (IsBranch)
BranchInst::Create(ChunkSucessors[0], &BB);
if (Address) {
auto NewIndBI =
IndirectBrInst::Create(Address, ChunkSucessors.size(), &BB);
for (auto Dest : ChunkSucessors)
NewIndBI->addDestination(Dest);
}
}
/// Removes uninteresting BBs from switch, if the default case ends up being
/// uninteresting, the switch is replaced with a void return (since it has to be
/// replace with something)
static void removeUninterestingBBsFromSwitch(SwitchInst &SwInst,
std::set<BasicBlock *> BBsToKeep) {
if (!BBsToKeep.count(SwInst.getDefaultDest())) {
ReturnInst::Create(SwInst.getContext(), nullptr, SwInst.getParent());
SwInst.eraseFromParent();
} else
for (int I = 0, E = SwInst.getNumCases(); I != E; ++I) {
auto Case = SwInst.case_begin() + I;
if (!BBsToKeep.count(Case->getCaseSuccessor())) {
SwInst.removeCase(Case);
--I;
--E;
}
}
}
/// Removes out-of-chunk arguments from functions, and modifies their calls
/// accordingly. It also removes allocations of out-of-chunk arguments.
static void extractBasicBlocksFromModule(std::vector<Chunk> ChunksToKeep,
Module *Program) {
int I = 0, BBCount = 0;
std::set<BasicBlock *> BBsToKeep;
for (auto &F : *Program)
for (auto &BB : F)
if (I < (int)ChunksToKeep.size()) {
if (ChunksToKeep[I].contains(++BBCount))
BBsToKeep.insert(&BB);
if (ChunksToKeep[I].end == BBCount)
++I;
}
std::vector<BasicBlock *> BBsToDelete;
for (auto &F : *Program)
for (auto &BB : F) {
if (!BBsToKeep.count(&BB)) {
BBsToDelete.push_back(&BB);
// Remove out-of-chunk BB from successor phi nodes
for (auto *Succ : successors(&BB))
Succ->removePredecessor(&BB);
}
}
// Replace terminators that reference out-of-chunk BBs
for (auto &F : *Program)
for (auto &BB : F) {
if (auto *SwInst = dyn_cast<SwitchInst>(BB.getTerminator()))
removeUninterestingBBsFromSwitch(*SwInst, BBsToKeep);
else
replaceBranchTerminator(BB, BBsToKeep);
}
// Replace out-of-chunk switch uses
for (auto &BB : BBsToDelete) {
// Instructions might be referenced in other BBs
for (auto &I : *BB)
I.replaceAllUsesWith(UndefValue::get(I.getType()));
BB->eraseFromParent();
}
}
/// Counts the amount of basic blocks and prints their name & respective index
static int countBasicBlocks(Module *Program) {
// TODO: Silence index with --quiet flag
outs() << "----------------------------\n";
int BBCount = 0;
for (auto &F : *Program)
for (auto &BB : F) {
if (BB.hasName())
outs() << "\t" << ++BBCount << ": " << BB.getName() << "\n";
else
outs() << "\t" << ++BBCount << ": Unnamed\n";
}
return BBCount;
}
void llvm::reduceBasicBlocksDeltaPass(TestRunner &Test) {
outs() << "*** Reducing Basic Blocks...\n";
int BBCount = countBasicBlocks(Test.getProgram());
runDeltaPass(Test, BBCount, extractBasicBlocksFromModule);
}

View File

@ -1,20 +0,0 @@
//===- ReduceArguments.h - Specialized Delta Pass -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce uninteresting Arguments from defined functions.
//
//===----------------------------------------------------------------------===//
#include "Delta.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
namespace llvm {
void reduceBasicBlocksDeltaPass(TestRunner &Test);
} // namespace llvm

View File

@ -1,77 +0,0 @@
//===- ReduceFunctions.cpp - Specialized Delta Pass -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce functions (and any instruction that calls it) in the provided
// Module.
//
//===----------------------------------------------------------------------===//
#include "ReduceFunctions.h"
#include "Delta.h"
#include "llvm/ADT/SetVector.h"
#include <set>
using namespace llvm;
/// Removes all the Defined Functions (as well as their calls)
/// that aren't inside any of the desired Chunks.
static void extractFunctionsFromModule(const std::vector<Chunk> &ChunksToKeep,
Module *Program) {
// Get functions inside desired chunks
std::set<Function *> FuncsToKeep;
int I = 0, FunctionCount = 0;
for (auto &F : *Program)
if (I < (int)ChunksToKeep.size()) {
if (ChunksToKeep[I].contains(++FunctionCount))
FuncsToKeep.insert(&F);
if (FunctionCount == ChunksToKeep[I].end)
++I;
}
// Delete out-of-chunk functions, and replace their calls with undef
std::vector<Function *> FuncsToRemove;
SetVector<CallInst *> CallsToRemove;
for (auto &F : *Program)
if (!FuncsToKeep.count(&F)) {
for (auto U : F.users())
if (auto *Call = dyn_cast<CallInst>(U)) {
Call->replaceAllUsesWith(UndefValue::get(Call->getType()));
CallsToRemove.insert(Call);
}
F.replaceAllUsesWith(UndefValue::get(F.getType()));
FuncsToRemove.push_back(&F);
}
for (auto *C : CallsToRemove)
C->eraseFromParent();
for (auto *F : FuncsToRemove)
F->eraseFromParent();
}
/// Counts the amount of non-declaration functions and prints their
/// respective name & index
static int countFunctions(Module *Program) {
// TODO: Silence index with --quiet flag
errs() << "----------------------------\n";
errs() << "Function Index Reference:\n";
int FunctionCount = 0;
for (auto &F : *Program)
errs() << "\t" << ++FunctionCount << ": " << F.getName() << "\n";
errs() << "----------------------------\n";
return FunctionCount;
}
void llvm::reduceFunctionsDeltaPass(TestRunner &Test) {
errs() << "*** Reducing Functions...\n";
int Functions = countFunctions(Test.getProgram());
runDeltaPass(Test, Functions, extractFunctionsFromModule);
errs() << "----------------------------\n";
}

View File

@ -1,20 +0,0 @@
//===- ReduceFunctions.h - Specialized Delta Pass -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce functions (and any instruction that calls it) in the provided
// Module.
//
//===----------------------------------------------------------------------===//
#include "Delta.h"
#include "llvm/Transforms/Utils/Cloning.h"
namespace llvm {
void reduceFunctionsDeltaPass(TestRunner &Test);
} // namespace llvm

View File

@ -1,74 +0,0 @@
//===- ReduceGlobalVars.cpp - Specialized Delta Pass ----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce initialized Global Variables in the provided Module.
//
//===----------------------------------------------------------------------===//
#include "ReduceGlobalVars.h"
#include <set>
using namespace llvm;
/// Removes all the Initialized GVs that aren't inside the desired Chunks.
static void extractGVsFromModule(std::vector<Chunk> ChunksToKeep,
Module *Program) {
// Get GVs inside desired chunks
std::set<GlobalVariable *> GVsToKeep;
int I = 0, GVCount = 0;
for (auto &GV : Program->globals())
if (GV.hasInitializer() && I < (int)ChunksToKeep.size()) {
if (ChunksToKeep[I].contains(++GVCount))
GVsToKeep.insert(&GV);
if (GVCount == ChunksToKeep[I].end)
++I;
}
// Delete out-of-chunk GVs and their uses
std::vector<GlobalVariable *> ToRemove;
std::vector<Instruction *> InstToRemove;
for (auto &GV : Program->globals())
if (GV.hasInitializer() && !GVsToKeep.count(&GV)) {
for (auto U : GV.users())
if (auto *Inst = dyn_cast<Instruction>(U))
InstToRemove.push_back(Inst);
GV.replaceAllUsesWith(UndefValue::get(GV.getType()));
ToRemove.push_back(&GV);
}
// Delete Instruction uses of unwanted GVs
for (auto *Inst : InstToRemove) {
Inst->replaceAllUsesWith(UndefValue::get(Inst->getType()));
Inst->eraseFromParent();
}
for (auto *GV : ToRemove)
GV->eraseFromParent();
}
/// Counts the amount of initialized GVs and displays their
/// respective name & index
static int countGVs(Module *Program) {
// TODO: Silence index with --quiet flag
outs() << "----------------------------\n";
outs() << "GlobalVariable Index Reference:\n";
int GVCount = 0;
for (auto &GV : Program->globals())
if (GV.hasInitializer())
outs() << "\t" << ++GVCount << ": " << GV.getName() << "\n";
outs() << "----------------------------\n";
return GVCount;
}
void llvm::reduceGlobalsDeltaPass(TestRunner &Test) {
outs() << "*** Reducing GVs...\n";
int GVCount = countGVs(Test.getProgram());
runDeltaPass(Test, GVCount, extractGVsFromModule);
}

View File

@ -1,20 +0,0 @@
//===- ReduceGlobalVars.h - Specialized Delta Pass ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce initialized Global Variables in the provided Module.
//
//===----------------------------------------------------------------------===//
#include "Delta.h"
#include "llvm/IR/Value.h"
#include "llvm/Transforms/Utils/Cloning.h"
namespace llvm {
void reduceGlobalsDeltaPass(TestRunner &Test);
} // namespace llvm

View File

@ -1,65 +0,0 @@
//===- ReduceArguments.cpp - Specialized Delta Pass -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce uninteresting Arguments from defined functions.
//
//===----------------------------------------------------------------------===//
#include "ReduceInstructions.h"
using namespace llvm;
/// Removes out-of-chunk arguments from functions, and modifies their calls
/// accordingly. It also removes allocations of out-of-chunk arguments.
static void extractInstrFromModule(std::vector<Chunk> ChunksToKeep,
Module *Program) {
int I = 0, InstCount = 0;
std::set<Instruction *> InstToKeep;
for (auto &F : *Program)
for (auto &BB : F)
for (auto &Inst : BB)
if (I < (int)ChunksToKeep.size()) {
if (ChunksToKeep[I].contains(++InstCount))
InstToKeep.insert(&Inst);
if (ChunksToKeep[I].end == InstCount)
++I;
}
std::vector<Instruction *> InstToDelete;
for (auto &F : *Program)
for (auto &BB : F)
for (auto &Inst : BB)
if (!InstToKeep.count(&Inst)) {
Inst.replaceAllUsesWith(UndefValue::get(Inst.getType()));
InstToDelete.push_back(&Inst);
}
for (auto &I : InstToDelete)
I->eraseFromParent();
}
/// Counts the amount of basic blocks and prints their name & respective index
static unsigned countInstructions(Module *Program) {
// TODO: Silence index with --quiet flag
outs() << "----------------------------\n";
int InstCount = 0;
for (auto &F : *Program)
for (auto &BB : F)
InstCount += BB.getInstList().size();
outs() << "Number of instructions: " << InstCount << "\n";
return InstCount;
}
void llvm::reduceInstructionsDeltaPass(TestRunner &Test) {
outs() << "*** Reducing Insructions...\n";
unsigned InstCount = countInstructions(Test.getProgram());
runDeltaPass(Test, InstCount, extractInstrFromModule);
}

View File

@ -1,20 +0,0 @@
//===- ReduceArguments.h - Specialized Delta Pass -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce uninteresting Arguments from defined functions.
//
//===----------------------------------------------------------------------===//
#include "Delta.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
namespace llvm {
void reduceInstructionsDeltaPass(TestRunner &Test);
} // namespace llvm

View File

@ -1,138 +0,0 @@
//===- ReduceMetadata.cpp - Specialized Delta Pass ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements two functions used by the Generic Delta Debugging
// Algorithm, which are used to reduce Metadata nodes.
//
//===----------------------------------------------------------------------===//
#include "ReduceMetadata.h"
#include "Delta.h"
#include "llvm/ADT/SmallVector.h"
#include <set>
#include <vector>
using namespace llvm;
/// Adds all Unnamed Metadata Nodes that are inside desired Chunks to set
template <class T>
static void getChunkMetadataNodes(T &MDUser, int &I,
const std::vector<Chunk> &ChunksToKeep,
std::set<MDNode *> &SeenNodes,
std::set<MDNode *> &NodesToKeep) {
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
MDUser.getAllMetadata(MDs);
for (auto &MD : MDs) {
SeenNodes.insert(MD.second);
if (I < (int)ChunksToKeep.size()) {
if (ChunksToKeep[I].contains(SeenNodes.size()))
NodesToKeep.insert(MD.second);
if (ChunksToKeep[I].end == (int)SeenNodes.size())
++I;
}
}
}
/// Erases out-of-chunk unnamed metadata nodes from its user
template <class T>
static void eraseMetadataIfOutsideChunk(T &MDUser,
const std::set<MDNode *> &NodesToKeep) {
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
MDUser.getAllMetadata(MDs);
for (int I = 0, E = MDs.size(); I != E; ++I)
if (!NodesToKeep.count(MDs[I].second))
MDUser.setMetadata(I, NULL);
}
/// Removes all the Named and Unnamed Metadata Nodes, as well as any debug
/// functions that aren't inside the desired Chunks.
static void extractMetadataFromModule(const std::vector<Chunk> &ChunksToKeep,
Module *Program) {
std::set<MDNode *> SeenNodes;
std::set<MDNode *> NodesToKeep;
int I = 0;
// Add chunk MDNodes used by GVs, Functions, and Instructions to set
for (auto &GV : Program->globals())
getChunkMetadataNodes(GV, I, ChunksToKeep, SeenNodes, NodesToKeep);
for (auto &F : *Program) {
getChunkMetadataNodes(F, I, ChunksToKeep, SeenNodes, NodesToKeep);
for (auto &BB : F)
for (auto &Inst : BB)
getChunkMetadataNodes(Inst, I, ChunksToKeep, SeenNodes, NodesToKeep);
}
// Once more, go over metadata nodes, but deleting the ones outside chunks
for (auto &GV : Program->globals())
eraseMetadataIfOutsideChunk(GV, NodesToKeep);
for (auto &F : *Program) {
eraseMetadataIfOutsideChunk(F, NodesToKeep);
for (auto &BB : F)
for (auto &Inst : BB)
eraseMetadataIfOutsideChunk(Inst, NodesToKeep);
}
// Get out-of-chunk Named metadata nodes
unsigned MetadataCount = SeenNodes.size();
std::vector<NamedMDNode *> NamedNodesToDelete;
for (auto &MD : Program->named_metadata()) {
if (I < (int)ChunksToKeep.size()) {
if (!ChunksToKeep[I].contains(++MetadataCount))
NamedNodesToDelete.push_back(&MD);
if (ChunksToKeep[I].end == (int)SeenNodes.size())
++I;
} else
NamedNodesToDelete.push_back(&MD);
}
for (auto *NN : NamedNodesToDelete) {
for (int I = 0, E = NN->getNumOperands(); I != E; ++I)
NN->setOperand(I, NULL);
NN->eraseFromParent();
}
}
// Gets unnamed metadata nodes used by a given instruction/GV/function and adds
// them to the set of seen nodes
template <class T>
static void addMetadataToSet(T &MDUser, std::set<MDNode *> &UnnamedNodes) {
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
MDUser.getAllMetadata(MDs);
for (auto &MD : MDs)
UnnamedNodes.insert(MD.second);
}
/// Returns the amount of Named and Unnamed Metadata Nodes
static int countMetadataTargets(Module *Program) {
std::set<MDNode *> UnnamedNodes;
int NamedMetadataNodes = Program->named_metadata_size();
// Get metadata nodes used by globals
for (auto &GV : Program->globals())
addMetadataToSet(GV, UnnamedNodes);
// Do the same for nodes used by functions & instructions
for (auto &F : *Program) {
addMetadataToSet(F, UnnamedNodes);
for (auto &BB : F)
for (auto &I : BB)
addMetadataToSet(I, UnnamedNodes);
}
return UnnamedNodes.size() + NamedMetadataNodes;
}
void llvm::reduceMetadataDeltaPass(TestRunner &Test) {
outs() << "*** Reducing Metadata...\n";
int MDCount = countMetadataTargets(Test.getProgram());
runDeltaPass(Test, MDCount, extractMetadataFromModule);
outs() << "----------------------------\n";
}

View File

@ -1,18 +0,0 @@
//===- ReduceMetadata.h - Specialized Delta Pass ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements two functions used by the Generic Delta Debugging
// Algorithm, which are used to reduce Metadata nodes.
//
//===----------------------------------------------------------------------===//
#include "TestRunner.h"
namespace llvm {
void reduceMetadataDeltaPass(TestRunner &Test);
} // namespace llvm

View File

@ -1,114 +0,0 @@
//===- llvm-reduce.cpp - The LLVM Delta Reduction utility -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This program tries to reduce an IR test case for a given interesting-ness
// test. It runs multiple delta debugging passes in order to minimize the input
// file. It's worth noting that this is a part of the bugpoint redesign
// proposal, and thus a *temporary* tool that will eventually be integrated
// into the bugpoint tool itself.
//
//===----------------------------------------------------------------------===//
#include "DeltaManager.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include <system_error>
#include <vector>
using namespace llvm;
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
static cl::opt<bool> Version("v", cl::desc("Alias for -version"), cl::Hidden);
static cl::opt<std::string> InputFilename(cl::Positional, cl::Required,
cl::desc("<input llvm ll/bc file>"));
static cl::opt<std::string>
TestFilename("test", cl::Required,
cl::desc("Name of the interesting-ness test to be run"));
static cl::list<std::string>
TestArguments("test-arg", cl::ZeroOrMore,
cl::desc("Arguments passed onto the interesting-ness test"));
static cl::opt<std::string>
OutputFilename("output",
cl::desc("Specify the output file. default: reduced.ll"));
static cl::alias OutputFileAlias("o", cl::desc("Alias for -output"),
cl::aliasopt(OutputFilename));
static cl::opt<bool>
ReplaceInput("in-place",
cl::desc("WARNING: This option will replace your input file"
"with the reduced version!"));
// Parses IR into a Module and verifies it
static std::unique_ptr<Module> parseInputFile(StringRef Filename,
LLVMContext &Ctxt) {
SMDiagnostic Err;
std::unique_ptr<Module> Result = parseIRFile(Filename, Err, Ctxt);
if (!Result) {
Err.print("llvm-reduce", errs());
return Result;
}
if (verifyModule(*Result, &errs())) {
errs() << "Error: " << Filename << " - input module is broken!\n";
return std::unique_ptr<Module>();
}
return Result;
}
int main(int argc, char **argv) {
InitLLVM X(argc, argv);
cl::ParseCommandLineOptions(argc, argv, "LLVM automatic testcase reducer.\n");
LLVMContext Context;
std::unique_ptr<Module> OriginalProgram =
parseInputFile(InputFilename, Context);
// Initialize test environment
TestRunner Tester(TestFilename, TestArguments);
Tester.setProgram(std::move(OriginalProgram));
// Try to reduce code
runDeltaPasses(Tester);
if (!Tester.getProgram()) {
errs() << "\nCouldnt reduce input :/\n";
} else {
// Print reduced file to STDOUT
if (OutputFilename == "-")
Tester.getProgram()->print(outs(), nullptr);
else {
if (ReplaceInput) // In-place
OutputFilename = InputFilename.c_str();
else if (OutputFilename.empty())
OutputFilename = "reduced.ll";
std::error_code EC;
raw_fd_ostream Out(OutputFilename, EC);
if (EC) {
errs() << "Error opening output file: " << EC.message() << "!\n";
exit(1);
}
Tester.getProgram()->print(Out, /*AnnotationWriter=*/nullptr);
errs() << "\nDone reducing! Reduced testcase: " << OutputFilename << "\n";
}
}
return 0;
}

View File

@ -1,7 +0,0 @@
set(LLVM_LINK_COMPONENTS
Analysis
Support
)
add_llvm_fuzzer(vfabi-demangler-fuzzer
vfabi-demangler-fuzzer.cpp
)

View File

@ -1,26 +0,0 @@
//===-- vfabi-demangler-fuzzer.cpp - Fuzzer VFABI using lib/Fuzzer ------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Build tool to fuzz the demangler for the vector function ABI names.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/VectorUtils.h"
using namespace llvm;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
const StringRef MangledName((const char *)Data, Size);
const auto Info = VFABI::tryDemangleForVFABI(MangledName);
// Do not optimize away the return value. Inspired by
// https://github.com/google/benchmark/blob/master/include/benchmark/benchmark.h#L307-L345
asm volatile("" : : "r,m"(Info) : "memory");
return 0;
}

View File

@ -1,7 +0,0 @@
set(LLVM_LINK_COMPONENTS
Support
)
llvm_add_library(LLVMTableGenGlobalISel STATIC DISABLE_LLVM_LINK_LLVM_DYLIB
CodeExpander.cpp
)

View File

@ -1,82 +0,0 @@
#!/usr/bin/env python3
import re, sys
def fix_string(s):
TYPE = re.compile('\s*(i[0-9]+|float|double|x86_fp80|fp128|ppc_fp128|\[\[.*?\]\]|\[2 x \[\[[A-Z_0-9]+\]\]\]|<.*?>|{.*?}|\[[0-9]+ x .*?\]|%["a-z:A-Z0-9._]+({{.*?}})?|%{{.*?}}|{{.*?}}|\[\[.*?\]\])(\s*(\*|addrspace\(.*?\)|dereferenceable\(.*?\)|byval\(.*?\)|sret|zeroext|inreg|returned|signext|nocapture|align \d+|swiftself|swifterror|readonly|noalias|inalloca|nocapture))*\s*')
counter = 0
if 'i32{{.*}}' in s:
counter = 1
at_pos = s.find('@')
if at_pos == -1:
at_pos = 0
annoying_pos = s.find('{{[^(]+}}')
if annoying_pos != -1:
at_pos = annoying_pos + 9
paren_pos = s.find('(', at_pos)
if paren_pos == -1:
return s
res = s[:paren_pos+1]
s = s[paren_pos+1:]
m = TYPE.match(s)
while m:
res += m.group()
s = s[m.end():]
if s.startswith(',') or s.startswith(')'):
res += f' %{counter}'
counter += 1
next_arg = s.find(',')
if next_arg == -1:
break
res += s[:next_arg+1]
s = s[next_arg+1:]
m = TYPE.match(s)
return res+s
def process_file(contents):
PREFIX = re.compile(r'check-prefix(es)?(=|\s+)([a-zA-Z0-9,]+)')
check_prefixes = ['CHECK']
result = ''
for line in contents.split('\n'):
if 'FileCheck' in line:
m = PREFIX.search(line)
if m:
check_prefixes.extend(m.group(3).split(','))
found_check = False
for prefix in check_prefixes:
if prefix in line:
found_check = True
break
if not found_check or 'define' not in line:
result += line + '\n'
continue
# We have a check for a function definition. Number the args.
line = fix_string(line)
result += line + '\n'
return result
def main():
print(f'Processing {sys.argv[1]}')
f = open(sys.argv[1])
content = f.read()
f.close()
content = process_file(content)
f = open(sys.argv[1], 'w')
f.write(content)
f.close()
if __name__ == '__main__':
main()

View File

@ -1,12 +0,0 @@
if (LLVM_BUILD_UTILS AND LLVM_BUILD_TOOLS)
add_custom_command(
OUTPUT ${LLVM_TOOLS_BINARY_DIR}/llvm-locstats
DEPENDS ${LLVM_MAIN_SRC_DIR}/utils/llvm-locstats/llvm-locstats.py
COMMAND ${CMAKE_COMMAND} -E copy ${LLVM_MAIN_SRC_DIR}/utils/llvm-locstats/llvm-locstats.py ${LLVM_TOOLS_BINARY_DIR}/llvm-locstats
COMMENT "Copying llvm-locstats into ${LLVM_TOOLS_BINARY_DIR}"
)
add_custom_target(llvm-locstats ALL
DEPENDS ${LLVM_TOOLS_BINARY_DIR}/llvm-locstats
)
set_target_properties(llvm-locstats PROPERTIES FOLDER "Tools")
endif()

View File

@ -1,209 +0,0 @@
#!/usr/bin/env python
#
# This is a tool that works like debug location coverage calculator.
# It parses the llvm-dwarfdump --statistics output by reporting it
# in a more human readable way.
#
from __future__ import print_function
import argparse
import os
import sys
from json import loads
from math import ceil
from subprocess import Popen, PIPE
def coverage_buckets():
yield '0%'
yield '1-9%'
for start in range(10, 91, 10):
yield '{0}-{1}%'.format(start, start + 9)
yield '100%'
def locstats_output(
variables_total,
variables_total_locstats,
variables_with_loc,
scope_bytes_covered,
scope_bytes_from_first_def,
variables_coverage_map
):
pc_ranges_covered = int(ceil(scope_bytes_covered * 100.0)
/ scope_bytes_from_first_def)
variables_coverage_per_map = {}
for cov_bucket in coverage_buckets():
variables_coverage_per_map[cov_bucket] = \
int(ceil(variables_coverage_map[cov_bucket] * 100.0) \
/ variables_total_locstats)
print (' =================================================')
print (' Debug Location Statistics ')
print (' =================================================')
print (' cov% samples percentage(~) ')
print (' -------------------------------------------------')
for cov_bucket in coverage_buckets():
print (' {0:6} {1:8d} {2:3d}%'. \
format(cov_bucket, variables_coverage_map[cov_bucket], \
variables_coverage_per_map[cov_bucket]))
print (' =================================================')
print (' -the number of debug variables processed: ' \
+ str(variables_total_locstats))
print (' -PC ranges covered: ' + str(pc_ranges_covered) + '%')
# Only if we are processing all the variables output the total
# availability.
if variables_total and variables_with_loc:
total_availability = int(ceil(variables_with_loc * 100.0) \
/ variables_total)
print (' -------------------------------------------------')
print (' -total availability: ' + str(total_availability) + '%')
print (' =================================================')
def parse_program_args(parser):
parser.add_argument('-only-variables', action='store_true',
default=False,
help='calculate the location statistics only for '
'local variables'
)
parser.add_argument('-only-formal-parameters', action='store_true',
default=False,
help='calculate the location statistics only for '
'formal parameters'
)
parser.add_argument('-ignore-debug-entry-values', action='store_true',
default=False,
help='ignore the location statistics on locations with '
'entry values'
)
parser.add_argument('file_name', type=str, help='file to process')
return parser.parse_args()
def Main():
parser = argparse.ArgumentParser()
results = parse_program_args(parser)
if len(sys.argv) < 2:
print ('error: Too few arguments.')
parser.print_help()
sys.exit(1)
if results.only_variables and results.only_formal_parameters:
print ('error: Please use just one only* option.')
parser.print_help()
sys.exit(1)
# These will be different due to different options enabled.
variables_total = None
variables_total_locstats = None
variables_with_loc = None
variables_scope_bytes_covered = None
variables_scope_bytes_from_first_def = None
variables_scope_bytes_entry_values = None
variables_coverage_map = {}
binary = results.file_name
# Get the directory of the LLVM tools.
llvm_dwarfdump_cmd = os.path.join(os.path.dirname(__file__), \
"llvm-dwarfdump")
# The statistics llvm-dwarfdump option.
llvm_dwarfdump_stats_opt = "--statistics"
subproc = Popen([llvm_dwarfdump_cmd, llvm_dwarfdump_stats_opt, binary], \
stdin=PIPE, stdout=PIPE, stderr=PIPE, \
universal_newlines = True)
cmd_stdout, cmd_stderr = subproc.communicate()
# Get the JSON and parse it.
json_parsed = None
try:
json_parsed = loads(cmd_stdout)
except:
print ('error: No valid llvm-dwarfdump statistics found.')
sys.exit(1)
if results.only_variables:
# Read the JSON only for local variables.
variables_total_locstats = \
json_parsed['total vars procesed by location statistics']
variables_scope_bytes_covered = \
json_parsed['vars scope bytes covered']
variables_scope_bytes_from_first_def = \
json_parsed['vars scope bytes total']
if not results.ignore_debug_entry_values:
for cov_bucket in coverage_buckets():
cov_category = "vars with {} of its scope covered".format(cov_bucket)
variables_coverage_map[cov_bucket] = json_parsed[cov_category]
else:
variables_scope_bytes_entry_values = \
json_parsed['vars entry value scope bytes covered']
variables_scope_bytes_covered = variables_scope_bytes_covered \
- variables_scope_bytes_entry_values
for cov_bucket in coverage_buckets():
cov_category = \
"vars (excluding the debug entry values) " \
"with {} of its scope covered".format(cov_bucket)
variables_coverage_map[cov_bucket] = json_parsed[cov_category]
elif results.only_formal_parameters:
# Read the JSON only for formal parameters.
variables_total_locstats = \
json_parsed['total params procesed by location statistics']
variables_scope_bytes_covered = \
json_parsed['formal params scope bytes covered']
variables_scope_bytes_from_first_def = \
json_parsed['formal params scope bytes total']
if not results.ignore_debug_entry_values:
for cov_bucket in coverage_buckets():
cov_category = "params with {} of its scope covered".format(cov_bucket)
variables_coverage_map[cov_bucket] = json_parsed[cov_category]
else:
variables_scope_bytes_entry_values = \
json_parsed['formal params entry value scope bytes covered']
variables_scope_bytes_covered = variables_scope_bytes_covered \
- variables_scope_bytes_entry_values
for cov_bucket in coverage_buckets():
cov_category = \
"params (excluding the debug entry values) " \
"with {} of its scope covered".format(cov_bucket)
variables_coverage_map[cov_bucket] = json_parsed[cov_category]
else:
# Read the JSON for both local variables and formal parameters.
variables_total = \
json_parsed['source variables']
variables_with_loc = json_parsed['variables with location']
variables_total_locstats = \
json_parsed['total variables procesed by location statistics']
variables_scope_bytes_covered = \
json_parsed['scope bytes covered']
variables_scope_bytes_from_first_def = \
json_parsed['scope bytes total']
if not results.ignore_debug_entry_values:
for cov_bucket in coverage_buckets():
cov_category = "variables with {} of its scope covered". \
format(cov_bucket)
variables_coverage_map[cov_bucket] = json_parsed[cov_category]
else:
variables_scope_bytes_entry_values = \
json_parsed['entry value scope bytes covered']
variables_scope_bytes_covered = variables_scope_bytes_covered \
- variables_scope_bytes_entry_values
for cov_bucket in coverage_buckets():
cov_category = "variables (excluding the debug entry values) " \
"with {} of its scope covered". format(cov_bucket)
variables_coverage_map[cov_bucket] = json_parsed[cov_category]
# Pretty print collected info.
locstats_output(
variables_total,
variables_total_locstats,
variables_with_loc,
variables_scope_bytes_covered,
variables_scope_bytes_from_first_def,
variables_coverage_map
)
if __name__ == '__main__':
Main()
sys.exit(0)