diff --git a/src/runtime/hexagon/sim/hexagon_device_sim.cc b/src/runtime/hexagon/sim/hexagon_device_sim.cc index 1d3f0fd1006f..14ab4c30e2f2 100644 --- a/src/runtime/hexagon/sim/hexagon_device_sim.cc +++ b/src/runtime/hexagon/sim/hexagon_device_sim.cc @@ -17,12 +17,10 @@ * under the License. */ -#include -#include -#include -#include -#include +#include +#include #include +#include #include #include @@ -31,6 +29,7 @@ #include #include #include +#include #include #include "../hexagon_module.h" @@ -84,6 +83,18 @@ std::unique_ptr make_unique(size_t size) { return std::unique_ptr(new U[size]()); } +// An "Optional" class, originally a replacement for llvm::Optional, then an +// extension of dmlc::optional to make it compatible with C++17's std::optional. +template +struct Optional : public dmlc::optional { + using dmlc::optional::optional; + using dmlc::optional::operator=; + Optional(const T& val) : dmlc::optional(val) {} // NOLINT(*) + + T* operator->() { return &this->operator*(); } + const T* operator->() const { return &this->operator*(); } +}; + // Converter class to translate vector to char**. This relieves the // user from memory reallocation and copying. struct non_const_str { @@ -117,7 +128,7 @@ struct non_const_str { std::vector> storage_; }; -using MaybeString = llvm::Optional; +using MaybeString = Optional; MaybeString front(const string_list& deq) { return !deq.empty() ? MaybeString(deq.front()) : MaybeString(); @@ -130,47 +141,47 @@ MaybeString pop_front(string_list& deq) { // NOLINT(*) return MaybeString(f); } -llvm::Optional to_int(const MaybeString& str) { - auto none = llvm::Optional(); - if (str.hasValue()) { +Optional to_int(const MaybeString& str) { + auto none = Optional(); + if (str.has_value()) { try { size_t pos; int64_t val = std::stoll(*str, &pos, 0); - return pos == str->size() ? llvm::Optional(val) : none; + return pos == str->size() ? Optional(val) : none; } catch (std::invalid_argument) { } } return none; } -llvm::Optional to_uint(const MaybeString& str) { - auto none = llvm::Optional(); - if (str.hasValue()) { +Optional to_uint(const MaybeString& str) { + auto none = Optional(); + if (str.has_value()) { try { size_t pos; uint64_t val = std::stoull(*str, &pos, 0); - return pos == str->size() ? llvm::Optional(val) : none; + return pos == str->size() ? Optional(val) : none; } catch (std::invalid_argument) { } } return none; } -llvm::Optional to_float(const MaybeString& str) { - auto none = llvm::Optional(); - if (str.hasValue()) { +Optional to_float(const MaybeString& str) { + auto none = Optional(); + if (str.has_value()) { try { size_t pos; float val = std::stof(*str, &pos); - return pos == str->size() ? llvm::Optional(val) : none; + return pos == str->size() ? Optional(val) : none; } catch (std::invalid_argument) { } } return none; } -llvm::Optional to_bool(const MaybeString& str) { - auto none = llvm::Optional(); +Optional to_bool(const MaybeString& str) { + auto none = Optional(); if (auto num = to_int(str)) { if (*num == 0) return false; if (*num == 1) return true; @@ -184,9 +195,9 @@ llvm::Optional to_bool(const MaybeString& str) { } template -using MaybeRange = llvm::Optional>; +using MaybeRange = Optional>; -template Parse(const MaybeString&)> +template Parse(const MaybeString&)> MaybeRange to_range(const MaybeString& str) { auto none = MaybeRange(); if (str && !str->empty()) { @@ -202,6 +213,72 @@ MaybeRange to_range(const MaybeString& str) { return none; } +// Replacement for llvm::StringSwitch. +template +class StringSwitch { + public: + explicit StringSwitch(const std::string& key) : key(key) {} + operator T() const { + auto f = map.find(key); + if (f != map.end()) { + return f->second; + } + ICHECK(static_cast(def_val)) << "default value not set"; + return *def_val; + } + StringSwitch& Case(const std::string& key, T val) { + map.insert(std::make_pair(key, val)); + return *this; + } + StringSwitch& Default(T val) { + ICHECK(!static_cast(def_val)) << "default value already set"; + def_val = val; + return *this; + } + + private: + const std::string key; + std::map map; + Optional def_val; +}; + +// Replacement for llvm::sys::fs::access with AccessMode = Execute. +bool FileExists(const std::string& file) { return access(file.c_str(), X_OK) == 0; } + +// Replacement for llvm::sys::Process::FindInEnvPath. +MaybeString FindInEnvPath(const std::string& env_var, const std::string& file) { + auto none = MaybeString(); + if (file.empty() || file[0] == '/') { + return none; + } + + const char* e = getenv(env_var.c_str()); + std::string env_val = e != nullptr ? std::string(e) : std::string(); + + std::vector paths; + // Split the environment variable into individual paths. + size_t first = 0, env_size = env_val.size(); + for (size_t last = 0; last != env_size; ++last) { + if (env_val[last] == ':') { + if (last > first) { + paths.emplace_back(env_val, first, last - first); + } + first = last + 1; + } + } + if (first < env_size) { + paths.emplace_back(env_val, first, env_size - first); + } + + // Search for the file. + for (const std::string& dir : paths) { + std::string full = dir + '/' + file; + if (FileExists(full)) { + return full; + } + } + return none; +} } // namespace detail class HexagonSimulator final : public tvm::runtime::hexagon::Device { @@ -304,17 +381,17 @@ class HexagonSimulator final : public tvm::runtime::hexagon::Device { bool HandleV2PTranslation(string_list& rest); // NOLINT(*) bool HandleVerbose(string_list& rest); // NOLINT(*) - using MaybeUInt64 = llvm::Optional; + using MaybeUInt64 = detail::Optional; using MaybeUIntRange = std::pair; bool should_parse_next(const string_list& rest); - llvm::Optional to_interval(const detail::MaybeString& str); - llvm::Optional to_timingmode(const detail::MaybeString& str); - llvm::Optional to_verbosemode(const detail::MaybeString& str); - llvm::Optional to_nullptr(const detail::MaybeString& str); + detail::Optional to_interval(const detail::MaybeString& str); + detail::Optional to_timingmode(const detail::MaybeString& str); + detail::Optional to_verbosemode(const detail::MaybeString& str); + detail::Optional to_nullptr(const detail::MaybeString& str); MaybeUIntRange ahb_, axi2_; - llvm::Optional debug_port_; + detail::Optional debug_port_; detail::non_const_str sim_dev_args_; using OptionHandler = bool (HexagonSimulator::*)(string_list&); @@ -556,13 +633,13 @@ HexagonSimulator::HexagonSimulator(bool enable_queuing) { LOG(INFO) << "HexagonSimulator: Core version: " << arch_; // Locate the sim_dev binary in PATH, or in the current working directory. - llvm::StringRef sim_dev = "sim_dev"; - detail::MaybeString path_sim_dev = llvm::sys::Process::FindInEnvPath("PATH", sim_dev); + std::string sim_dev = "sim_dev"; + detail::MaybeString path_sim_dev = detail::FindInEnvPath("PATH", sim_dev); if (!path_sim_dev) { - if (!llvm::sys::fs::exists(sim_dev)) { + if (!detail::FileExists(sim_dev)) { LOG(FATAL) << "Cannot find sim_dev in PATH."; } - path_sim_dev = sim_dev.str(); + path_sim_dev = sim_dev; } CHECKED_CALL(ConfigureExecutableBinary, path_sim_dev->c_str()); @@ -767,19 +844,19 @@ bool HexagonSimulator::Configure(string_list& opts) { } // Check AHB. - if (ahb_.first.hasValue() && ahb_.second.hasValue()) { + if (ahb_.first.has_value() && ahb_.second.has_value()) { CHECKED_CALL(ConfigureAHB, *ahb_.first, *ahb_.second); } else { - ICHECK(!ahb_.first.hasValue() && !ahb_.second.hasValue()) + ICHECK(!ahb_.first.has_value() && !ahb_.second.has_value()) << "HexagonSimulator: please specify both low and high addresses " "for AHB"; } // Check AXI2. - if (axi2_.first.hasValue() && axi2_.second.hasValue()) { + if (axi2_.first.has_value() && axi2_.second.has_value()) { CHECKED_CALL(ConfigureAXI2, *axi2_.first, *axi2_.second); } else { - ICHECK(!axi2_.first.hasValue() && !axi2_.second.hasValue()) + ICHECK(!axi2_.first.has_value() && !axi2_.second.has_value()) << "HexagonSimulator: please specify both low and high addresses " "for AXI2"; } @@ -1260,8 +1337,8 @@ bool HexagonSimulator::should_parse_next(const string_list& rest) { return false; } -llvm::Optional HexagonSimulator::to_interval(const detail::MaybeString& str) { - auto none = llvm::Optional(); +detail::Optional HexagonSimulator::to_interval(const detail::MaybeString& str) { + auto none = detail::Optional(); if (!str) return none; if (auto val = detail::to_int(*str)) { @@ -1275,7 +1352,7 @@ llvm::Optional HexagonSimulator::to_interval(const detail::Mayb } } - return llvm::StringSwitch>(*str) + return detail::StringSwitch>(*str) .Case("MILLISEC", HEX_MILLISEC) .Case("MICROSEC", HEX_MICROSEC) .Case("NANOSEC", HEX_NANOSEC) @@ -1284,8 +1361,9 @@ llvm::Optional HexagonSimulator::to_interval(const detail::Mayb .Default(none); } -llvm::Optional HexagonSimulator::to_timingmode(const detail::MaybeString& str) { - auto none = llvm::Optional(); +detail::Optional HexagonSimulator::to_timingmode( + const detail::MaybeString& str) { + auto none = detail::Optional(); if (!str) return none; if (auto val = detail::to_int(*str)) { @@ -1298,7 +1376,7 @@ llvm::Optional HexagonSimulator::to_timingmode(const detail:: } } - return llvm::StringSwitch>(*str) + return detail::StringSwitch>(*str) .Case("NOTIMING", HEX_NOTIMING) .Case("TIMING_NODBC", HEX_TIMING_NODBC) .Case("TIMING", HEX_TIMING) @@ -1306,9 +1384,9 @@ llvm::Optional HexagonSimulator::to_timingmode(const detail:: .Default(none); } -llvm::Optional HexagonSimulator::to_verbosemode( +detail::Optional HexagonSimulator::to_verbosemode( const detail::MaybeString& str) { - auto none = llvm::Optional(); + auto none = detail::Optional(); if (!str) return none; if (auto val = detail::to_int(*str)) { @@ -1322,7 +1400,7 @@ llvm::Optional HexagonSimulator::to_verbosemode( } } - return llvm::StringSwitch>(*str) + return detail::StringSwitch>(*str) .Case("SILENT", HEX_SILENT) .Case("QUIET", HEX_QUIET) .Case("NORMAL", HEX_NORMAL) @@ -1331,8 +1409,8 @@ llvm::Optional HexagonSimulator::to_verbosemode( .Default(none); } -llvm::Optional HexagonSimulator::to_nullptr(const detail::MaybeString& str) { - auto none = llvm::Optional(); +detail::Optional HexagonSimulator::to_nullptr(const detail::MaybeString& str) { + auto none = detail::Optional(); if (!str) return none; if (auto val = detail::to_int(*str)) { @@ -1345,7 +1423,7 @@ llvm::Optional HexagonSimulator::to_nullptr(const detail::MaybeS } } - return llvm::StringSwitch>(*str) + return detail::StringSwitch>(*str) .Case("IGNORE", HEX_NULLPTR_IGNORE) .Case("WARN", HEX_NULLPTR_WARN) .Case("FATAL", HEX_NULLPTR_FATAL)