[Parallel_libs-commits] [parallel-libs] r277210 - [StreamExecutor] Add error handling library

Jason Henline via Parallel_libs-commits parallel_libs-commits at lists.llvm.org
Fri Jul 29 13:45:52 PDT 2016


Author: jhen
Date: Fri Jul 29 15:45:52 2016
New Revision: 277210

URL: http://llvm.org/viewvc/llvm-project?rev=277210&view=rev
Log:
[StreamExecutor] Add error handling library

Summary:
Error handling in StreamExecutor is based on llvm::Error and
llvm::Expected. This CL sets up the StreamExecutor wrapper classes in
the streamexecutor namespace.

All the other StreamExecutor code makes use of this error handling code,
so this is the first CL for checking in StreamExecutor.

Reviewers: jlebar, tra

Subscribers: parallel_libs-commits

Differential Revision: https://reviews.llvm.org/D22687

Added:
    parallel-libs/trunk/streamexecutor/CMakeLists.txt
    parallel-libs/trunk/streamexecutor/include/
    parallel-libs/trunk/streamexecutor/include/streamexecutor/
    parallel-libs/trunk/streamexecutor/include/streamexecutor/Utils/
    parallel-libs/trunk/streamexecutor/include/streamexecutor/Utils/Error.h
    parallel-libs/trunk/streamexecutor/lib/
    parallel-libs/trunk/streamexecutor/lib/CMakeLists.txt
    parallel-libs/trunk/streamexecutor/lib/Utils/
    parallel-libs/trunk/streamexecutor/lib/Utils/Error.cpp
Modified:
    parallel-libs/trunk/streamexecutor/README.txt

Added: parallel-libs/trunk/streamexecutor/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/parallel-libs/trunk/streamexecutor/CMakeLists.txt?rev=277210&view=auto
==============================================================================
--- parallel-libs/trunk/streamexecutor/CMakeLists.txt (added)
+++ parallel-libs/trunk/streamexecutor/CMakeLists.txt Fri Jul 29 15:45:52 2016
@@ -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)

Modified: parallel-libs/trunk/streamexecutor/README.txt
URL: http://llvm.org/viewvc/llvm-project/parallel-libs/trunk/streamexecutor/README.txt?rev=277210&r1=277209&r2=277210&view=diff
==============================================================================
--- parallel-libs/trunk/streamexecutor/README.txt (original)
+++ parallel-libs/trunk/streamexecutor/README.txt Fri Jul 29 15:45:52 2016
@@ -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.

