10b57cec5SDimitry Andric //===-- NVPTXAssignValidGlobalNames.cpp - Assign valid names to globals ---===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Clean up the names of global variables in the module to not contain symbols 100b57cec5SDimitry Andric // that are invalid in PTX. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric // Currently NVPTX, like other backends, relies on generic symbol name 130b57cec5SDimitry Andric // sanitizing done by MC. However, the ptxas assembler is more stringent and 140b57cec5SDimitry Andric // disallows some additional characters in symbol names. This pass makes sure 150b57cec5SDimitry Andric // such names do not reach MC at all. 160b57cec5SDimitry Andric // 170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "NVPTX.h" 200b57cec5SDimitry Andric #include "llvm/IR/Function.h" 210b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 220b57cec5SDimitry Andric #include "llvm/IR/LegacyPassManager.h" 230b57cec5SDimitry Andric #include "llvm/IR/Module.h" 240b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 250b57cec5SDimitry Andric #include <string> 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric using namespace llvm; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric namespace { 300b57cec5SDimitry Andric /// NVPTXAssignValidGlobalNames 310b57cec5SDimitry Andric class NVPTXAssignValidGlobalNames : public ModulePass { 320b57cec5SDimitry Andric public: 330b57cec5SDimitry Andric static char ID; 340b57cec5SDimitry Andric NVPTXAssignValidGlobalNames() : ModulePass(ID) {} 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric bool runOnModule(Module &M) override; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric /// Clean up the name to remove symbols invalid in PTX. 390b57cec5SDimitry Andric std::string cleanUpName(StringRef Name); 400b57cec5SDimitry Andric }; 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric char NVPTXAssignValidGlobalNames::ID = 0; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric namespace llvm { 460b57cec5SDimitry Andric void initializeNVPTXAssignValidGlobalNamesPass(PassRegistry &); 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric INITIALIZE_PASS(NVPTXAssignValidGlobalNames, "nvptx-assign-valid-global-names", 500b57cec5SDimitry Andric "Assign valid PTX names to globals", false, false) 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric bool NVPTXAssignValidGlobalNames::runOnModule(Module &M) { 530b57cec5SDimitry Andric for (GlobalVariable &GV : M.globals()) { 540b57cec5SDimitry Andric // We are only allowed to rename local symbols. 550b57cec5SDimitry Andric if (GV.hasLocalLinkage()) { 560b57cec5SDimitry Andric // setName doesn't do extra work if the name does not change. 570b57cec5SDimitry Andric // Note: this does not create collisions - if setName is asked to set the 580b57cec5SDimitry Andric // name to something that already exists, it adds a proper postfix to 590b57cec5SDimitry Andric // avoid collisions. 600b57cec5SDimitry Andric GV.setName(cleanUpName(GV.getName())); 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric // Do the same for local functions. 650b57cec5SDimitry Andric for (Function &F : M.functions()) 660b57cec5SDimitry Andric if (F.hasLocalLinkage()) 670b57cec5SDimitry Andric F.setName(cleanUpName(F.getName())); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric return true; 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric std::string NVPTXAssignValidGlobalNames::cleanUpName(StringRef Name) { 730b57cec5SDimitry Andric std::string ValidName; 740b57cec5SDimitry Andric raw_string_ostream ValidNameStream(ValidName); 75*4824e7fdSDimitry Andric for (char C : Name) { 760b57cec5SDimitry Andric if (C == '.' || C == '@') { 770b57cec5SDimitry Andric ValidNameStream << "_$_"; 780b57cec5SDimitry Andric } else { 790b57cec5SDimitry Andric ValidNameStream << C; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric return ValidNameStream.str(); 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric ModulePass *llvm::createNVPTXAssignValidGlobalNamesPass() { 870b57cec5SDimitry Andric return new NVPTXAssignValidGlobalNames(); 880b57cec5SDimitry Andric } 89