brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.9 KiB · 7c3404e Raw
165 lines · cpp
1//===---------- DeviceOffload.cpp - Device Offloading------------*- 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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements offloading to CUDA devices.10//11//===----------------------------------------------------------------------===//12 13#include "DeviceOffload.h"14 15#include "clang/Basic/TargetOptions.h"16#include "clang/CodeGen/ModuleBuilder.h"17#include "clang/Frontend/CompilerInstance.h"18#include "clang/Interpreter/PartialTranslationUnit.h"19 20#include "llvm/IR/LegacyPassManager.h"21#include "llvm/IR/Module.h"22#include "llvm/MC/TargetRegistry.h"23#include "llvm/Target/TargetMachine.h"24 25namespace clang {26 27IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(28    CompilerInstance &DeviceInstance, CompilerInstance &HostInstance,29    IncrementalAction *DeviceAct,30    llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS,31    llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs)32    : IncrementalParser(DeviceInstance, DeviceAct, Err, PTUs), VFS(FS),33      CodeGenOpts(HostInstance.getCodeGenOpts()),34      TargetOpts(DeviceInstance.getTargetOpts()) {35  if (Err)36    return;37  StringRef Arch = TargetOpts.CPU;38  if (!Arch.starts_with("sm_") || Arch.substr(3).getAsInteger(10, SMVersion)) {39    Err = llvm::joinErrors(std::move(Err), llvm::make_error<llvm::StringError>(40                                               "Invalid CUDA architecture",41                                               llvm::inconvertibleErrorCode()));42    return;43  }44}45 46llvm::Expected<llvm::StringRef> IncrementalCUDADeviceParser::GeneratePTX() {47  auto &PTU = PTUs.back();48  std::string Error;49 50  const llvm::Target *Target = llvm::TargetRegistry::lookupTarget(51      PTU.TheModule->getTargetTriple(), Error);52  if (!Target)53    return llvm::make_error<llvm::StringError>(std::move(Error),54                                               std::error_code());55  llvm::TargetOptions TO = llvm::TargetOptions();56  llvm::TargetMachine *TargetMachine = Target->createTargetMachine(57      PTU.TheModule->getTargetTriple(), TargetOpts.CPU, "", TO,58      llvm::Reloc::Model::PIC_);59  PTU.TheModule->setDataLayout(TargetMachine->createDataLayout());60 61  PTXCode.clear();62  llvm::raw_svector_ostream dest(PTXCode);63 64  llvm::legacy::PassManager PM;65  if (TargetMachine->addPassesToEmitFile(PM, dest, nullptr,66                                         llvm::CodeGenFileType::AssemblyFile)) {67    return llvm::make_error<llvm::StringError>(68        "NVPTX backend cannot produce PTX code.",69        llvm::inconvertibleErrorCode());70  }71 72  if (!PM.run(*PTU.TheModule))73    return llvm::make_error<llvm::StringError>("Failed to emit PTX code.",74                                               llvm::inconvertibleErrorCode());75 76  PTXCode += '\0';77  while (PTXCode.size() % 8)78    PTXCode += '\0';79  return PTXCode.str();80}81 82llvm::Error IncrementalCUDADeviceParser::GenerateFatbinary() {83  enum FatBinFlags {84    AddressSize64 = 0x01,85    HasDebugInfo = 0x02,86    ProducerCuda = 0x04,87    HostLinux = 0x10,88    HostMac = 0x20,89    HostWindows = 0x4090  };91 92  struct FatBinInnerHeader {93    uint16_t Kind;             // 0x0094    uint16_t unknown02;        // 0x0295    uint32_t HeaderSize;       // 0x0496    uint32_t DataSize;         // 0x0897    uint32_t unknown0c;        // 0x0c98    uint32_t CompressedSize;   // 0x1099    uint32_t SubHeaderSize;    // 0x14100    uint16_t VersionMinor;     // 0x18101    uint16_t VersionMajor;     // 0x1a102    uint32_t CudaArch;         // 0x1c103    uint32_t unknown20;        // 0x20104    uint32_t unknown24;        // 0x24105    uint32_t Flags;            // 0x28106    uint32_t unknown2c;        // 0x2c107    uint32_t unknown30;        // 0x30108    uint32_t unknown34;        // 0x34109    uint32_t UncompressedSize; // 0x38110    uint32_t unknown3c;        // 0x3c111    uint32_t unknown40;        // 0x40112    uint32_t unknown44;        // 0x44113    FatBinInnerHeader(uint32_t DataSize, uint32_t CudaArch, uint32_t Flags)114        : Kind(1 /*PTX*/), unknown02(0x0101), HeaderSize(sizeof(*this)),115          DataSize(DataSize), unknown0c(0), CompressedSize(0),116          SubHeaderSize(HeaderSize - 8), VersionMinor(2), VersionMajor(4),117          CudaArch(CudaArch), unknown20(0), unknown24(0), Flags(Flags),118          unknown2c(0), unknown30(0), unknown34(0), UncompressedSize(0),119          unknown3c(0), unknown40(0), unknown44(0) {}120  };121 122  struct FatBinHeader {123    uint32_t Magic;      // 0x00124    uint16_t Version;    // 0x04125    uint16_t HeaderSize; // 0x06126    uint32_t DataSize;   // 0x08127    uint32_t unknown0c;  // 0x0c128  public:129    FatBinHeader(uint32_t DataSize)130        : Magic(0xba55ed50), Version(1), HeaderSize(sizeof(*this)),131          DataSize(DataSize), unknown0c(0) {}132  };133 134  FatBinHeader OuterHeader(sizeof(FatBinInnerHeader) + PTXCode.size());135  FatbinContent.append((char *)&OuterHeader,136                       ((char *)&OuterHeader) + OuterHeader.HeaderSize);137 138  FatBinInnerHeader InnerHeader(PTXCode.size(), SMVersion,139                                FatBinFlags::AddressSize64 |140                                    FatBinFlags::HostLinux);141  FatbinContent.append((char *)&InnerHeader,142                       ((char *)&InnerHeader) + InnerHeader.HeaderSize);143 144  FatbinContent.append(PTXCode.begin(), PTXCode.end());145 146  const PartialTranslationUnit &PTU = PTUs.back();147 148  std::string FatbinFileName = "/" + PTU.TheModule->getName().str() + ".fatbin";149 150  VFS->addFile(FatbinFileName, 0,151               llvm::MemoryBuffer::getMemBuffer(152                   llvm::StringRef(FatbinContent.data(), FatbinContent.size()),153                   "", false));154 155  CodeGenOpts.CudaGpuBinaryFileName = std::move(FatbinFileName);156 157  FatbinContent.clear();158 159  return llvm::Error::success();160}161 162IncrementalCUDADeviceParser::~IncrementalCUDADeviceParser() {}163 164} // namespace clang165