Added: parallel-libs/trunk/streamexecutor/include/streamexecutor/Utils/Error.h
URL: http://llvm.org/viewvc/llvm-project/parallel-libs/trunk/streamexecutor/include/streamexecutor/Utils/Error.h?rev=277210&view=auto
==============================================================================
--- parallel-libs/trunk/streamexecutor/include/streamexecutor/Utils/Error.h (added)
+++ parallel-libs/trunk/streamexecutor/include/streamexecutor/Utils/Error.h Fri Jul 29 15:45:52 2016
@@ -0,0 +1,184 @@
+//===-- 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
+/// Error types used in the public API and internally in StreamExecutor.
+///
+/// StreamExecutor's error handling is based on the types streamexecutor::Error
+/// and streamexecutor::Expected<T>.
+///
+///
+/// \section error The Error Class
+///
+/// The Error class either represents success or contains an error message
+/// describing the cause of the error. Error instances are created by calling
+/// Error::success for successes or make_error for errors.
+///
+/// \code{.cpp}
+/// Error achieveWorldPeace() {
+///   if (WorldPeaceAlreadyAchieved) {
+///     return Error::success();
+///   } else {
+///     return make_error("Can't someone else do it?");
+///   }
+/// }
+/// \endcode
+///
+/// Error instances are implicitly convertable to bool. Error values convert to
+/// true and successes convert to false. Error instances must have their boolean
+/// values checked or they must be moved before they go out of scope, otherwise
+/// their destruction will cause the program to abort with a warning about an
+/// unchecked Error.
+///
+/// If the Error represents success, then checking the boolean value is all that
+/// is required, but if the Error represents a real error, the Error value must
+/// be consumed. The function consumeAndGetMessage is the way to extract the
+/// error message from an Error and consume the Error at the same time, so
+/// typical error handling will first check whether there was an error and then
+/// extract the error message if so. Here is an example:
+///
+/// \code{.cpp}
+/// if (Error E = achieveWorldPeace()) {
+///   printf("An error occurred: %s\n", consumeAndGetMessage(E).c_str());
+///   exit(EXIT_FAILURE):
+/// }
+/// \endcode
+///
+/// It is also common to simply pass an error along up the call stack if it
+/// cannot be handled in the current function.
+///
+/// \code{.cpp}
+/// Error doTask() {
+///   if (Error E = achieveWorldPeace()) {
+///     return E;
+///   }
+///   ...
+/// }
+/// \endcode
+///
+/// There is also a function consumeError that consumes an error value without
+/// fetching the error message. This is useful when we want to ignore an error.
+///
+///
+/// \section expected The Expected Class
+///
+/// The Expected<T> class either represents a value of type T or an Error.
+/// Expected<T> has one constructor that takes a T value and another constructor
+/// that takes an Error rvalue reference, so Expected instances can be
+/// constructed either from values or from errors:
+///
+/// \code{.cpp}
+/// Expected<int> getMyFavoriteInt() {
+///   int MyFavorite = 42;
+///   if (IsThereAFavorite) {
+///     return MyFavorite;
+///   } else {
+///     return make_error("I don't have a favorite");
+///   }
+/// }
+/// \endcode
+///
+/// Expected<T> instances are implicitly convertible to bool and are true if
+/// they contain a value and false if they contain an error. Note that this is
+/// the opposite convention of the Error type conversion to bool, where true
+/// meant error and false meant success.
+///
+/// If the Expected<T> instance is not an error, the stored value can be
+/// obtained by using operator*. If access to members of the value are desired
+/// instead of the value itself, operator-> can be used as well.
+///
+/// Expected<T> instances must have their boolean value checked or they must be
+/// moved before they go out of scope, otherwise they will cause the program to
+/// abort with a warning about an unchecked error. If the Expected<T> instance
+/// contains a value, then checking the boolean value is all that is required,
+/// but if it contains an Error object, that Error object must be handled by
+/// calling Expected<T>::takeError() to get the underlying error.
+///
+/// Here is an example of the use of an Expected<T> value returned from a
+/// function:
+///
+/// \code{.cpp}
+/// Expected<int> ExpectedInt = getMyFavoriteInt();
+/// if (ExpectedInt) {
+///   printf("My favorite integer is %d\n", *ExpectedInt);
+/// } else {
+///   printf("An error occurred: %s\n",
+///     consumeAndGetMessage(ExpectedInt.takeError()));
+///   exit(EXIT_FAILURE);
+/// }
+/// \endcode
+///
+/// The following snippet shows some examples of how Errors and Expected values
+/// can be passed up the stack if they should not be handled in the current
+/// function.
+///
+/// \code{.cpp}
+/// Expected<double> doTask3() {
+///   Error WorldPeaceError = achieveWorldPeace();
+///   if (!WorldPeaceError) {
+///     return WorldPeaceError;
+///   }
+///
+///   Expected<martian> ExpectedMartian = getMyFavoriteMartian();
+///   if (!ExpectedMartian) {
+///     // Must extract the error because martian cannot be converted to double.
+///     return ExpectedMartian.takeError():
+///   }
+///
+///   // It's fine to return Expected<int> for Expected<double> because int can
+///   // be converted to double.
+///   return getMyFavoriteInt();
+/// }
+/// \endcode
+///
+///
+/// \section llvm Relation to llvm::Error and llvm::Expected
+///
+/// The streamexecutor::Error and streamexecutor::Expected classes are actually
+/// just their LLVM counterparts redeclared in the streamexectuor namespace, but
+/// they should be treated as separate types, even so.
+///
+/// StreamExecutor does not support any underlying llvm::ErrorInfo class except
+/// the one it defines internally for itself, so a streamexecutor::Error can be
+/// thought of as a restricted llvm::Error that is guaranteed to hold a specific
+/// error type.
+///
+/// Although code may compile if llvm functions used to handle these
+/// StreamExecutor error types, it is likely that code will lead to runtime
+/// errors, so it is strongly recommended that only the functions from the
+/// streamexecutor namespace are used on these StreamExecutor error types.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef STREAMEXECUTOR_UTILS_ERROR_H
+#define STREAMEXECUTOR_UTILS_ERROR_H
+
+#include <memory>
+#include <string>
+
+#include "llvm/Support/Error.h"
+
+namespace streamexecutor {
+
+using llvm::consumeError;
+using llvm::Error;
+using llvm::Expected;
+using llvm::StringRef;
+
+// Makes an Error object from an error message.
+Error make_error(StringRef Message);
+
+// Consumes the input error and returns its error message.
+//
+// Assumes the input was created by the make_error function above.
+std::string consumeAndGetMessage(Error &&E);
+
+} // namespace streamexecutor
+
+#endif // STREAMEXECUTOR_UTILS_ERROR_H

