|
| 1 | +/*========================== begin_copyright_notice ============================ |
| 2 | +
|
| 3 | +Copyright (C) 2022 Intel Corporation |
| 4 | +
|
| 5 | +SPDX-License-Identifier: MIT |
| 6 | +
|
| 7 | +============================= end_copyright_notice ===========================*/ |
| 8 | + |
| 9 | +// |
| 10 | +/// GenXFixInvalidFuncName |
| 11 | +/// ------------ |
| 12 | +/// |
| 13 | +/// GenXFixInvalidFuncName is a function pass that replaces all '.' and '$' |
| 14 | +/// characters with '_' in function names generated by llvm in all call |
| 15 | +/// instructions in the current function and in the name of the current function. |
| 16 | +/// It needs to be kept in sync with the same pass on the SPMD side. |
| 17 | +/// |
| 18 | +//===----------------------------------------------------------------------===// |
| 19 | + |
| 20 | +#include "GenX.h" |
| 21 | + |
| 22 | +#include "llvm/IR/Function.h" |
| 23 | +#include "llvm/InitializePasses.h" |
| 24 | +#include "llvm/Pass.h" |
| 25 | +#include "llvm/Support/Debug.h" |
| 26 | + |
| 27 | +#define DEBUG_TYPE "GENX_FIX_INVALID_FUNC_NAMES" |
| 28 | + |
| 29 | +using namespace llvm; |
| 30 | + |
| 31 | +class GenXFixInvalidFuncName : public FunctionPass |
| 32 | +{ |
| 33 | +public: |
| 34 | + static char ID; |
| 35 | + explicit GenXFixInvalidFuncName() : FunctionPass(ID) {} |
| 36 | + llvm::StringRef getPassName() const override { return "Fix Invalid Func Name"; } |
| 37 | + bool runOnFunction(Function& F) override; |
| 38 | +private: |
| 39 | + std::string replaceInvalidCharToUnderline(std::string str); |
| 40 | + bool isSupportedCallingConv(CallingConv::ID callingConv); |
| 41 | + bool changeFuncName(Function& F); |
| 42 | +}; |
| 43 | + |
| 44 | +bool GenXFixInvalidFuncName::runOnFunction(Function& F) { |
| 45 | + bool modified = false; |
| 46 | + if(isSupportedCallingConv(F.getCallingConv())) { |
| 47 | + modified = changeFuncName(F); |
| 48 | + } |
| 49 | + for (Function::iterator fi = F.begin(), fe = F.end(); fi != fe; ++fi) { |
| 50 | + BasicBlock *BB = &*fi; |
| 51 | + for (BasicBlock::iterator bi = BB->begin(), be = BB->end(); bi != be; ++bi) { |
| 52 | + Instruction *Inst = &*bi; |
| 53 | + if (CallInst* callInst = dyn_cast<CallInst>(Inst)) { |
| 54 | + if (isSupportedCallingConv(callInst->getCallingConv())) { |
| 55 | + Function* func = callInst->getCalledFunction(); |
| 56 | + if (func) { |
| 57 | + modified = changeFuncName(*func); |
| 58 | + } |
| 59 | + } |
| 60 | + } |
| 61 | + } |
| 62 | + } |
| 63 | + return modified; |
| 64 | +} |
| 65 | + |
| 66 | +std::string GenXFixInvalidFuncName::replaceInvalidCharToUnderline(std::string str) { |
| 67 | + std::replace_if(str.begin(), str.end(), [](const char c){ return c == '.' || c == '$'; }, '_'); |
| 68 | + return str; |
| 69 | +} |
| 70 | + |
| 71 | +bool GenXFixInvalidFuncName::isSupportedCallingConv(CallingConv::ID callingConv) { |
| 72 | + return callingConv == CallingConv::SPIR_FUNC; |
| 73 | +} |
| 74 | + |
| 75 | +bool GenXFixInvalidFuncName::changeFuncName(Function& F) { |
| 76 | + bool isNameChanged = false; |
| 77 | + std::string original = F.getName().str(); |
| 78 | + std::string changed = replaceInvalidCharToUnderline(original); |
| 79 | + if (original != changed) { |
| 80 | + F.setName(changed); |
| 81 | + isNameChanged = true; |
| 82 | + } |
| 83 | + return isNameChanged; |
| 84 | +} |
| 85 | + |
| 86 | +char GenXFixInvalidFuncName::ID = 0; |
| 87 | +namespace llvm { |
| 88 | +void initializeGenXFixInvalidFuncNamePass(PassRegistry &); |
| 89 | +} |
| 90 | +INITIALIZE_PASS_BEGIN(GenXFixInvalidFuncName, "GenXFixInvalidFuncName", "GenXFixInvalidFuncName", false, false) |
| 91 | +INITIALIZE_PASS_END(GenXFixInvalidFuncName, "GenXFixInvalidFuncName", "GenXFixInvalidFuncName", false, false) |
| 92 | +FunctionPass *llvm::createGenXFixInvalidFuncNamePass() { |
| 93 | + initializeGenXFixInvalidFuncNamePass(*PassRegistry::getPassRegistry()); |
| 94 | + return new GenXFixInvalidFuncName; |
| 95 | +} |
0 commit comments