================
@@ -6,24 +6,209 @@
 //
 
//===----------------------------------------------------------------------===//
 //
-// This file implements offloading to CUDA devices.
+// This file implements offloading to HIP and CUDA devices.
 //
 
//===----------------------------------------------------------------------===//
 
 #include "DeviceOffload.h"
+#include "IncrementalAction.h"
 
 #include "clang/Basic/TargetOptions.h"
-#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/CodeGen/BackendUtil.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Driver/OffloadBundler.h"
 #include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
 #include "clang/Interpreter/PartialTranslationUnit.h"
 
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/TargetParser/AMDGPUTargetParser.h"
+#include "llvm/TargetParser/Host.h"
 
 namespace clang {
 
+static llvm::Expected<llvm::TargetMachine *>
+getOrCreateTargetMachine(std::unique_ptr<llvm::TargetMachine> &Cache,
+                         llvm::Module &M, llvm::StringRef CPU) {
+  if (!Cache) {
+    std::string Error;
+    const llvm::Target *Target =
+        llvm::TargetRegistry::lookupTarget(M.getTargetTriple(), Error);
+    if (!Target)
+      return llvm::make_error<llvm::StringError>(std::move(Error),
+                                                 std::error_code());
+    llvm::TargetOptions TO = llvm::TargetOptions();
+    Cache.reset(Target->createTargetMachine(M.getTargetTriple(), CPU, "", TO,
+                                            llvm::Reloc::Model::PIC_));
+  }
+  M.setDataLayout(Cache->createDataLayout());
+  return Cache.get();
+}
+
+IncrementalHIPDeviceParser::IncrementalHIPDeviceParser(
+    CompilerInstance &DeviceInstance, CompilerInstance &HostInstance,
+    IncrementalAction *DeviceAct,
+    llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS,
+    llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs)
+    : IncrementalParser(DeviceInstance, DeviceAct, Err, PTUs),
+      DeviceCI(DeviceInstance), VFS(FS),
+      CodeGenOpts(HostInstance.getCodeGenOpts()),
+      TargetOpts(DeviceInstance.getTargetOpts()) {
+  if (Err)
+    return;
+  StringRef Arch = TargetOpts.CPU;
+  if (!Arch.starts_with("gfx")) {
+    Err = llvm::joinErrors(std::move(Err), llvm::make_error<llvm::StringError>(
+                                               "Invalid HIP architecture",
+                                               
llvm::inconvertibleErrorCode()));
+    return;
+  }
+}
+
+llvm::Expected<TranslationUnitDecl *>
+IncrementalHIPDeviceParser::Parse(llvm::StringRef Input) {
+  if (FrontendAction *WrappedAct = Act->getWrapped())
+    if (WrappedAct->hasIRSupport())
+      static_cast<CodeGenAction *>(WrappedAct)->reloadLinkModules(DeviceCI);
+
+  return IncrementalParser::Parse(Input);
+}
+
+llvm::Expected<llvm::StringRef> IncrementalHIPDeviceParser::GenerateHSACO() {
+  auto &PTU = PTUs.back();
+
+  CodeGenOptions CodeGenOptsForObj = DeviceCI.getCodeGenOpts();
+  CodeGenOptsForObj.DisableLLVMPasses = true;
+
+  llvm::SmallVector<char, 0> Object;
+  auto ObjOS = std::make_unique<llvm::raw_svector_ostream>(Object);
+  clang::emitBackendOutput(
+      DeviceCI, CodeGenOptsForObj, DeviceCI.getTarget().getDataLayoutString(),
+      PTU.TheModule.get(), Backend_EmitObj, DeviceCI.getVirtualFileSystemPtr(),
+      std::move(ObjOS));
+
+  std::string Exe = llvm::sys::fs::getMainExecutable(nullptr, nullptr);
+  llvm::StringRef ExeDir = llvm::sys::path::parent_path(Exe);
+  llvm::ErrorOr<std::string> LLDPath =
+      llvm::sys::findProgramByName("ld.lld", {ExeDir});
+  if (!LLDPath)
+    LLDPath = llvm::sys::findProgramByName("ld.lld");
+  if (!LLDPath)
+    return llvm::make_error<llvm::StringError>(
+        "Could not find ld.lld next to the executable or on PATH.",
+        llvm::inconvertibleErrorCode());
+
+  int ObjFD = -1;
+  llvm::SmallString<128> ObjFile;
+  if (llvm::sys::fs::createTemporaryFile("kernel", "o", ObjFD, ObjFile))
+    return llvm::make_error<llvm::StringError>(
+        "Failed to create a temporary object file.",
+        llvm::inconvertibleErrorCode());
+  llvm::FileRemover ObjRemover(ObjFile);
+  {
+    llvm::raw_fd_ostream OS(ObjFD, /*shouldClose=*/true);
+    OS << llvm::StringRef(Object.data(), Object.size());
+  }
+
+  llvm::SmallString<128> HsacoFile;
+  if (llvm::sys::fs::createTemporaryFile("kernel", "hsaco", HsacoFile))
+    return llvm::make_error<llvm::StringError>(
+        "Failed to create a temporary code object file.",
+        llvm::inconvertibleErrorCode());
+  llvm::FileRemover HsacoRemover(HsacoFile);
+
+  llvm::StringRef Args[] = {"ld.lld", "-shared", "--no-undefined",
+                            ObjFile,  "-o",      HsacoFile};
+  if (llvm::sys::ExecuteAndWait(*LLDPath, Args) != 0)
+    return llvm::make_error<llvm::StringError>("ld.lld invocation failed.",
+                                               llvm::inconvertibleErrorCode());
+
+  auto HsacoBuf = llvm::MemoryBuffer::getFile(HsacoFile, /*IsText=*/false);
+  if (!HsacoBuf)
+    return llvm::make_error<llvm::StringError>(
+        "Failed to read the code object.", llvm::inconvertibleErrorCode());
+
+  llvm::StringRef Buffer = (*HsacoBuf)->getBuffer();
+  HSACOContent.assign(Buffer.begin(), Buffer.end());
+  return llvm::StringRef(HSACOContent.data(), HSACOContent.size());
+}
+
+llvm::Error IncrementalHIPDeviceParser::GenerateOffloadBundle() {
+  static constexpr unsigned CodeObjectAlign = 4096;
+
+  const PartialTranslationUnit &PTU = PTUs.back();
+
+  llvm::SmallString<128> HostFile;
+  if (llvm::sys::fs::createTemporaryFile("hip-host", "", HostFile))
+    return llvm::make_error<llvm::StringError>(
+        "Failed to create a temporary host bundle input.",
+        llvm::inconvertibleErrorCode());
+  llvm::FileRemover HostRemover(HostFile);
+
+  llvm::SmallString<128> DeviceFile;
+  int DeviceFD = -1;
+  if (llvm::sys::fs::createTemporaryFile("hip-device", "hsaco", DeviceFD,
+                                         DeviceFile))
+    return llvm::make_error<llvm::StringError>(
+        "Failed to create a temporary code object file.",
+        llvm::inconvertibleErrorCode());
+  llvm::FileRemover DeviceRemover(DeviceFile);
+  {
+    llvm::raw_fd_ostream OS(DeviceFD, /*shouldClose=*/true);
+    OS << llvm::StringRef(HSACOContent.data(), HSACOContent.size());
+  }
+
+  llvm::SmallString<128> BundleFile;
+  if (llvm::sys::fs::createTemporaryFile("hip-bundle", "hipfb", BundleFile))
+    return llvm::make_error<llvm::StringError>(
+        "Failed to create a temporary offload bundle file.",
+        llvm::inconvertibleErrorCode());
+  llvm::FileRemover BundleRemover(BundleFile);
+
+  std::string TargetID = llvm::AMDGPU::TargetID::createFromSubtargetFeatures(
+                             DeviceCI.getTarget().getTriple(), TargetOpts.CPU,
+                             llvm::join(TargetOpts.Features, ","))
+                             .getCanonicalTargetIDString();
+
+  std::string HostTriple = "host-" + llvm::sys::getProcessTriple() + "-";
+  std::string DeviceTriple =
+      "hip-" + PTU.TheModule->getTargetTriple().str() + "--" + TargetID;
----------------
AdityaSinha149 wrote:

i have created a new PR #225049 which moves the `normalizeForBundler ` function 
from `HIPUtility.cpp` to `OffloadBundler` so that it would be accessible  in 
`DeviceOffload.cpp`. Please review that and after merging it, I will update 
this code to use that function.

https://github.com/llvm/llvm-project/pull/218337
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to