1//===-- NVPTXAssignValidGlobalNames.cpp - Assign valid names to globals ---===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Clean up the names of global variables in the module to not contain symbols
10// that are invalid in PTX.
11//
12// Currently NVPTX, like other backends, relies on generic symbol name
13// sanitizing done by MC. However, the ptxas assembler is more stringent and
14// disallows some additional characters in symbol names. This pass makes sure
15// such names do not reach MC at all.
16//
17//===----------------------------------------------------------------------===//
18
19#include "NVPTX.h"
20#include "NVPTXUtilities.h"
21#include "llvm/IR/Function.h"
22#include "llvm/IR/GlobalVariable.h"
23#include "llvm/IR/LegacyPassManager.h"
24#include "llvm/IR/Module.h"
25
26using namespace llvm;
27
28/// Give \p GV a name that is a valid PTX identifier, returning whether it had
29/// to be renamed. Invalid names are rare, so checking first lets the pass
30/// report accurately that it left the module alone.
31///
32/// Note: this does not create collisions - if setName is asked to set the name
33/// to something that already exists, it adds a proper postfix to avoid
34/// collisions.
35static bool assignValidName(GlobalValue &GV) {
36 std::string ValidName = NVPTX::getValidPTXIdentifier(Name: GV.getName());
37 if (ValidName == GV.getName())
38 return false;
39 GV.setName(ValidName);
40 return true;
41}
42
43static bool assignValidGlobalNames(Module &M) {
44 bool Changed = false;
45 for (GlobalVariable &GV : M.globals()) {
46 // We are only allowed to rename symbols that are not externally linked by
47 // name
48 // - local symbols, as all references will be renamed
49 // - .extern .shared symbols, as they're the same regardless of name
50 if (GV.hasLocalLinkage() ||
51 (GV.hasExternalLinkage() &&
52 GV.getAddressSpace() == NVPTX::AddressSpace::Shared))
53 Changed |= assignValidName(GV);
54 }
55
56 // Do the same for local functions.
57 for (Function &F : M.functions())
58 if (F.hasLocalLinkage())
59 Changed |= assignValidName(GV&: F);
60
61 return Changed;
62}
63
64namespace {
65/// NVPTXAssignValidGlobalNamesLegacyPass
66class NVPTXAssignValidGlobalNamesLegacyPass : public ModulePass {
67public:
68 static char ID;
69 NVPTXAssignValidGlobalNamesLegacyPass() : ModulePass(ID) {}
70
71 bool runOnModule(Module &M) override { return assignValidGlobalNames(M); }
72};
73} // namespace
74
75char NVPTXAssignValidGlobalNamesLegacyPass::ID = 0;
76
77INITIALIZE_PASS(NVPTXAssignValidGlobalNamesLegacyPass,
78 "nvptx-assign-valid-global-names",
79 "Assign valid PTX names to globals", false, false)
80
81ModulePass *llvm::createNVPTXAssignValidGlobalNamesLegacyPass() {
82 return new NVPTXAssignValidGlobalNamesLegacyPass();
83}
84
85PreservedAnalyses
86NVPTXAssignValidGlobalNamesPass::run(Module &M, ModuleAnalysisManager &MAM) {
87 if (!assignValidGlobalNames(M))
88 return PreservedAnalyses::all();
89 return PreservedAnalyses::none().preserveSet<CFGAnalyses>();
90}
91