|
15 | 15 | #include "llvm/IR/GlobalVariable.h" |
16 | 16 | #include "llvm/IR/Value.h" |
17 | 17 | #include "llvm/Object/ELFObjectFile.h" |
| 18 | +#include "llvm/ObjectYAML/ELFYAML.h" |
| 19 | +#include "llvm/ObjectYAML/yaml2obj.h" |
18 | 20 | #include "llvm/Support/MemoryBufferRef.h" |
19 | 21 | #include "llvm/Transforms/Utils/ModuleUtils.h" |
20 | 22 |
|
@@ -374,3 +376,86 @@ Error llvm::offloading::amdgpu::getAMDGPUMetaDataFromImage( |
374 | 376 | } |
375 | 377 | return Error::success(); |
376 | 378 | } |
| 379 | +Error offloading::intel::containerizeOpenMPSPIRVImage( |
| 380 | + std::unique_ptr<MemoryBuffer> &Img) { |
| 381 | + constexpr char INTEL_ONEOMP_OFFLOAD_VERSION[] = "1.0"; |
| 382 | + constexpr int NT_INTEL_ONEOMP_OFFLOAD_VERSION = 1; |
| 383 | + constexpr int NT_INTEL_ONEOMP_OFFLOAD_IMAGE_COUNT = 2; |
| 384 | + constexpr int NT_INTEL_ONEOMP_OFFLOAD_IMAGE_AUX = 3; |
| 385 | + |
| 386 | + // Start creating notes for the ELF container. |
| 387 | + std::vector<ELFYAML::NoteEntry> Notes; |
| 388 | + std::string Version = toHex(INTEL_ONEOMP_OFFLOAD_VERSION); |
| 389 | + Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD", |
| 390 | + yaml::BinaryRef(Version), |
| 391 | + NT_INTEL_ONEOMP_OFFLOAD_VERSION}); |
| 392 | + |
| 393 | + // The AuxInfo string will hold auxiliary information for the image. |
| 394 | + // ELFYAML::NoteEntry structures will hold references to the |
| 395 | + // string, so we have to make sure the string is valid. |
| 396 | + std::string AuxInfo; |
| 397 | + |
| 398 | + // TODO: Pass compile/link opts |
| 399 | + StringRef CompileOpts = ""; |
| 400 | + StringRef LinkOpts = ""; |
| 401 | + |
| 402 | + unsigned ImageFmt = 1; // SPIR-V format |
| 403 | + |
| 404 | + AuxInfo = toHex((Twine(0) + Twine('\0') + Twine(ImageFmt) + Twine('\0') + |
| 405 | + CompileOpts + Twine('\0') + LinkOpts) |
| 406 | + .str()); |
| 407 | + Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD", |
| 408 | + yaml::BinaryRef(AuxInfo), |
| 409 | + NT_INTEL_ONEOMP_OFFLOAD_IMAGE_AUX}); |
| 410 | + |
| 411 | + std::string ImgCount = toHex(Twine(1).str()); // always one image per ELF |
| 412 | + Notes.emplace_back(ELFYAML::NoteEntry{"INTELONEOMPOFFLOAD", |
| 413 | + yaml::BinaryRef(ImgCount), |
| 414 | + NT_INTEL_ONEOMP_OFFLOAD_IMAGE_COUNT}); |
| 415 | + |
| 416 | + std::string YamlFile; |
| 417 | + llvm::raw_string_ostream YamlFileStream(YamlFile); |
| 418 | + |
| 419 | + // Write the YAML template file. |
| 420 | + |
| 421 | + // We use 64-bit little-endian ELF currently. |
| 422 | + ELFYAML::FileHeader Header{}; |
| 423 | + Header.Class = ELF::ELFCLASS64; |
| 424 | + Header.Data = ELF::ELFDATA2LSB; |
| 425 | + Header.Type = ELF::ET_DYN; |
| 426 | + // Use an existing Intel machine type as there is not one specifically for |
| 427 | + // Intel GPUs. |
| 428 | + Header.Machine = ELF::EM_IA_64; |
| 429 | + |
| 430 | + // Create a section with notes. |
| 431 | + ELFYAML::NoteSection Section{}; |
| 432 | + Section.Type = ELF::SHT_NOTE; |
| 433 | + Section.AddressAlign = 0; |
| 434 | + Section.Name = ".note.inteloneompoffload"; |
| 435 | + Section.Notes.emplace(std::move(Notes)); |
| 436 | + |
| 437 | + ELFYAML::Object Object{}; |
| 438 | + Object.Header = Header; |
| 439 | + Object.Chunks.push_back( |
| 440 | + std::make_unique<ELFYAML::NoteSection>(std::move(Section))); |
| 441 | + |
| 442 | + // Create the section that will hold the image |
| 443 | + ELFYAML::RawContentSection ImageSection{}; |
| 444 | + ImageSection.Type = ELF::SHT_PROGBITS; |
| 445 | + ImageSection.AddressAlign = 0; |
| 446 | + std::string Name = "__openmp_offload_spirv_0"; |
| 447 | + ImageSection.Name = Name; |
| 448 | + ImageSection.Content = |
| 449 | + llvm::yaml::BinaryRef(arrayRefFromStringRef(Img->getBuffer())); |
| 450 | + Object.Chunks.push_back( |
| 451 | + std::make_unique<ELFYAML::RawContentSection>(std::move(ImageSection))); |
| 452 | + Error Err = Error::success(); |
| 453 | + llvm::yaml::yaml2elf( |
| 454 | + Object, YamlFileStream, |
| 455 | + [&Err](const Twine &Msg) { Err = createStringError(Msg); }, UINT64_MAX); |
| 456 | + if (Err) |
| 457 | + return Err; |
| 458 | + |
| 459 | + Img = MemoryBuffer::getMemBufferCopy(YamlFile); |
| 460 | + return Error::success(); |
| 461 | +} |
0 commit comments