1 //===- offload_impl.hpp- Implementation helpers for the Offload library ---===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 #pragma once 9 10 #include <OffloadAPI.h> 11 #include <iostream> 12 #include <memory> 13 #include <optional> 14 #include <set> 15 #include <string> 16 #include <unordered_set> 17 #include <vector> 18 19 #include "llvm/ADT/DenseSet.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/ADT/StringSet.h" 22 23 struct OffloadConfig { 24 bool TracingEnabled = false; 25 }; 26 27 OffloadConfig &offloadConfig(); 28 29 // Use the StringSet container to efficiently deduplicate repeated error 30 // strings (e.g. if the same error is hit constantly in a long running program) 31 llvm::StringSet<> &errorStrs(); 32 33 // Use an unordered_set to avoid duplicates of error structs themselves. 34 // We cannot store the structs directly as returned pointers to them must always 35 // be valid, and a rehash of the set may invalidate them. This requires 36 // custom hash and equal_to function objects. 37 using ErrPtrT = std::unique_ptr<ol_error_struct_t>; 38 struct ErrPtrEqual { 39 bool operator()(const ErrPtrT &lhs, const ErrPtrT &rhs) const { 40 if (!lhs && !rhs) { 41 return true; 42 } 43 if (!lhs || !rhs) { 44 return false; 45 } 46 47 bool StrsEqual = false; 48 if (lhs->Details == NULL && rhs->Details == NULL) { 49 StrsEqual = true; 50 } else if (lhs->Details != NULL && rhs->Details != NULL) { 51 StrsEqual = (std::strcmp(lhs->Details, rhs->Details) == 0); 52 } 53 return (lhs->Code == rhs->Code) && StrsEqual; 54 } 55 }; 56 struct ErrPtrHash { 57 size_t operator()(const ErrPtrT &e) const { 58 if (!e) { 59 // We shouldn't store empty errors (i.e. success), but just in case 60 return 0lu; 61 } else { 62 return std::hash<int>{}(e->Code); 63 } 64 } 65 }; 66 using ErrSetT = std::unordered_set<ErrPtrT, ErrPtrHash, ErrPtrEqual>; 67 ErrSetT &errors(); 68 69 struct ol_impl_result_t { 70 ol_impl_result_t(std::nullptr_t) : Result(OL_SUCCESS) {} 71 ol_impl_result_t(ol_errc_t Code) { 72 if (Code == OL_ERRC_SUCCESS) { 73 Result = nullptr; 74 } else { 75 auto Err = std::unique_ptr<ol_error_struct_t>( 76 new ol_error_struct_t{Code, nullptr}); 77 Result = errors().emplace(std::move(Err)).first->get(); 78 } 79 } 80 81 ol_impl_result_t(ol_errc_t Code, llvm::StringRef Details) { 82 assert(Code != OL_ERRC_SUCCESS); 83 Result = nullptr; 84 auto DetailsStr = errorStrs().insert(Details).first->getKeyData(); 85 auto Err = std::unique_ptr<ol_error_struct_t>( 86 new ol_error_struct_t{Code, DetailsStr}); 87 Result = errors().emplace(std::move(Err)).first->get(); 88 } 89 90 operator ol_result_t() { return Result; } 91 92 private: 93 ol_result_t Result; 94 }; 95