mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 18:26:05 +00:00

This reverts commit aa495214b39d475bab24b468de7a7c676ce9e366. As discussed in https://github.com/llvm/llvm-project/issues/53475 this patch allows for using LLD-as-a-lib. It also lets clients link only the drivers that they want (see unit tests). This also adds the unit test infra as in the other LLVM projects. Among the test coverage, I've added the original issue from @krzysz00, see: https://github.com/ROCmSoftwarePlatform/D108850-lld-bug-reproduction Important note: this doesn't allow (yet) linking in parallel. This will come a bit later hopefully, in subsequent patches, for COFF at least. Differential revision: https://reviews.llvm.org/D119049
75 lines
2.8 KiB
C++
75 lines
2.8 KiB
C++
//===- ROCm.cpp -------------------------------------------------*- C++ -*-===//
|
|
//
|
|
// This file is licensed 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// The purpose of this test is to showcase a more singular usage of LLD as a
|
|
// library, where only one LLD driver is being used (and linked in the target
|
|
// application). We also expect that linking twice the same object files
|
|
// would yield a successfull result. When used as library, LLD always cleans its
|
|
// internal memory context after each linker call.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// When this flag is on, we actually need the MinGW driver library, not the
|
|
// ELF one. Here our test only covers the case where the ELF driver is linked
|
|
// into the unit test binary.
|
|
#ifndef LLD_DEFAULT_LD_LLD_IS_MINGW
|
|
|
|
#include "lld/Common/Driver.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/FileUtilities.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "gmock/gmock.h"
|
|
#include <algorithm>
|
|
|
|
static std::string expand(const char *path) {
|
|
if (!llvm::StringRef(path).contains("%"))
|
|
return std::string(path);
|
|
|
|
llvm::SmallString<256> thisPath;
|
|
thisPath.append(getenv("LLD_SRC_DIR"));
|
|
llvm::sys::path::append(thisPath, "unittests", "AsLibELF");
|
|
|
|
std::string expanded(path);
|
|
expanded.replace(expanded.find("%S"), 2, thisPath.data(), thisPath.size());
|
|
return expanded;
|
|
}
|
|
|
|
LLD_HAS_DRIVER(elf)
|
|
|
|
static bool lldInvoke(const char *inPath, const char *outPath) {
|
|
std::vector<const char *> args{"ld.lld", "-shared", inPath, "-o", outPath};
|
|
lld::Result s = lld::lldMain(args, llvm::outs(), llvm::errs(),
|
|
{{lld::Gnu, &lld::elf::link}});
|
|
return !s.retCode && s.canRunAgain;
|
|
}
|
|
|
|
static bool runLinker(const char *path) {
|
|
// Create a temp file for HSA code object.
|
|
int tempHsacoFD = -1;
|
|
llvm::SmallString<128> tempHsacoFilename;
|
|
if (llvm::sys::fs::createTemporaryFile("kernel", "hsaco", tempHsacoFD,
|
|
tempHsacoFilename)) {
|
|
return false;
|
|
}
|
|
llvm::FileRemover cleanupHsaco(tempHsacoFilename);
|
|
// Invoke lld. Expect a true return value from lld.
|
|
std::string expandedPath = expand(path);
|
|
if (!lldInvoke(expandedPath.data(), tempHsacoFilename.c_str())) {
|
|
llvm::errs() << "Failed to link: " << expandedPath << "\n";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
TEST(AsLib, ROCm) {
|
|
EXPECT_TRUE(runLinker("%S/Inputs/kernel1.o"));
|
|
EXPECT_TRUE(runLinker("%S/Inputs/kernel2.o"));
|
|
EXPECT_TRUE(runLinker("%S/Inputs/kernel1.o"));
|
|
EXPECT_TRUE(runLinker("%S/Inputs/kernel2.o"));
|
|
}
|
|
#endif
|