xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Object/OffloadBundle.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- OffloadBundle.h - Utilities for offload bundles---*- 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 // This file contains the binary format used for budingling device metadata with
10 // an associated device image. The data can then be stored inside a host object
11 // file to create a fat binary and read by the linker. This is intended to be a
12 // thin wrapper around the image itself. If this format becomes sufficiently
13 // complex it should be moved to a standard binary format like msgpack or ELF.
14 //
15 //===-------------------------------------------------------------------------===//
16 
17 #ifndef LLVM_OBJECT_OFFLOADBUNDLE_H
18 #define LLVM_OBJECT_OFFLOADBUNDLE_H
19 
20 #include "llvm/ADT/MapVector.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/Object/Binary.h"
24 #include "llvm/Object/ObjectFile.h"
25 #include "llvm/Support/Compiler.h"
26 #include "llvm/Support/Compression.h"
27 #include "llvm/Support/Error.h"
28 #include "llvm/Support/MemoryBuffer.h"
29 #include <memory>
30 
31 namespace llvm {
32 
33 namespace object {
34 
35 class CompressedOffloadBundle {
36 private:
37   static inline const size_t MagicSize = 4;
38   static inline const size_t VersionFieldSize = sizeof(uint16_t);
39   static inline const size_t MethodFieldSize = sizeof(uint16_t);
40   static inline const size_t FileSizeFieldSize = sizeof(uint32_t);
41   static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t);
42   static inline const size_t HashFieldSize = sizeof(uint64_t);
43   static inline const size_t V1HeaderSize =
44       MagicSize + VersionFieldSize + MethodFieldSize +
45       UncompressedSizeFieldSize + HashFieldSize;
46   static inline const size_t V2HeaderSize =
47       MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize +
48       UncompressedSizeFieldSize + HashFieldSize;
49   static inline const llvm::StringRef MagicNumber = "CCOB";
50   static inline const uint16_t Version = 2;
51 
52 public:
53   LLVM_ABI static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
54   compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
55            bool Verbose = false);
56   LLVM_ABI static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
57   decompress(llvm::MemoryBufferRef &Input, bool Verbose = false);
58 };
59 
60 /// Bundle entry in binary clang-offload-bundler format.
61 struct OffloadBundleEntry {
62   uint64_t Offset = 0u;
63   uint64_t Size = 0u;
64   uint64_t IDLength = 0u;
65   StringRef ID;
OffloadBundleEntryOffloadBundleEntry66   OffloadBundleEntry(uint64_t O, uint64_t S, uint64_t I, StringRef T)
67       : Offset(O), Size(S), IDLength(I), ID(T) {}
dumpInfoOffloadBundleEntry68   void dumpInfo(raw_ostream &OS) {
69     OS << "Offset = " << Offset << ", Size = " << Size
70        << ", ID Length = " << IDLength << ", ID = " << ID;
71   }
dumpURIOffloadBundleEntry72   void dumpURI(raw_ostream &OS, StringRef FilePath) {
73     OS << ID.data() << "\tfile://" << FilePath << "#offset=" << Offset
74        << "&size=" << Size << "\n";
75   }
76 };
77 
78 /// Fat binary embedded in object files in clang-offload-bundler format
79 class OffloadBundleFatBin {
80 
81   uint64_t Size = 0u;
82   StringRef FileName;
83   uint64_t NumberOfEntries;
84   SmallVector<OffloadBundleEntry> Entries;
85 
86 public:
getEntries()87   SmallVector<OffloadBundleEntry> getEntries() { return Entries; }
getSize()88   uint64_t getSize() const { return Size; }
getFileName()89   StringRef getFileName() const { return FileName; }
getNumEntries()90   uint64_t getNumEntries() const { return NumberOfEntries; }
91 
92   LLVM_ABI static Expected<std::unique_ptr<OffloadBundleFatBin>>
93   create(MemoryBufferRef, uint64_t SectionOffset, StringRef FileName);
94   LLVM_ABI Error extractBundle(const ObjectFile &Source);
95 
96   LLVM_ABI Error dumpEntryToCodeObject();
97 
98   LLVM_ABI Error readEntries(StringRef Section, uint64_t SectionOffset);
dumpEntries()99   void dumpEntries() {
100     for (OffloadBundleEntry &Entry : Entries)
101       Entry.dumpInfo(outs());
102   }
103 
printEntriesAsURI()104   void printEntriesAsURI() {
105     for (OffloadBundleEntry &Entry : Entries)
106       Entry.dumpURI(outs(), FileName);
107   }
108 
OffloadBundleFatBin(MemoryBufferRef Source,StringRef File)109   OffloadBundleFatBin(MemoryBufferRef Source, StringRef File)
110       : FileName(File), NumberOfEntries(0),
111         Entries(SmallVector<OffloadBundleEntry>()) {}
112 };
113 
114 enum UriTypeT { FILE_URI, MEMORY_URI };
115 
116 struct OffloadBundleURI {
117   int64_t Offset = 0;
118   int64_t Size = 0;
119   uint64_t ProcessID = 0;
120   StringRef FileName;
121   UriTypeT URIType;
122 
123   // Constructors
124   // TODO: add a Copy ctor ?
OffloadBundleURIOffloadBundleURI125   OffloadBundleURI(StringRef File, int64_t Off, int64_t Size)
126       : Offset(Off), Size(Size), ProcessID(0), FileName(File),
127         URIType(FILE_URI) {}
128 
129 public:
130   static Expected<std::unique_ptr<OffloadBundleURI>>
createOffloadBundleURIOffloadBundleURI131   createOffloadBundleURI(StringRef Str, UriTypeT Type) {
132     switch (Type) {
133     case FILE_URI:
134       return createFileURI(Str);
135       break;
136     case MEMORY_URI:
137       return createMemoryURI(Str);
138       break;
139     }
140     llvm_unreachable("Unknown UriTypeT enum");
141   }
142 
143   static Expected<std::unique_ptr<OffloadBundleURI>>
createFileURIOffloadBundleURI144   createFileURI(StringRef Str) {
145     int64_t O = 0;
146     int64_t S = 0;
147 
148     if (!Str.consume_front("file://"))
149       return createStringError(object_error::parse_failed,
150                                "Reading type of URI");
151 
152     StringRef FilePathname =
153         Str.take_until([](char C) { return (C == '#') || (C == '?'); });
154     Str = Str.drop_front(FilePathname.size());
155 
156     if (!Str.consume_front("#offset="))
157       return createStringError(object_error::parse_failed,
158                                "Reading 'offset' in URI");
159 
160     StringRef OffsetStr = Str.take_until([](char C) { return C == '&'; });
161     OffsetStr.getAsInteger(10, O);
162     Str = Str.drop_front(OffsetStr.size());
163 
164     if (Str.consume_front("&size="))
165       return createStringError(object_error::parse_failed,
166                                "Reading 'size' in URI");
167 
168     Str.getAsInteger(10, S);
169     std::unique_ptr<OffloadBundleURI> OffloadingURI(
170         new OffloadBundleURI(FilePathname, O, S));
171     return std::move(OffloadingURI);
172   }
173 
174   static Expected<std::unique_ptr<OffloadBundleURI>>
createMemoryURIOffloadBundleURI175   createMemoryURI(StringRef Str) {
176     // TODO: add parseMemoryURI type
177     return createStringError(object_error::parse_failed,
178                              "Memory Type URI is not currently supported.");
179   }
180 
getFileNameOffloadBundleURI181   StringRef getFileName() const { return FileName; }
182 };
183 
184 /// Extracts fat binary in binary clang-offload-bundler format from object \p
185 /// Obj and return it in \p Bundles
186 LLVM_ABI Error extractOffloadBundleFatBinary(
187     const ObjectFile &Obj, SmallVectorImpl<OffloadBundleFatBin> &Bundles);
188 
189 /// Extract code object memory from the given \p Source object file at \p Offset
190 /// and of \p Size, and copy into \p OutputFileName.
191 LLVM_ABI Error extractCodeObject(const ObjectFile &Source, int64_t Offset,
192                                  int64_t Size, StringRef OutputFileName);
193 
194 /// Extracts an Offload Bundle Entry given by URI
195 LLVM_ABI Error extractOffloadBundleByURI(StringRef URIstr);
196 
197 } // namespace object
198 
199 } // namespace llvm
200 #endif
201