diff --git a/openmp/libomptarget/include/Shared/EnvironmentVar.h b/openmp/libomptarget/include/Shared/EnvironmentVar.h new file mode 100644 index 0000000000000..4cbdad695a0ee --- /dev/null +++ b/openmp/libomptarget/include/Shared/EnvironmentVar.h @@ -0,0 +1,194 @@ +//===-- Shared/EnvironmentVar.h - Environment variable handling -*- 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 OMPTARGET_SHARED_ENVIRONMENT_VAR_H +#define OMPTARGET_SHARED_ENVIRONMENT_VAR_H + +#include "Debug.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +#include +#include + +/// Utility class for parsing strings to other types. +struct StringParser { + /// Parse a string to another type. + template static bool parse(const char *Value, Ty &Result); +}; + +/// Class for reading and checking environment variables. Currently working with +/// integer, floats, std::string and bool types. +template class Envar { + Ty Data; + bool IsPresent; + bool Initialized; + +public: + /// Auxiliary function to safely create envars. This static function safely + /// creates envars using fallible constructors. See the constructors to know + /// more details about the creation parameters. + template + static llvm::Expected create(ArgsTy &&...Args) { + llvm::Error Err = llvm::Error::success(); + Envar Envar(std::forward(Args)..., Err); + if (Err) + return std::move(Err); + return std::move(Envar); + } + + /// Create an empty envar. Cannot be consulted. This constructor is merely + /// for convenience. This constructor is not fallible. + Envar() : Data(Ty()), IsPresent(false), Initialized(false) {} + + /// Create an envar with a name and an optional default. The Envar object will + /// take the value read from the environment variable, or the default if it + /// was not set or not correct. This constructor is not fallible. + Envar(llvm::StringRef Name, Ty Default = Ty()) + : Data(Default), IsPresent(false), Initialized(true) { + + if (const char *EnvStr = getenv(Name.data())) { + // Check whether the envar is defined and valid. + IsPresent = StringParser::parse(EnvStr, Data); + + if (!IsPresent) { + DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data()); + Data = Default; + } + } + } + + Envar &operator=(const Ty &V) { + Data = V; + Initialized = true; + return *this; + } + + /// Get the definitive value. + const Ty &get() const { + // Throw a runtime error in case this envar is not initialized. + if (!Initialized) + FATAL_MESSAGE0(1, "Consulting envar before initialization"); + + return Data; + } + + /// Get the definitive value. + operator Ty() const { return get(); } + + /// Indicate whether the environment variable was defined and valid. + bool isPresent() const { return IsPresent; } + +private: + /// This constructor should never fail but we provide it for convenience. This + /// way, the constructor can be used by the Envar::create() static function + /// to safely create this kind of envars. + Envar(llvm::StringRef Name, Ty Default, llvm::Error &Err) + : Envar(Name, Default) { + llvm::ErrorAsOutParameter EAO(&Err); + Err = llvm::Error::success(); + } + + /// Create an envar with a name, getter function and a setter function. The + /// Envar object will take the value read from the environment variable if + /// this value is accepted by the setter function. Otherwise, the getter + /// function will be executed to get the default value. The getter should be + /// of the form Error GetterFunctionTy(Ty &Value) and the setter should + /// be of the form Error SetterFunctionTy(Ty Value). This constructor has a + /// private visibility because is a fallible constructor. Please use the + /// Envar::create() static function to safely create this object instead. + template + Envar(llvm::StringRef Name, GetterFunctor Getter, SetterFunctor Setter, + llvm::Error &Err) + : Data(Ty()), IsPresent(false), Initialized(true) { + llvm::ErrorAsOutParameter EAO(&Err); + Err = init(Name, Getter, Setter); + } + + template + llvm::Error init(llvm::StringRef Name, GetterFunctor Getter, + SetterFunctor Setter); +}; + +/// Define some common envar types. +using IntEnvar = Envar; +using Int32Envar = Envar; +using Int64Envar = Envar; +using UInt32Envar = Envar; +using UInt64Envar = Envar; +using StringEnvar = Envar; +using BoolEnvar = Envar; + +template <> +inline bool StringParser::parse(const char *ValueStr, bool &Result) { + std::string Value(ValueStr); + + // Convert the string to lowercase. + std::transform(Value.begin(), Value.end(), Value.begin(), + [](unsigned char c) { return std::tolower(c); }); + + // May be implemented with fancier C++ features, but let's keep it simple. + if (Value == "true" || Value == "yes" || Value == "on" || Value == "1") + Result = true; + else if (Value == "false" || Value == "no" || Value == "off" || Value == "0") + Result = false; + else + return false; + + // Parsed correctly. + return true; +} + +template +inline bool StringParser::parse(const char *Value, Ty &Result) { + assert(Value && "Parsed value cannot be null"); + + std::istringstream Stream(Value); + Stream >> Result; + + return !Stream.fail(); +} + +template +template +inline llvm::Error Envar::init(llvm::StringRef Name, GetterFunctor Getter, + SetterFunctor Setter) { + // Get the default value. + Ty Default; + if (llvm::Error Err = Getter(Default)) + return Err; + + if (const char *EnvStr = getenv(Name.data())) { + IsPresent = StringParser::parse(EnvStr, Data); + if (IsPresent) { + // Check whether the envar value is actually valid. + llvm::Error Err = Setter(Data); + if (Err) { + // The setter reported an invalid value. Mark the user-defined value as + // not present and reset to the getter value (default). + IsPresent = false; + Data = Default; + DP("Setter of envar %s failed, resetting to %s\n", Name.data(), + std::to_string(Data).data()); + consumeError(std::move(Err)); + } + } else { + DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data()); + Data = Default; + } + } else { + Data = Default; + } + + return llvm::Error::success(); +} + +#endif // OMPTARGET_SHARED_ENVIRONMENT_VAR_H diff --git a/openmp/libomptarget/include/Shared/Utils.h b/openmp/libomptarget/include/Shared/Utils.h index b6bb97ce59496..fce14b54edb98 100644 --- a/openmp/libomptarget/include/Shared/Utils.h +++ b/openmp/libomptarget/include/Shared/Utils.h @@ -15,131 +15,18 @@ #define OMPTARGET_SHARED_UTILS_H #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Error.h" #include "Debug.h" -#include #include #include -#include -#include -#include -#include #include #include -#include -#include namespace llvm { namespace omp { namespace target { -/// Utility class for parsing strings to other types. -struct StringParser { - /// Parse a string to another type. - template static bool parse(const char *Value, Ty &Result); -}; - -/// Class for reading and checking environment variables. Currently working with -/// integer, floats, std::string and bool types. -template class Envar { - Ty Data; - bool IsPresent; - bool Initialized; - -public: - /// Auxiliary function to safely create envars. This static function safely - /// creates envars using fallible constructors. See the constructors to know - /// more details about the creation parameters. - template - static Expected create(ArgsTy &&...Args) { - Error Err = Error::success(); - Envar Envar(std::forward(Args)..., Err); - if (Err) - return std::move(Err); - return std::move(Envar); - } - - /// Create an empty envar. Cannot be consulted. This constructor is merely - /// for convenience. This constructor is not fallible. - Envar() : Data(Ty()), IsPresent(false), Initialized(false) {} - - /// Create an envar with a name and an optional default. The Envar object will - /// take the value read from the environment variable, or the default if it - /// was not set or not correct. This constructor is not fallible. - Envar(StringRef Name, Ty Default = Ty()) - : Data(Default), IsPresent(false), Initialized(true) { - - if (const char *EnvStr = getenv(Name.data())) { - // Check whether the envar is defined and valid. - IsPresent = StringParser::parse(EnvStr, Data); - - if (!IsPresent) { - DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data()); - Data = Default; - } - } - } - - Envar &operator=(const Ty &V) { - Data = V; - Initialized = true; - return *this; - } - - /// Get the definitive value. - const Ty &get() const { - // Throw a runtime error in case this envar is not initialized. - if (!Initialized) - FATAL_MESSAGE0(1, "Consulting envar before initialization"); - - return Data; - } - - /// Get the definitive value. - operator Ty() const { return get(); } - - /// Indicate whether the environment variable was defined and valid. - bool isPresent() const { return IsPresent; } - -private: - /// This constructor should never fail but we provide it for convenience. This - /// way, the constructor can be used by the Envar::create() static function - /// to safely create this kind of envars. - Envar(StringRef Name, Ty Default, Error &Err) : Envar(Name, Default) { - ErrorAsOutParameter EAO(&Err); - Err = Error::success(); - } - - /// Create an envar with a name, getter function and a setter function. The - /// Envar object will take the value read from the environment variable if - /// this value is accepted by the setter function. Otherwise, the getter - /// function will be executed to get the default value. The getter should be - /// of the form Error GetterFunctionTy(Ty &Value) and the setter should - /// be of the form Error SetterFunctionTy(Ty Value). This constructor has a - /// private visibility because is a fallible constructor. Please use the - /// Envar::create() static function to safely create this object instead. - template - Envar(StringRef Name, GetterFunctor Getter, SetterFunctor Setter, Error &Err) - : Data(Ty()), IsPresent(false), Initialized(true) { - ErrorAsOutParameter EAO(&Err); - Err = init(Name, Getter, Setter); - } - - template - Error init(StringRef Name, GetterFunctor Getter, SetterFunctor Setter); -}; - -/// Define some common envar types. -using IntEnvar = Envar; -using Int32Envar = Envar; -using Int64Envar = Envar; -using UInt32Envar = Envar; -using UInt64Envar = Envar; -using StringEnvar = Envar; -using BoolEnvar = Envar; - /// Utility class for thread-safe reference counting. Any class that needs /// objects' reference counting can inherit from this entity or have it as a /// class data member. @@ -170,70 +57,6 @@ struct RefCountTy { std::atomic Refs; }; -template <> -inline bool StringParser::parse(const char *ValueStr, bool &Result) { - std::string Value(ValueStr); - - // Convert the string to lowercase. - std::transform(Value.begin(), Value.end(), Value.begin(), - [](unsigned char c) { return std::tolower(c); }); - - // May be implemented with fancier C++ features, but let's keep it simple. - if (Value == "true" || Value == "yes" || Value == "on" || Value == "1") - Result = true; - else if (Value == "false" || Value == "no" || Value == "off" || Value == "0") - Result = false; - else - return false; - - // Parsed correctly. - return true; -} - -template -inline bool StringParser::parse(const char *Value, Ty &Result) { - assert(Value && "Parsed value cannot be null"); - - std::istringstream Stream(Value); - Stream >> Result; - - return !Stream.fail(); -} - -template -template -inline Error Envar::init(StringRef Name, GetterFunctor Getter, - SetterFunctor Setter) { - // Get the default value. - Ty Default; - if (Error Err = Getter(Default)) - return Err; - - if (const char *EnvStr = getenv(Name.data())) { - IsPresent = StringParser::parse(EnvStr, Data); - if (IsPresent) { - // Check whether the envar value is actually valid. - Error Err = Setter(Data); - if (Err) { - // The setter reported an invalid value. Mark the user-defined value as - // not present and reset to the getter value (default). - IsPresent = false; - Data = Default; - DP("Setter of envar %s failed, resetting to %s\n", Name.data(), - std::to_string(Data).data()); - consumeError(std::move(Err)); - } - } else { - DP("Ignoring invalid value %s for envar %s\n", EnvStr, Name.data()); - Data = Default; - } - } else { - Data = Default; - } - - return Error::success(); -} - /// Return the difference (in bytes) between \p Begin and \p End. template ptrdiff_t getPtrDiff(const void *End, const void *Begin) { diff --git a/openmp/libomptarget/plugins-nextgen/common/include/JIT.h b/openmp/libomptarget/plugins-nextgen/common/include/JIT.h index 1a5e56b2ea732..7252519a8c2eb 100644 --- a/openmp/libomptarget/plugins-nextgen/common/include/JIT.h +++ b/openmp/libomptarget/plugins-nextgen/common/include/JIT.h @@ -11,6 +11,7 @@ #ifndef OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_JIT_H #define OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_JIT_H +#include "Shared/EnvironmentVar.h" #include "Shared/Utils.h" #include "llvm/ADT/StringMap.h" @@ -106,18 +107,16 @@ struct JITEngine { std::mutex ComputeUnitMapMutex; /// Control environment variables. - target::StringEnvar ReplacementObjectFileName = - target::StringEnvar("LIBOMPTARGET_JIT_REPLACEMENT_OBJECT"); - target::StringEnvar ReplacementModuleFileName = - target::StringEnvar("LIBOMPTARGET_JIT_REPLACEMENT_MODULE"); - target::StringEnvar PreOptIRModuleFileName = - target::StringEnvar("LIBOMPTARGET_JIT_PRE_OPT_IR_MODULE"); - target::StringEnvar PostOptIRModuleFileName = - target::StringEnvar("LIBOMPTARGET_JIT_POST_OPT_IR_MODULE"); - target::UInt32Envar JITOptLevel = - target::UInt32Envar("LIBOMPTARGET_JIT_OPT_LEVEL", 3); - target::BoolEnvar JITSkipOpt = - target::BoolEnvar("LIBOMPTARGET_JIT_SKIP_OPT", false); + StringEnvar ReplacementObjectFileName = + StringEnvar("LIBOMPTARGET_JIT_REPLACEMENT_OBJECT"); + StringEnvar ReplacementModuleFileName = + StringEnvar("LIBOMPTARGET_JIT_REPLACEMENT_MODULE"); + StringEnvar PreOptIRModuleFileName = + StringEnvar("LIBOMPTARGET_JIT_PRE_OPT_IR_MODULE"); + StringEnvar PostOptIRModuleFileName = + StringEnvar("LIBOMPTARGET_JIT_POST_OPT_IR_MODULE"); + UInt32Envar JITOptLevel = UInt32Envar("LIBOMPTARGET_JIT_OPT_LEVEL", 3); + BoolEnvar JITSkipOpt = BoolEnvar("LIBOMPTARGET_JIT_SKIP_OPT", false); }; } // namespace target diff --git a/openmp/libomptarget/plugins-nextgen/common/include/MemoryManager.h b/openmp/libomptarget/plugins-nextgen/common/include/MemoryManager.h index 95491b4be6fa6..fe1989930b76e 100644 --- a/openmp/libomptarget/plugins-nextgen/common/include/MemoryManager.h +++ b/openmp/libomptarget/plugins-nextgen/common/include/MemoryManager.h @@ -324,7 +324,7 @@ class MemoryManagerTy { /// manager explicitly by setting the var to 0. If user doesn't specify /// anything, returns <0, true>. static std::pair getSizeThresholdFromEnv() { - static llvm::omp::target::UInt32Envar MemoryManagerThreshold( + static UInt32Envar MemoryManagerThreshold( "LIBOMPTARGET_MEMORY_MANAGER_THRESHOLD", 0); size_t Threshold = MemoryManagerThreshold.get(); diff --git a/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h b/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h index 6abd1b6829ab5..dd601e6b4231a 100644 --- a/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h +++ b/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h @@ -21,6 +21,7 @@ #include "Shared/Debug.h" #include "Shared/Environment.h" +#include "Shared/EnvironmentVar.h" #include "Shared/Utils.h" #include "GlobalHandler.h" diff --git a/openmp/libomptarget/src/device.cpp b/openmp/libomptarget/src/device.cpp index 2431d7c073352..da7d33b3f40c6 100644 --- a/openmp/libomptarget/src/device.cpp +++ b/openmp/libomptarget/src/device.cpp @@ -18,7 +18,7 @@ #include "private.h" #include "rtl.h" -#include "Shared/Utils.h" +#include "Shared/EnvironmentVar.h" #include #include @@ -535,11 +535,10 @@ void DeviceTy::init() { return; // Enables recording kernels if set. - llvm::omp::target::BoolEnvar OMPX_RecordKernel("LIBOMPTARGET_RECORD", false); + BoolEnvar OMPX_RecordKernel("LIBOMPTARGET_RECORD", false); if (OMPX_RecordKernel) { // Enables saving the device memory kernel output post execution if set. - llvm::omp::target::BoolEnvar OMPX_ReplaySaveOutput( - "LIBOMPTARGET_RR_SAVE_OUTPUT", false); + BoolEnvar OMPX_ReplaySaveOutput("LIBOMPTARGET_RR_SAVE_OUTPUT", false); uint64_t ReqPtrArgOffset; RTL->initialize_record_replay(RTLDeviceID, 0, nullptr, true, diff --git a/openmp/libomptarget/src/interface.cpp b/openmp/libomptarget/src/interface.cpp index 97cada94527f0..a2f713459e1d0 100644 --- a/openmp/libomptarget/src/interface.cpp +++ b/openmp/libomptarget/src/interface.cpp @@ -19,8 +19,8 @@ #include "private.h" #include "rtl.h" +#include "Shared/EnvironmentVar.h" #include "Shared/Profile.h" -#include "Shared/Utils.h" #include "Utils/ExponentialBackoff.h" diff --git a/openmp/libomptarget/src/rtl.cpp b/openmp/libomptarget/src/rtl.cpp index e80d6e09c4840..09084be12a76e 100644 --- a/openmp/libomptarget/src/rtl.cpp +++ b/openmp/libomptarget/src/rtl.cpp @@ -14,11 +14,11 @@ #include "OpenMP/OMPT/Callback.h" #include "PluginManager.h" -#include "Shared/Debug.h" #include "device.h" #include "private.h" #include "rtl.h" +#include "Shared/Debug.h" #include "Shared/Profile.h" #include "Shared/Utils.h"