1 //===- OffloadBundler.h - File Bundling and Unbundling ----------*- 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 /// \file 10 /// This file defines an offload bundling API that bundles different files 11 /// that relate with the same source code but different targets into a single 12 /// one. Also the implements the opposite functionality, i.e. unbundle files 13 /// previous created by this API. 14 /// 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_CLANG_DRIVER_OFFLOADBUNDLER_H 18 #define LLVM_CLANG_DRIVER_OFFLOADBUNDLER_H 19 20 #include "llvm/Support/Compression.h" 21 #include "llvm/Support/Error.h" 22 #include "llvm/TargetParser/Triple.h" 23 #include <llvm/Support/MemoryBuffer.h> 24 #include <string> 25 #include <vector> 26 27 namespace clang { 28 29 class OffloadBundlerConfig { 30 public: 31 OffloadBundlerConfig(); 32 33 bool AllowNoHost = false; 34 bool AllowMissingBundles = false; 35 bool CheckInputArchive = false; 36 bool PrintExternalCommands = false; 37 bool HipOpenmpCompatible = false; 38 bool Compress = false; 39 bool Verbose = false; 40 llvm::compression::Format CompressionFormat; 41 int CompressionLevel; 42 uint16_t CompressedBundleVersion; 43 44 unsigned BundleAlignment = 1; 45 unsigned HostInputIndex = ~0u; 46 47 std::string FilesType; 48 std::string ObjcopyPath; 49 50 // TODO: Convert these to llvm::SmallVector 51 std::vector<std::string> TargetNames; 52 std::vector<std::string> InputFileNames; 53 std::vector<std::string> OutputFileNames; 54 }; 55 56 class OffloadBundler { 57 public: 58 const OffloadBundlerConfig &BundlerConfig; 59 60 // TODO: Add error checking from ClangOffloadBundler.cpp 61 OffloadBundler(const OffloadBundlerConfig &BC) : BundlerConfig(BC) {} 62 63 // List bundle IDs. Return true if an error was found. 64 static llvm::Error 65 ListBundleIDsInFile(llvm::StringRef InputFileName, 66 const OffloadBundlerConfig &BundlerConfig); 67 68 llvm::Error BundleFiles(); 69 llvm::Error UnbundleFiles(); 70 llvm::Error UnbundleArchive(); 71 }; 72 73 /// Obtain the offload kind, real machine triple, and an optional TargetID 74 /// out of the target information specified by the user. 75 /// Bundle Entry ID (or, Offload Target String) has following components: 76 /// * Offload Kind - Host, OpenMP, or HIP 77 /// * Triple - Standard LLVM Triple 78 /// * TargetID (Optional) - target ID, like gfx906:xnack+ or sm_30 79 struct OffloadTargetInfo { 80 llvm::StringRef OffloadKind; 81 llvm::Triple Triple; 82 llvm::StringRef TargetID; 83 84 const OffloadBundlerConfig &BundlerConfig; 85 86 OffloadTargetInfo(const llvm::StringRef Target, 87 const OffloadBundlerConfig &BC); 88 bool hasHostKind() const; 89 bool isOffloadKindValid() const; 90 bool isOffloadKindCompatible(const llvm::StringRef TargetOffloadKind) const; 91 bool isTripleValid() const; 92 bool operator==(const OffloadTargetInfo &Target) const; 93 std::string str() const; 94 }; 95 96 // CompressedOffloadBundle represents the format for the compressed offload 97 // bundles. 98 // 99 // The format is as follows: 100 // - Magic Number (4 bytes) - A constant "CCOB". 101 // - Version (2 bytes) 102 // - Compression Method (2 bytes) - Uses the values from 103 // llvm::compression::Format. 104 // - Total file size (4 bytes in V2, 8 bytes in V3). 105 // - Uncompressed Size (4 bytes in V1/V2, 8 bytes in V3). 106 // - Truncated MD5 Hash (8 bytes). 107 // - Compressed Data (variable length). 108 class CompressedOffloadBundle { 109 private: 110 static inline const size_t MagicSize = 4; 111 static inline const size_t VersionFieldSize = sizeof(uint16_t); 112 static inline const size_t MethodFieldSize = sizeof(uint16_t); 113 // Legacy size fields for V1/V2 114 static inline const size_t FileSizeFieldSizeV2 = sizeof(uint32_t); 115 static inline const size_t UncompressedSizeFieldSizeV2 = sizeof(uint32_t); 116 // New size fields for V3 117 static inline const size_t FileSizeFieldSizeV3 = sizeof(uint64_t); 118 static inline const size_t UncompressedSizeFieldSizeV3 = sizeof(uint64_t); 119 static inline const size_t HashFieldSize = sizeof(uint64_t); 120 121 // Keep V1 header size for backward compatibility 122 static inline const size_t V1HeaderSize = 123 MagicSize + VersionFieldSize + MethodFieldSize + 124 UncompressedSizeFieldSizeV2 + HashFieldSize; 125 126 // Keep V2 header size for backward compatibility 127 static inline const size_t V2HeaderSize = 128 MagicSize + VersionFieldSize + FileSizeFieldSizeV2 + MethodFieldSize + 129 UncompressedSizeFieldSizeV2 + HashFieldSize; 130 131 // Add V3 header size with 64-bit fields 132 static inline const size_t V3HeaderSize = 133 MagicSize + VersionFieldSize + FileSizeFieldSizeV3 + MethodFieldSize + 134 UncompressedSizeFieldSizeV3 + HashFieldSize; 135 136 static inline const llvm::StringRef MagicNumber = "CCOB"; 137 138 public: 139 static inline const uint16_t DefaultVersion = 2; 140 141 // Helper method to get header size based on version 142 static size_t getHeaderSize(uint16_t Version) { 143 switch (Version) { 144 case 1: 145 return V1HeaderSize; 146 case 2: 147 return V2HeaderSize; 148 case 3: 149 return V3HeaderSize; 150 default: 151 llvm_unreachable("Unsupported version"); 152 } 153 } 154 155 static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> 156 compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input, 157 uint16_t Version, bool Verbose = false); 158 static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> 159 decompress(const llvm::MemoryBuffer &Input, bool Verbose = false); 160 }; 161 } // namespace clang 162 163 #endif // LLVM_CLANG_DRIVER_OFFLOADBUNDLER_H 164