Index: streamexecutor/CMakeLists.txt =================================================================== --- /dev/null +++ streamexecutor/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 3.1) + +option(STREAM_EXECUTOR_UNIT_TESTS "enable unit tests" ON) + +# First find includes relative to the streamexecutor top-level source path. +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include) + +# If we are not building as part of LLVM, build StreamExecutor as a standalone +# project using LLVM as an external library: +string( + COMPARE + EQUAL + "${CMAKE_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}" + STREAM_EXECUTOR_STANDALONE) + +if(STREAM_EXECUTOR_STANDALONE) + project(StreamExecutor) + + find_package(LLVM REQUIRED CONFIG) + message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") + message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + + include_directories(${LLVM_INCLUDE_DIRS}) + add_definitions(${LLVM_DEFINITIONS}) + + # Find the libraries that correspond to the LLVM components + # that we wish to use + llvm_map_components_to_libnames(llvm_libs support) + + if(STREAM_EXECUTOR_UNIT_TESTS) + enable_testing() + find_package(GTest REQUIRED) + include_directories(${GTEST_INCLUDE_DIRS}) + endif() +else(NOT STREAM_EXECUTOR_STANDALONE) + if(STREAM_EXECUTOR_UNIT_TESTS) + include_directories( + "${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include") + endif() +endif(STREAM_EXECUTOR_STANDALONE) + +# Insist on C++ 11 features. +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Add warning flags. +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter") + +add_subdirectory(lib) Index: streamexecutor/README.txt =================================================================== --- streamexecutor/README.txt +++ streamexecutor/README.txt @@ -1 +1,11 @@ -This directory will contain the StreamExecutor library. +StreamExecutor +============== + +StreamExecutor is a wrapper around CUDA and OpenCL (host-side) programming +models (runtimes). This abstraction cleanly permits host code to target either +CUDA or OpenCL devices with identically-functioning data parallel kernels. It +manages the execution of concurrent work targeting the accelerator, similar to a +host-side Executor. + +This version of StreamExecutor can be built either as a sub-project of the LLVM +project or as a standalone project depending on LLVM as an external package. Index: streamexecutor/include/streamexecutor/Utils/Error.h =================================================================== --- /dev/null +++ streamexecutor/include/streamexecutor/Utils/Error.h @@ -0,0 +1,112 @@ +//===-- Error.h - Error handling --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Types for returning recoverable errors. +/// +//===----------------------------------------------------------------------===// + +#ifndef STREAMEXECUTOR_UTILS_ERROR_H +#define STREAMEXECUTOR_UTILS_ERROR_H + +#include +#include + +#include + +namespace streamexecutor { + +using llvm::Error; +using llvm::Expected; +using llvm::consumeError; + +// An error with a string message describing the cause. +class ErrorInfo : public llvm::ErrorInfo { +public: + ErrorInfo(std::string Message) : Message(Message) {} + void log(llvm::raw_ostream &OS) const override { OS << Message; } + std::error_code convertToErrorCode() const override { + llvm_unreachable( + "ErrorInfo does not support convertion to std::error_code"); + } + std::string GetMessage() const { return Message; } + static char ID; + +private: + std::string Message; +}; + +// Makes an error object based on a streamexecutor::ErrorInfo. +// +// Accepted arguments are arguments to ErrorInfo constructors. +template Error make_error(ArgTs &&... Args) { + return llvm::make_error(std::forward(Args)...); +} + +// Gets the message which is returned by consumeMessage if there is no error. +static inline std::string getSuccessMessage() { return "success"; } + +// Consumes the input error and returns its error message. +// +// If there is no error, the returned message matches the return value of +// getSuccessMessage. +static inline std::string consumeMessage(Error &&E) { + if (!E) { + return getSuccessMessage(); + } + std::string Message; + llvm::handleAllErrors(std::move(E), [&Message](const ErrorInfo &Info) { + Message = Info.GetMessage(); + }); + return Message; +} + +// Consumes the input expected value and returns its error message. +// +// If there is no error, the returned message matches the return value of +// getSuccessMessage. +template std::string consumeMessage(Expected &&Exp) { + if (Exp) { + return getSuccessMessage(); + } + return consumeMessage(Exp.takeError()); +} + +// Returns the error output from the expression if the output is an error. +// +// This is useful when the return type of the function is Error because it can +// take advantage of copy elision. +#define SE_ERROR_RETURN_IF_ERROR(x) \ + do { \ + if (Error E = (x)) { \ + return E; \ + } \ + } while (false) + +// Returns the moved error output from the expression if the output is an error. +// +// This is useful when the return type of the function is Expected. +#define SE_ERROR_RETURN_MOVED_IF_ERROR(x) \ + do { \ + if (Error E = (x)) { \ + return std::move(E); \ + } \ + } while (false) + +// If Expected is good, assign it to Symbol. Otherwise return the error. +#define SE_ASSIGN_EXPECTED_OR_RETURN_ERROR(Symbol, Expected) \ + if (auto E__ = Expected) { \ + Symbol = *E__; \ + } else { \ + return E__.takeError(); \ + } + +} // namespace streamexecutor + +#endif // STREAMEXECUTOR_UTILS_ERROR_H Index: streamexecutor/include/streamexecutor/Utils/Macros.h =================================================================== --- /dev/null +++ streamexecutor/include/streamexecutor/Utils/Macros.h @@ -0,0 +1,55 @@ +//===-- Macros.h - DSO loader selector --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Defines various helper macros which are useful throughout the StreamExecutor +/// project. +/// +//===----------------------------------------------------------------------===// + +#ifndef STREAMEXECUTOR_UTILS_MACROS_H +#define STREAMEXECUTOR_UTILS_MACROS_H + +/// Returns the number of elements in an array. +/// +/// The expression SE_ARRAYSIZE(a) is a compile-time constant of type size_t. +#define SE_ARRAYSIZE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast(!(sizeof(a) % sizeof(*(a))))) + +/// Marks a function return value so that the compiler emits a warning if that +/// return value is unused. +/// +/// If a type is marked with this attribute, all functions that return that type +/// are implicitly marked with this attribute. +#if defined(__clang__) && !defined(SWIG) +#if __has_feature(cxx_attributes) +#define SE_WARN_UNUSED_RESULT [[clang::warn_unused_result]] +#else +#define SE_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#endif +#else +#define SE_WARN_UNUSED_RESULT +#endif + +/// Checks that the input boolean expression is true +/// +/// The check is performed using assert, but the boolean expression is +/// evaluated even if the assert check is disabled by NDEBUG. +/// +/// The cast to void is to prevent unused variable warnings when NDEBUG causes +/// assert calls to be removed. +#define SE_CHECK(bool_expression) \ + do { \ + bool ok = (bool_expression); \ + assert(ok); \ + static_cast(ok); \ + } while (false) + +#endif // STREAMEXECUTOR_UTILS_MACROS_H Index: streamexecutor/include/streamexecutor/Utils/ThreadAnnotations.h =================================================================== --- /dev/null +++ streamexecutor/include/streamexecutor/Utils/ThreadAnnotations.h @@ -0,0 +1,30 @@ +//===-- ThreadAnnotations.h - Thread annotations ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Declares macros for thread annotations. +/// +//===----------------------------------------------------------------------===// + +#ifndef STREAMEXECUTOR_UTILS_THREADANNOTATIONS_H +#define STREAMEXECUTOR_UTILS_THREADANNOTATIONS_H + +#if defined(__clang__) && (!defined(SWIG)) +#define SE_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define SE_THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +/// Document if a shared variable/field needs to be protected by a mutex. +/// +/// SE_GUARDED_BY allows the user to specify a particular mutex that should be +/// held when accessing the annotated variable. +#define SE_GUARDED_BY(x) SE_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#endif // STREAMEXECUTOR_UTILS_THREADANNOTATIONS_H Index: streamexecutor/lib/CMakeLists.txt =================================================================== --- /dev/null +++ streamexecutor/lib/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library( + utils + OBJECT + Utils/Error.cpp) Index: streamexecutor/lib/Utils/Error.cpp =================================================================== --- /dev/null +++ streamexecutor/lib/Utils/Error.cpp @@ -0,0 +1,17 @@ +//===-- Error.cpp - Error handling ----------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Types for returning recoverable errors. +/// +//===----------------------------------------------------------------------===// + +#include "streamexecutor/Utils/Error.h" + +char streamexecutor::ErrorInfo::ID = 0;