aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Frontend/Offloading/PropertySet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Frontend/Offloading/PropertySet.cpp')
-rw-r--r--llvm/lib/Frontend/Offloading/PropertySet.cpp102
1 files changed, 102 insertions, 0 deletions
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;
+}