Added: parallel-libs/trunk/streamexecutor/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/parallel-libs/trunk/streamexecutor/lib/CMakeLists.txt?rev=277210&view=auto
==============================================================================
--- parallel-libs/trunk/streamexecutor/lib/CMakeLists.txt (added)
+++ parallel-libs/trunk/streamexecutor/lib/CMakeLists.txt Fri Jul 29 15:45:52 2016
@@ -0,0 +1,4 @@
+add_library(
+    utils
+    OBJECT
+    Utils/Error.cpp)

Added: parallel-libs/trunk/streamexecutor/lib/Utils/Error.cpp
URL: http://llvm.org/viewvc/llvm-project/parallel-libs/trunk/streamexecutor/lib/Utils/Error.cpp?rev=277210&view=auto
==============================================================================
--- parallel-libs/trunk/streamexecutor/lib/Utils/Error.cpp (added)
+++ parallel-libs/trunk/streamexecutor/lib/Utils/Error.cpp Fri Jul 29 15:45:52 2016
@@ -0,0 +1,63 @@
+//===-- 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"
+
+#include "llvm/ADT/StringRef.h"
+
+namespace {
+
+// An error with a string message describing the cause.
+class StreamExecutorError : public llvm::ErrorInfo<StreamExecutorError> {
+public:
+  StreamExecutorError(llvm::StringRef Message) : Message(Message.str()) {}
+
+  void log(llvm::raw_ostream &OS) const override { OS << Message; }
+
+  std::error_code convertToErrorCode() const override {
+    llvm_unreachable(
+        "StreamExecutorError does not support convertion to std::error_code");
+  }
+
+  std::string getErrorMessage() const { return Message; }
+
+  static char ID;
+
+private:
+  std::string Message;
+};
+
+char StreamExecutorError::ID = 0;
+
+} // namespace
+
+namespace streamexecutor {
+
+Error make_error(StringRef Message) {
+  return llvm::make_error<StreamExecutorError>(Message);
+}
+
+std::string consumeAndGetMessage(Error &&E) {
+  if (!E) {
+    return "success";
+  }
+  std::string Message;
+  llvm::handleAllErrors(std::move(E),
+                        [&Message](const StreamExecutorError &SEE) {
+                          Message = SEE.getErrorMessage();
+                        });
+  return Message;
+}
+
+} // namespace streamexecutor




More information about the Parallel_libs-commits mailing list