1//===------ offload2yaml.cpp - obj2yaml conversion tool ---*- C++ -------*-===//
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
9#include "obj2yaml.h"
10#include "llvm/Object/OffloadBinary.h"
11#include "llvm/ObjectYAML/OffloadYAML.h"
12#include "llvm/Support/Alignment.h"
13#include "llvm/Support/MemoryBuffer.h"
14#include "llvm/Support/StringSaver.h"
15
16#include <memory>
17
18using namespace llvm;
19
20namespace {
21
22void populateYAML(OffloadYAML::Binary &YAMLBinary,
23 ArrayRef<std::unique_ptr<object::OffloadBinary>> OBinaries,
24 UniqueStringSaver &Saver) {
25 for (const auto &OBinaryPtr : OBinaries) {
26 object::OffloadBinary &OB = *OBinaryPtr;
27
28 YAMLBinary.Members.emplace_back();
29 auto &Member = YAMLBinary.Members.back();
30 Member.ImageKind = OB.getImageKind();
31 Member.OffloadKind = OB.getOffloadKind();
32 Member.Flags = OB.getFlags();
33 if (!OB.strings().empty()) {
34 Member.StringEntries = std::vector<OffloadYAML::Binary::StringEntry>();
35 for (const auto &StringEntry : OB.strings())
36 Member.StringEntries->emplace_back(args: OffloadYAML::Binary::StringEntry(
37 {.Key: Saver.save(S: StringEntry.first), .Value: Saver.save(S: StringEntry.second)}));
38 }
39
40 if (!OB.getImage().empty())
41 Member.Content = arrayRefFromStringRef(Input: Saver.save(S: OB.getImage()));
42 }
43}
44
45Expected<OffloadYAML::Binary *> dump(MemoryBufferRef Source,
46 UniqueStringSaver &Saver) {
47 std::unique_ptr<OffloadYAML::Binary> YAMLBinary =
48 std::make_unique<OffloadYAML::Binary>();
49
50 YAMLBinary->Members = std::vector<OffloadYAML::Binary::Member>();
51
52 uint64_t Offset = 0;
53 while (Offset < Source.getBufferSize()) {
54 MemoryBufferRef Buffer = MemoryBufferRef(
55 Source.getBuffer().drop_front(N: Offset), Source.getBufferIdentifier());
56 std::unique_ptr<MemoryBuffer> Aligned;
57 if (!isAddrAligned(Lhs: Align(object::OffloadBinary::getAlignment()),
58 Addr: Buffer.getBufferStart())) {
59 Aligned = MemoryBuffer::getMemBufferCopy(InputData: Buffer.getBuffer(),
60 BufferName: Buffer.getBufferIdentifier());
61 Buffer = *Aligned;
62 }
63 auto HeaderOrErr = object::OffloadBinary::extractHeader(Buf: Buffer);
64 if (!HeaderOrErr)
65 return HeaderOrErr.takeError();
66 const object::OffloadBinary::Header *TheHeader = *HeaderOrErr;
67 uint64_t Size = TheHeader->Size;
68
69 auto BinariesOrErr = object::OffloadBinary::create(Buf: Buffer);
70 if (!BinariesOrErr)
71 return BinariesOrErr.takeError();
72
73 populateYAML(YAMLBinary&: *YAMLBinary, OBinaries: *BinariesOrErr, Saver);
74
75 Offset =
76 alignTo(Size: Offset + Size, A: Align(object::OffloadBinary::getAlignment()));
77 }
78
79 return YAMLBinary.release();
80}
81
82} // namespace
83
84Error offload2yaml(raw_ostream &Out, MemoryBufferRef Source) {
85 BumpPtrAllocator Alloc;
86 UniqueStringSaver Saver(Alloc);
87
88 Expected<OffloadYAML::Binary *> YAMLOrErr = dump(Source, Saver);
89 if (!YAMLOrErr)
90 return YAMLOrErr.takeError();
91
92 std::unique_ptr<OffloadYAML::Binary> YAML(YAMLOrErr.get());
93 yaml::Output Yout(Out);
94 Yout << *YAML;
95
96 return Error::success();
97}
98