| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s | ||
| !Offload | ||
| EntrySize: 999999999 | ||
| Members: | ||
| - ImageKind: IMG_Cubin | ||
| OffloadKind: OFK_OpenMP | ||
| Flags: 0 | ||
| String: | ||
| - Key: "triple" | ||
| Value: "nvptx64-nvidia-cuda" | ||
| - Key: "arch" | ||
| Value: "sm_70" | ||
| Content: "deadbeef" | ||
|
|
||
| # CHECK: Error reading file: <stdin>: The end of the file was unexpectedly encountered |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s | ||
| !Offload | ||
| EntryOffset: 999999999 | ||
| Members: | ||
| - ImageKind: IMG_Cubin | ||
| OffloadKind: OFK_OpenMP | ||
| Flags: 0 | ||
| String: | ||
| - Key: "triple" | ||
| Value: "nvptx64-nvidia-cuda" | ||
| - Key: "arch" | ||
| Value: "sm_70" | ||
| Content: "deadbeef" | ||
|
|
||
| # CHECK: Error reading file: <stdin>: The end of the file was unexpectedly encountered |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s | ||
| !Offload | ||
| Size: 999999999 | ||
| Members: | ||
| - ImageKind: IMG_Cubin | ||
| OffloadKind: OFK_OpenMP | ||
| Flags: 0 | ||
| String: | ||
| - Key: "triple" | ||
| Value: "nvptx64-nvidia-cuda" | ||
| - Key: "arch" | ||
| Value: "sm_70" | ||
| Content: "deadbeef" | ||
|
|
||
| # CHECK: Error reading file: <stdin>: The end of the file was unexpectedly encountered |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s | ||
| !Offload | ||
| Version: 2 | ||
| Members: | ||
| - ImageKind: IMG_Cubin | ||
| OffloadKind: OFK_OpenMP | ||
| Flags: 0 | ||
| String: | ||
| - Key: "triple" | ||
| Value: "nvptx64-nvidia-cuda" | ||
| - Key: "arch" | ||
| Value: "sm_70" | ||
| Content: "deadbeef" | ||
|
|
||
| # CHECK: Error reading file: <stdin>: Invalid data was encountered while parsing the file |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # RUN: yaml2obj %s | obj2yaml | FileCheck %s | ||
| !Offload | ||
| Members: | ||
| - ImageKind: IMG_Cubin | ||
| OffloadKind: OFK_OpenMP | ||
| Flags: 0 | ||
| String: | ||
| - Key: "triple" | ||
| Value: "nvptx64-nvidia-cuda" | ||
| - Key: "arch" | ||
| Value: "sm_70" | ||
| Content: "deadbeef" | ||
| - ImageKind: IMG_Bitcode | ||
| OffloadKind: OFK_OpenMP | ||
| Flags: 0 | ||
| String: | ||
| - Key: "triple" | ||
| Value: "amdgcn-amd-amdhsa" | ||
| - Key: "arch" | ||
| Value: "gfx908" | ||
| Content: "cafefeed" | ||
|
|
||
| # CHECK: --- !Offload | ||
| # CHECK-NEXT: Members: | ||
| # CHECK-NEXT: - ImageKind: IMG_Cubin | ||
| # CHECK-NEXT: OffloadKind: OFK_OpenMP | ||
| # CHECK-NEXT: Flags: 0 | ||
| # CHECK-NEXT: String: | ||
| # CHECK-NEXT: - Key: triple | ||
| # CHECK-NEXT: Value: nvptx64-nvidia-cuda | ||
| # CHECK-NEXT: - Key: arch | ||
| # CHECK-NEXT: Value: sm_70 | ||
| # CHECK-NEXT: Content: DEADBEEF | ||
| # CHECK-NEXT: - ImageKind: IMG_Bitcode | ||
| # CHECK-NEXT: OffloadKind: OFK_OpenMP | ||
| # CHECK-NEXT: Flags: 0 | ||
| # CHECK-NEXT: String: | ||
| # CHECK-NEXT: - Key: triple | ||
| # CHECK-NEXT: Value: amdgcn-amd-amdhsa | ||
| # CHECK-NEXT: - Key: arch | ||
| # CHECK-NEXT: Value: gfx908 | ||
| # CHECK-NEXT: Content: CAFEFEED | ||
| # CHECK-NEXT: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| !Offload | ||
| Members: | ||
| - ImageKind: IMG_Bitcode | ||
| OffloadKind: OFK_OpenMP | ||
| String: | ||
| - Key: "triple" | ||
| Value: "amdgcn-amd-amdhsa" | ||
| - Key: "arch" | ||
| Value: "gfx908" | ||
| - ImageKind: IMG_Bitcode | ||
| OffloadKind: OFK_OpenMP | ||
| String: | ||
| - Key: "triple" | ||
| Value: "amdgcn-amd-amdhsa" | ||
| - Key: "arch" | ||
| Value: "gfx90a" | ||
| - ImageKind: IMG_Cubin | ||
| OffloadKind: OFK_OpenMP | ||
| String: | ||
| - Key: "triple" | ||
| Value: "nvptx64-nvidia-cuda" | ||
| - Key: "arch" | ||
| Value: "sm_52" | ||
| - ImageKind: IMG_None | ||
| OffloadKind: OFK_None | ||
| String: | ||
| - Key: "triple" | ||
| Value: "nvptx64-nvidia-cuda" | ||
| - Key: "arch" | ||
| Value: "sm_70" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| !Offload | ||
| EntryOffset: 999999999 | ||
| Members: | ||
| - ImageKind: IMG_Cubin | ||
| OffloadKind: OFK_OpenMP | ||
| Flags: 0 | ||
| String: | ||
| - Key: "triple" | ||
| Value: "nvptx64-nvidia-cuda" | ||
| - Key: "arch" | ||
| Value: "sm_70" | ||
| Content: "deadbeef" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| ## Check that we can dump an offloading binary directly. | ||
| # RUN: yaml2obj %S/Inputs/binary.yaml -o %t.bin | ||
| # RUN: llvm-objdump --offloading %t.bin | FileCheck %s --match-full-lines --strict-whitespace --implicit-check-not={{.}} | ||
|
|
||
| ## Check that we can dump an offloading binary inside of an ELF section. | ||
| # RUN: yaml2obj %s -o %t.elf | ||
| # RUN: llvm-objcopy --add-section .llvm.offloading=%t.bin %t.elf | ||
| # RUN: llvm-objdump --offloading %t.elf | FileCheck %s --check-prefixes=CHECK,ELF --match-full-lines --strict-whitespace --implicit-check-not={{.}} | ||
|
|
||
| !ELF | ||
| FileHeader: | ||
| Class: ELFCLASS64 | ||
| Data: ELFDATA2LSB | ||
| Type: ET_EXEC | ||
|
|
||
| # ELF:{{.*}}file format elf64-unknown | ||
| # ELF-EMPTY: | ||
| # CHECK:OFFLOADING IMAGE [0]: | ||
| # CHECK-NEXT:kind llvm ir | ||
| # CHECK-NEXT:arch gfx908 | ||
| # CHECK-NEXT:triple amdgcn-amd-amdhsa | ||
| # CHECK-NEXT:producer openmp | ||
| # CHECK-EMPTY: | ||
| # CHECK-NEXT:OFFLOADING IMAGE [1]: | ||
| # CHECK-NEXT:kind llvm ir | ||
| # CHECK-NEXT:arch gfx90a | ||
| # CHECK-NEXT:triple amdgcn-amd-amdhsa | ||
| # CHECK-NEXT:producer openmp | ||
| # CHECK-EMPTY: | ||
| # CHECK-NEXT:OFFLOADING IMAGE [2]: | ||
| # CHECK-NEXT:kind cubin | ||
| # CHECK-NEXT:arch sm_52 | ||
| # CHECK-NEXT:triple nvptx64-nvidia-cuda | ||
| # CHECK-NEXT:producer openmp | ||
| # CHECK-EMPTY: | ||
| # CHECK-NEXT:OFFLOADING IMAGE [3]: | ||
| # CHECK-NEXT:kind <none> | ||
| # CHECK-NEXT:arch sm_70 | ||
| # CHECK-NEXT:triple nvptx64-nvidia-cuda | ||
| # CHECK-NEXT:producer none |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Test to check if we fail to get the section contents. | ||
| # RUN: yaml2obj %s -o %t | ||
| # RUN: not llvm-objdump --offloading %t 2>&1 | FileCheck -DFILENAME=%t %s | ||
|
|
||
| !ELF | ||
| FileHeader: | ||
| Class: ELFCLASS64 | ||
| Data: ELFDATA2LSB | ||
| Type: ET_EXEC | ||
| Sections: | ||
| - Name: .llvm.offloading | ||
| Type: SHT_PROGBITS | ||
| Flags: [ SHF_EXCLUDE ] | ||
| Address: 0x0 | ||
| ShOffset: 0x99999 | ||
| AddressAlign: 0x0000000000000008 | ||
|
|
||
| # CHECK: error: '[[FILENAME]]': The end of the file was unexpectedly encountered |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # RUN: yaml2obj %s -o %t | ||
| # RUN: not llvm-objdump --offloading %t 2>&1 | FileCheck -DFILENAME=%t %s | ||
|
|
||
| !ELF | ||
| FileHeader: | ||
| Class: ELFCLASS64 | ||
| Data: ELFDATA2LSB | ||
| Type: ET_EXEC | ||
| Sections: | ||
| - Name: .llvm.offloading | ||
| Type: SHT_PROGBITS | ||
| Flags: [ SHF_EXCLUDE ] | ||
| Address: 0x0 | ||
| AddressAlign: 0x0000000000000008 | ||
| Content: "10ffb0ad" | ||
|
|
||
| # CHECK: error: '[[FILENAME]]': while extracting offloading files: Invalid data was encountered while parsing the file |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| ## Ensure we give a warning on bad input following good input. | ||
| # RUN: yaml2obj %S/Inputs/binary.yaml -o %t-good.bin | ||
| # RUN: yaml2obj %S/Inputs/malformed.yaml -o %t-bad.bin | ||
| # RUN: cat %t-bad.bin >> %t-good.bin | ||
| # RUN: yaml2obj %s -o %t.elf | ||
| # RUN: llvm-objcopy --add-section .llvm.offloading=%t-good.bin %t.elf | ||
| # RUN: llvm-objdump --offloading %t.elf 2>&1 | FileCheck %s -DFILENAME=%t.elf | ||
|
|
||
| !ELF | ||
| FileHeader: | ||
| Class: ELFCLASS64 | ||
| Data: ELFDATA2LSB | ||
| Type: ET_EXEC | ||
|
|
||
| # CHECK: OFFLOADING IMAGE [0]: | ||
| # CHECK: warning: '[[FILENAME]]': while parsing offloading files: The end of the file was unexpectedly encountered |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| //===-- OffloadDump.cpp - Offloading dumper ---------------------*- C++ -*-===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| /// | ||
| /// \file | ||
| /// This file implements the offloading-specific dumper for llvm-objdump. | ||
| /// | ||
| //===----------------------------------------------------------------------===// | ||
| #include "OffloadDump.h" | ||
| #include "llvm-objdump.h" | ||
|
|
||
| using namespace llvm; | ||
| using namespace llvm::object; | ||
| using namespace llvm::objdump; | ||
|
|
||
| constexpr const char OffloadSectionString[] = ".llvm.offloading"; | ||
|
|
||
| /// Get the printable name of the image kind. | ||
| static StringRef getImageName(const OffloadBinary &OB) { | ||
| switch (OB.getImageKind()) { | ||
| case IMG_Object: | ||
| return "elf"; | ||
| case IMG_Bitcode: | ||
| return "llvm ir"; | ||
| case IMG_Cubin: | ||
| return "cubin"; | ||
| case IMG_Fatbinary: | ||
| return "fatbinary"; | ||
| case IMG_PTX: | ||
| return "ptx"; | ||
| default: | ||
| return "<none>"; | ||
| } | ||
| } | ||
|
|
||
| static void printBinary(const OffloadBinary &OB, uint64_t Index) { | ||
| outs() << "\nOFFLOADING IMAGE [" << Index << "]:\n"; | ||
| outs() << left_justify("kind", 16) << getImageName(OB) << "\n"; | ||
| outs() << left_justify("arch", 16) << OB.getArch() << "\n"; | ||
| outs() << left_justify("triple", 16) << OB.getTriple() << "\n"; | ||
| outs() << left_justify("producer", 16) | ||
| << getOffloadKindName(OB.getOffloadKind()) << "\n"; | ||
| } | ||
|
|
||
| static Error visitAllBinaries(const OffloadBinary &OB) { | ||
| uint64_t Offset = 0; | ||
| uint64_t Index = 0; | ||
| while (Offset < OB.getMemoryBufferRef().getBufferSize()) { | ||
| MemoryBufferRef Buffer = | ||
| MemoryBufferRef(OB.getData().drop_front(Offset), OB.getFileName()); | ||
| auto BinaryOrErr = OffloadBinary::create(Buffer); | ||
| if (!BinaryOrErr) | ||
| return BinaryOrErr.takeError(); | ||
|
|
||
| OffloadBinary &Binary = **BinaryOrErr; | ||
| printBinary(Binary, Index++); | ||
|
|
||
| Offset += Binary.getSize(); | ||
| } | ||
| return Error::success(); | ||
| } | ||
|
|
||
| /// Print the embedded offloading contents of an ObjectFile \p O. | ||
| void llvm::dumpOffloadBinary(const ObjectFile &O) { | ||
| for (SectionRef Sec : O.sections()) { | ||
| Expected<StringRef> Name = Sec.getName(); | ||
| if (!Name || !Name->startswith(OffloadSectionString)) | ||
| continue; | ||
|
|
||
| Expected<StringRef> Contents = Sec.getContents(); | ||
| if (!Contents) | ||
| reportError(Contents.takeError(), O.getFileName()); | ||
|
|
||
| MemoryBufferRef Buffer = MemoryBufferRef(*Contents, O.getFileName()); | ||
| auto BinaryOrErr = OffloadBinary::create(Buffer); | ||
| if (!BinaryOrErr) | ||
| reportError(O.getFileName(), "while extracting offloading files: " + | ||
| toString(BinaryOrErr.takeError())); | ||
| OffloadBinary &Binary = **BinaryOrErr; | ||
|
|
||
| // Print out all the binaries that are contained in this buffer. If we fail | ||
| // to parse a binary before reaching the end of the buffer emit a warning. | ||
| if (Error Err = visitAllBinaries(Binary)) | ||
| reportWarning("while parsing offloading files: " + | ||
| toString(std::move(Err)), | ||
| O.getFileName()); | ||
| } | ||
| } | ||
|
|
||
| /// Print the contents of an offload binary file \p OB. This may contain | ||
| /// multiple binaries stored in the same buffer. | ||
| void llvm::dumpOffloadSections(const OffloadBinary &OB) { | ||
| // Print out all the binaries that are contained at this buffer. If we fail to | ||
| // parse a binary before reaching the end of the buffer emit a warning. | ||
| if (Error Err = visitAllBinaries(OB)) | ||
| reportWarning("while parsing offloading files: " + toString(std::move(Err)), | ||
| OB.getFileName()); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| //===-- OffloadDump.h -------------------------------------------*- C++ -*-===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_TOOLS_LLVM_OBJDUMP_OFFLOADDUMP_H | ||
| #define LLVM_TOOLS_LLVM_OBJDUMP_OFFLOADDUMP_H | ||
|
|
||
| #include "llvm/Object/ObjectFile.h" | ||
| #include "llvm/Object/OffloadBinary.h" | ||
|
|
||
| namespace llvm { | ||
|
|
||
| void dumpOffloadSections(const object::OffloadBinary &OB); | ||
| void dumpOffloadBinary(const object::ObjectFile &O); | ||
|
|
||
| } // namespace llvm | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| //===------ offload2yaml.cpp - obj2yaml conversion tool ---*- C++ -------*-===// | ||
| // | ||
| // 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 "obj2yaml.h" | ||
| #include "llvm/BinaryFormat/Magic.h" | ||
| #include "llvm/Object/OffloadBinary.h" | ||
| #include "llvm/ObjectYAML/OffloadYAML.h" | ||
| #include "llvm/Support/StringSaver.h" | ||
|
|
||
| using namespace llvm; | ||
|
|
||
| namespace { | ||
|
|
||
| void populateYAML(OffloadYAML::Binary &YAMLBinary, object::OffloadBinary &OB, | ||
| UniqueStringSaver Saver) { | ||
| YAMLBinary.Members.emplace_back(); | ||
| auto &Member = YAMLBinary.Members.back(); | ||
| Member.ImageKind = OB.getImageKind(); | ||
| Member.OffloadKind = OB.getOffloadKind(); | ||
| Member.Flags = OB.getFlags(); | ||
| if (!OB.strings().empty()) { | ||
| Member.StringEntries = std::vector<OffloadYAML::Binary::StringEntry>(); | ||
| for (const auto &Entry : OB.strings()) | ||
| Member.StringEntries->emplace_back(OffloadYAML::Binary::StringEntry( | ||
| {Saver.save(Entry.getKey()), Saver.save(Entry.getValue())})); | ||
| } | ||
|
|
||
| if (!OB.getImage().empty()) | ||
| Member.Content = arrayRefFromStringRef(OB.getImage()); | ||
| } | ||
|
|
||
| Expected<OffloadYAML::Binary *> dump(MemoryBufferRef Source, | ||
| UniqueStringSaver Saver) { | ||
| Expected<std::unique_ptr<object::OffloadBinary>> OB = | ||
| object::OffloadBinary::create(Source); | ||
| if (!OB) | ||
| return OB.takeError(); | ||
|
|
||
| std::unique_ptr<OffloadYAML::Binary> YAMLBinary = | ||
| std::make_unique<OffloadYAML::Binary>(); | ||
|
|
||
| YAMLBinary->Members = std::vector<OffloadYAML::Binary::Member>(); | ||
|
|
||
| uint64_t Offset = 0; | ||
| while (Offset < (*OB)->getMemoryBufferRef().getBufferSize()) { | ||
| MemoryBufferRef Buffer = MemoryBufferRef( | ||
| (*OB)->getData().drop_front(Offset), (*OB)->getFileName()); | ||
| auto BinaryOrErr = object::OffloadBinary::create(Buffer); | ||
| if (!BinaryOrErr) | ||
| return BinaryOrErr.takeError(); | ||
|
|
||
| object::OffloadBinary &Binary = **BinaryOrErr; | ||
|
|
||
| populateYAML(*YAMLBinary, Binary, Saver); | ||
|
|
||
| Offset += Binary.getSize(); | ||
| } | ||
|
|
||
| return YAMLBinary.release(); | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| Error offload2yaml(raw_ostream &Out, MemoryBufferRef Source) { | ||
| BumpPtrAllocator Alloc; | ||
| UniqueStringSaver Saver(Alloc); | ||
|
|
||
| Expected<OffloadYAML::Binary *> YAMLOrErr = dump(Source, Saver); | ||
| if (!YAMLOrErr) | ||
| return YAMLOrErr.takeError(); | ||
|
|
||
| std::unique_ptr<OffloadYAML::Binary> YAML(YAMLOrErr.get()); | ||
| yaml::Output Yout(Out); | ||
| Yout << *YAML; | ||
|
|
||
| return Error::success(); | ||
| } |