diff options
Diffstat (limited to 'llvm/lib/Frontend/Offloading')
-rw-r--r-- | llvm/lib/Frontend/Offloading/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Frontend/Offloading/PropertySet.cpp | 102 |
2 files changed, 103 insertions, 0 deletions
diff --git a/llvm/lib/Frontend/Offloading/CMakeLists.txt b/llvm/lib/Frontend/Offloading/CMakeLists.txt index 8e1ede9..9747dbd 100644 --- a/llvm/lib/Frontend/Offloading/CMakeLists.txt +++ b/llvm/lib/Frontend/Offloading/CMakeLists.txt @@ -1,6 +1,7 @@ add_llvm_component_library(LLVMFrontendOffloading Utility.cpp OffloadWrapper.cpp + PropertySet.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend diff --git a/llvm/lib/Frontend/Offloading/PropertySet.cpp b/llvm/lib/Frontend/Offloading/PropertySet.cpp new file mode 100644 index 0000000..a70290d --- /dev/null +++ b/llvm/lib/Frontend/Offloading/PropertySet.cpp @@ -0,0 +1,102 @@ +///===- llvm/Frontend/Offloading/PropertySet.cpp --------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/Frontend/Offloading/PropertySet.h" +#include "llvm/Support/Base64.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/MemoryBufferRef.h" + +using namespace llvm; +using namespace llvm::offloading; + +void llvm::offloading::writePropertiesToJSON( + const PropertySetRegistry &PSRegistry, raw_ostream &Out) { + json::OStream J(Out); + J.object([&] { + for (const auto &[CategoryName, PropSet] : PSRegistry) { + auto PropSetCapture = PropSet; + J.attributeObject(CategoryName, [&] { + for (const auto &[PropName, PropVal] : PropSetCapture) { + switch (PropVal.index()) { + case 0: + J.attribute(PropName, std::get<uint32_t>(PropVal)); + break; + case 1: + J.attribute(PropName, encodeBase64(std::get<ByteArray>(PropVal))); + break; + default: + llvm_unreachable("unsupported property type"); + } + } + }); + } + }); +} + +// note: createStringError has an overload that takes a format string, +// but it uses llvm::format instead of llvm::formatv, which does +// not work with json::Value. This is a helper function to use +// llvm::formatv with createStringError. +template <typename... Ts> auto createStringErrorV(Ts &&...Args) { + return createStringError(formatv(std::forward<Ts>(Args)...)); +} + +Expected<PropertyValue> +readPropertyValueFromJSON(const json::Value &PropValueVal) { + if (std::optional<uint64_t> Val = PropValueVal.getAsUINT64()) + return PropertyValue(static_cast<uint32_t>(*Val)); + + if (std::optional<StringRef> Val = PropValueVal.getAsString()) { + std::vector<char> Decoded; + if (Error E = decodeBase64(*Val, Decoded)) + return createStringErrorV("unable to base64 decode the string {0}: {1}", + Val, toString(std::move(E))); + return PropertyValue(ByteArray(Decoded.begin(), Decoded.end())); + } + + return createStringErrorV("expected a uint64 or a string, got {0}", + PropValueVal); +} + +Expected<PropertySetRegistry> +llvm::offloading::readPropertiesFromJSON(MemoryBufferRef Buf) { + PropertySetRegistry Res; + Expected<json::Value> V = json::parse(Buf.getBuffer()); + if (Error E = V.takeError()) + return E; + + const json::Object *O = V->getAsObject(); + if (!O) + return createStringErrorV( + "error while deserializing property set registry: " + "expected JSON object, got {0}", + *V); + + for (const auto &[CategoryName, Value] : *O) { + const json::Object *PropSetVal = Value.getAsObject(); + if (!PropSetVal) + return createStringErrorV("error while deserializing property set {0}: " + "expected JSON array, got {1}", + CategoryName.str(), Value); + + PropertySet &PropSet = Res[CategoryName.str()]; + for (const auto &[PropName, PropValueVal] : *PropSetVal) { + Expected<PropertyValue> Prop = readPropertyValueFromJSON(PropValueVal); + if (Error E = Prop.takeError()) + return createStringErrorV( + "error while deserializing property {0} in property set {1}: {2}", + PropName.str(), CategoryName.str(), toString(std::move(E))); + + auto [It, Inserted] = + PropSet.try_emplace(PropName.str(), std::move(*Prop)); + assert(Inserted && "Property already exists in PropertySet"); + (void)Inserted; + } + } + return Res; +} |