Skip to content

[libspirv][remangler] Remangle pointer address space when target's default addrspace is private #18383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: sycl
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libclc/cmake/modules/AddLibclc.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ function(add_libclc_builtin_set)
COMMAND ${CMAKE_COMMAND} -E make_directory ${LIBCLC_LIBRARY_OUTPUT_INTDIR}
COMMAND ${libclc-remangler_exe}
-o "${builtins_remangle_path}"
--triple=${ARG_TRIPLE}
--long-width=${long_width}
--char-signedness=${signedness}
--input-ir=${builtins_lib}
Expand Down
75 changes: 73 additions & 2 deletions libclc/utils/libclc-remangler/LibclcRemangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@
// char, signed char)`), is not defined. The remangler creates a clone
// of the renamed function,`_Z1fxaa`, to this permutation, `_Z1fxca`.
//
// Remangled Pointer Address Space Example:
// If libclc defined a function `f(int *)`, the mangled name is
// `_Z1fPU3AS4i` for a target when generic address space is 4. The
// remangler would rename this function to `_Z1fPi`, to be
// consistent with SYCL device code mangling for the target. If libclc
// defined a function `f(private int *)`, the mangled name is
// `_Z1fPi` when default address space is private. The remangler would
// rename it to `_Z1fPU3AS0i`.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/Mangle.h"
Expand Down Expand Up @@ -62,6 +71,8 @@ enum class SupportedLongWidth { L32, L64 };

static ExitOnError ExitOnErr;

static StringRef TmpSuffix = ".tmp";

// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static llvm::cl::OptionCategory
Expand All @@ -72,6 +83,8 @@ static cl::opt<std::string>
cl::cat(LibCLCRemanglerToolCategory));
static cl::opt<std::string> OutputFilename("o", cl::init("-"),
cl::desc("Output filename"));
static cl::opt<std::string> TargetTriple("triple", cl::init(""),
cl::desc("Device target triple"));
static cl::opt<SupportedLongWidth>
LongWidth("long-width",
cl::values(clEnumValN(SupportedLongWidth::L32, "l32",
Expand Down Expand Up @@ -271,6 +284,7 @@ class Remangler {
: AST(AST), Root(Root), TypeReplacements(TypeReplacements) {
MangleContext.reset(
ItaniumMangleContext::create(*AST, AST->getDiagnostics()));
TargetGenericAddrSpace = AST->getTargetAddressSpace(LangAS::Default);
}

bool hasFailed() { return Failed; }
Expand Down Expand Up @@ -628,6 +642,14 @@ class Remangler {
for (auto I = PossibleKinds.rbegin(); I != PossibleKinds.rend(); ++I) {
switch (I->K) {
case Node::Kind::KPointerType: {
if (TargetGenericAddrSpace != 0) {
if (Res.hasAddressSpace() &&
toTargetAddressSpace(Res.getAddressSpace()) ==
TargetGenericAddrSpace)
Res = AST->removeAddrSpaceQualType(Res);
else if (!Res.hasAddressSpace())
Res = AST->getAddrSpaceQualType(Res, LangAS::opencl_private);
}
Res = AST->getPointerType(Res);
break;
}
Expand Down Expand Up @@ -709,6 +731,8 @@ class Remangler {

std::map<std::string, clang::QualType> NestedNamesQTMap{};
NamespaceDecl *SpvNamespace = nullptr;

unsigned TargetGenericAddrSpace;
};

class TargetTypeReplacements {
Expand Down Expand Up @@ -865,7 +889,7 @@ class LibCLCRemangler : public ASTConsumer {
Remangler R{ASTCtx, FunctionTree,
Replacements.getParameterTypeReplacements()};

std::string const RemangledName = R.remangle();
std::string RemangledName = R.remangle();

if (R.hasFailed())
return false;
Expand All @@ -883,6 +907,16 @@ class LibCLCRemangler : public ASTConsumer {
errs() << "Test run failure!\n";
return false;
}
// When TargetGenericAddrSpace is not 0, there is a possibility that
// RemangledName may already exist. For instance, the function name
// _Z1fPU3AS4i would be remangled to _Z1fPi, which is a valid variant and
// might already be present. Since we cannot alter the name of an existing
// variant function that may not have been processed yet, we append a
// temporary suffix to RemangledName to prevent a name clash. This
// temporary suffix will be removed during the post-processing stage, once
// all functions have been handled.
if (M->getFunction(RemangledName))
RemangledName += TmpSuffix;
Func.setName(RemangledName);

// Make a clone of a suitable function using the old name if there is a
Expand All @@ -894,6 +928,31 @@ class LibCLCRemangler : public ASTConsumer {
return true;
}

// When TargetGenericAddrSpace is not 0, post-processing is necessary after
// all functions have been processed. During this stage, the temporary suffix
// is removed from the remangled name.
void postProcessRemoveTmpSuffix(llvm::Module *M) {
if (TestRun)
return;
for (auto &F : *M) {
StringRef Name = F.getName();
if (!Name.consume_back(TmpSuffix))
continue;
// If a name clash persists, the old function is renamed. For example,
// _Z1fPi is remangled to _Z1fPU3AS0i, and the remangler clones
// _Z1fPU3AS0i to _Z1fPi to preserve the original implementation.
// Subsequently, _Z1fPU3AS4i is remangled to _Z1fPi, and the remangled
// name is temporarily changed to _Z1fPi$TmpSuffix. When attempting to
// revert _Z1fPi$TmpSuffix back to _Z1fPi, a clash occurs because _Z1fPi
// still exists. Since _Z1fPi is no longer useful, it is renamed to
// _Z1fPi.old,
if (auto *Func = M->getFunction(Name))
Func->setName(Twine(Name) + ".old");
// Complete the mangling process from _Z1fPU3AS4i to _Z1fPi.
F.setName(Name);
}
}

void handleModule(llvm::Module *M) {
std::error_code EC;
std::unique_ptr<ToolOutputFile> Out(
Expand All @@ -919,6 +978,7 @@ class LibCLCRemangler : public ASTConsumer {
bool Success = true;
for (auto *Func : FuncList)
Success &= remangleFunction(*Func, M);
postProcessRemoveTmpSuffix(M);
// Only fail after all to give as much context as possible.
if (!Success) {
errs() << "Failed to remangle all mangled functions in module.\n";
Expand Down Expand Up @@ -967,7 +1027,18 @@ int main(int argc, const char **argv) {

// Use a default Compilation DB instead of the build one, as it might contain
// toolchain specific options, not compatible with clang.
FixedCompilationDatabase Compilations(".", std::vector<std::string>());
// Configure the triple to ensure that clang correctly sets up TargetInfo
// which is essential for querying the target address space. This allows the
// remangler to have the same target address space mapping as the mangling
// performed in the SYCL device code compilation.
std::vector<std::string> CommandLine;
CommandLine.push_back("-cc1");
CommandLine.push_back("-triple");
CommandLine.push_back(TargetTriple);
// Workaround error `unknown argument resource-dir`
CommandLine.push_back("-resource-dir");
CommandLine.push_back(".");
FixedCompilationDatabase Compilations(".", CommandLine);
ClangTool Tool(Compilations, ExpectedParser->getSourcePathList());

LibCLCRemanglerActionFactory LRAF{};
Expand Down
Loading