101 lines · plain
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-exception6//7//===----------------------------------------------------------------------===//8#pragma once9 10#include "PluginInterface.h"11#include <OffloadAPI.h>12#include <iostream>13#include <memory>14#include <optional>15#include <set>16#include <string>17#include <unordered_set>18#include <vector>19 20#include "llvm/ADT/DenseSet.h"21#include "llvm/ADT/StringRef.h"22#include "llvm/ADT/StringSet.h"23#include "llvm/Support/Error.h"24 25namespace llvm {26namespace offload {27bool isTracingEnabled();28bool isValidationEnabled();29bool isOffloadInitialized();30} // namespace offload31} // namespace llvm32 33// Use the StringSet container to efficiently deduplicate repeated error34// strings (e.g. if the same error is hit constantly in a long running program)35llvm::StringSet<> &errorStrs();36 37// Use an unordered_set to avoid duplicates of error structs themselves.38// We cannot store the structs directly as returned pointers to them must always39// be valid, and a rehash of the set may invalidate them. This requires40// custom hash and equal_to function objects.41using ErrPtrT = std::unique_ptr<ol_error_struct_t>;42struct ErrPtrEqual {43 bool operator()(const ErrPtrT &lhs, const ErrPtrT &rhs) const {44 if (!lhs && !rhs) {45 return true;46 }47 if (!lhs || !rhs) {48 return false;49 }50 51 bool StrsEqual = false;52 if (lhs->Details == NULL && rhs->Details == NULL) {53 StrsEqual = true;54 } else if (lhs->Details != NULL && rhs->Details != NULL) {55 StrsEqual = (std::strcmp(lhs->Details, rhs->Details) == 0);56 }57 return (lhs->Code == rhs->Code) && StrsEqual;58 }59};60struct ErrPtrHash {61 size_t operator()(const ErrPtrT &e) const {62 if (!e) {63 // We shouldn't store empty errors (i.e. success), but just in case64 return 0lu;65 } else {66 return std::hash<int>{}(e->Code);67 }68 }69};70using ErrSetT = std::unordered_set<ErrPtrT, ErrPtrHash, ErrPtrEqual>;71ErrSetT &errors();72 73namespace {74ol_errc_t GetErrorCode(std::error_code Code) {75 if (Code.category() ==76 error::make_error_code(error::ErrorCode::SUCCESS).category())77 return static_cast<ol_errc_t>(Code.value());78 79 return OL_ERRC_UNKNOWN;80}81} // namespace82 83inline ol_result_t llvmErrorToOffloadError(llvm::Error &&Err) {84 if (!Err) {85 // No error86 return nullptr;87 }88 89 ol_errc_t ErrCode;90 llvm::StringRef Details;91 92 llvm::handleAllErrors(std::move(Err), [&](llvm::StringError &Err) {93 ErrCode = GetErrorCode(Err.convertToErrorCode());94 Details = errorStrs().insert(Err.getMessage()).first->getKeyData();95 });96 97 auto NewErr = std::unique_ptr<ol_error_struct_t>(98 new ol_error_struct_t{ErrCode, Details.data()});99 return errors().emplace(std::move(NewErr)).first->get();100}101