1+ /* ========================== begin_copyright_notice ============================
2+
3+ Copyright (C) 2021 Intel Corporation
4+
5+ SPDX-License-Identifier: MIT
6+
7+ ============================= end_copyright_notice ===========================*/
8+
9+ #include " Compiler/FixInvalidFuncNamePass.hpp"
10+ #include " IGCPassSupport.h"
11+ #include " GenISAIntrinsics/GenIntrinsicInst.h"
12+ #include " AdaptorCommon/ImplicitArgs.hpp"
13+ #include " common/LLVMWarningsPush.hpp"
14+ #include " llvm/IR/Function.h"
15+ #include " common/LLVMWarningsPop.hpp"
16+
17+ using namespace llvm ;
18+ using namespace IGC ;
19+
20+
21+ // LLVM sometimes creates the function with characters which are incorrect for vISA (e.g. with ".")
22+ // Here we check the LLVM names and replace incorrect characters for vISA to "_"
23+ // We need to check call instruction. If contains invalid char, we change func name called by this instruction
24+ class FixInvalidFuncName : public FunctionPass
25+ {
26+ public:
27+ FixInvalidFuncName () : FunctionPass(ID) {}
28+ virtual bool runOnFunction (Function& F) override ;
29+ virtual llvm::StringRef getPassName () const override
30+ {
31+ return " Fix Invalid Func Name" ;
32+ }
33+ static char ID;
34+
35+ private:
36+ // Check and change call instruction if contains invalid char
37+ bool changeCallInstr (Function& F);
38+ // Change func name. This changing update all the references inside the same module
39+ bool changeInvalidFuncName (Function& F);
40+ // Replace invalid char to underscore
41+ std::string replaceInvalidCharToUnderline (std::string str);
42+ };
43+
44+ char FixInvalidFuncName::ID = 0 ;
45+
46+ bool FixInvalidFuncName::runOnFunction (Function& F)
47+ {
48+ return changeCallInstr (F);
49+ }
50+
51+ bool FixInvalidFuncName::changeInvalidFuncName (Function& F)
52+ {
53+ std::string str = F.getName ().str ();
54+ std::string str_changed = replaceInvalidCharToUnderline (str);
55+ if (str != str_changed)
56+ {
57+ F.setName (str_changed);
58+ return true ;
59+ }
60+ return false ;
61+ }
62+
63+ bool FixInvalidFuncName::changeCallInstr (Function& F)
64+ {
65+ for (inst_iterator I = inst_begin (F), E = inst_end (F); I != E; ++I)
66+ {
67+ if (CallInst* callInst = dyn_cast<CallInst>(&(*I)))
68+ {
69+ if (callInst->getCallingConv () == CallingConv::SPIR_FUNC)
70+ {
71+ auto calledFuncName = callInst->getCalledFunction ();
72+ if (calledFuncName)
73+ {
74+ StringRef funcName = calledFuncName->getName ();
75+ std::string str = funcName.str ();
76+ std::string str_changed = replaceInvalidCharToUnderline (str);
77+ if (str != str_changed)
78+ {
79+ Function* func = callInst->getCalledFunction ();
80+ if (func)
81+ {
82+ return changeInvalidFuncName (*func);
83+ }
84+ }
85+ }
86+ }
87+ }
88+ }
89+ return false ;
90+ }
91+
92+ std::string FixInvalidFuncName::replaceInvalidCharToUnderline (std::string str)
93+ {
94+ std::replace (str.begin (), str.end (), ' .' , ' _' );
95+ std::replace (str.begin (), str.end (), ' $' , ' _' );
96+ return str;
97+ }
98+
99+ namespace IGC
100+ {
101+ #define PASS_FLAG " fix-invalid-func-name"
102+ #define PASS_DESCRIPTION " Fix Invalid Func Name Pass"
103+ #define PASS_CFG_ONLY false
104+ #define PASS_ANALYSIS true
105+ IGC_INITIALIZE_PASS_BEGIN (FixInvalidFuncName, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
106+ IGC_INITIALIZE_PASS_END (FixInvalidFuncName, PASS_FLAG, PASS_DESCRIPTION, PASS_CFG_ONLY, PASS_ANALYSIS)
107+
108+ FunctionPass* createFixInvalidFuncNamePass ()
109+ {
110+ return new FixInvalidFuncName ();
111+ }
112+ }
0 commit comments