• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef MAPLEBE_INCLUDE_BE_LOWERER_H
17 #define MAPLEBE_INCLUDE_BE_LOWERER_H
18 /* C++ headers. */
19 #include <vector>
20 #include <unordered_map>
21 #include <utility>
22 #include <cstddef>
23 #include <cstdarg>
24 #include <regex>
25 #include "intrinsics.h" /* For IntrinDesc. This includes 'intrinsic_op.h' as well */
26 #include "becommon.h"
27 #include "cg.h"
28 /* MapleIR headers. */
29 #include "mir_nodes.h"
30 #include "mir_module.h"
31 #include "mir_function.h"
32 #include "mir_lower.h"
33 
34 namespace maplebe {
35 class CGLowerer {
36     enum Option : uint64 {
37         kUndefined = 0,
38         kGenEh = 1ULL << 0,
39         kVerboseCG = 1ULL << 1,
40     };
41 
42     using BuiltinFunctionID = uint32;
43     using OptionFlag = uint64;
44 
45 public:
mirModule(mod)46     CGLowerer(MIRModule &mod, BECommon &common, MIRFunction *func = nullptr) : mirModule(mod), beCommon(common)
47     {
48         SetOptions(kGenEh);
49         mirBuilder = mod.GetMIRBuilder();
50         SetCurrentFunc(func);
51     }
52 
CGLowerer(MIRModule & mod,BECommon & common,bool genEh,bool verboseCG)53     CGLowerer(MIRModule &mod, BECommon &common, bool genEh, bool verboseCG) : mirModule(mod), beCommon(common)
54     {
55         OptionFlag option = 0;
56         if (genEh) {
57             option |= kGenEh;
58         }
59         if (verboseCG) {
60             option |= kVerboseCG;
61         }
62         SetOptions(option);
63         mirBuilder = mod.GetMIRBuilder();
64         SetCurrentFunc(nullptr);
65     }
66 
~CGLowerer()67     ~CGLowerer()
68     {
69         mirBuilder = nullptr;
70         currentBlock = nullptr;
71     }
72 
73     void LowerFunc(MIRFunction &func);
74 
75     StmtNode *LowerDefaultIntrinsicCall(IntrinsiccallNode &intrinCall, MIRSymbol &st, MIRFunction &fn);
76 
77     StmtNode *LowerIntrinsiccall(IntrinsiccallNode &intrinCall, BlockNode &);
78 
GetCurrentFunc()79     MIRFunction *GetCurrentFunc() const
80     {
81         return mirModule.CurFunction();
82     }
83 
84     BaseNode *LowerExpr(BaseNode &, BaseNode &, BlockNode &);
85 
86     BaseNode *LowerDread(DreadNode &dread, const BlockNode &block);
87 
LowerIread(IreadNode & iread)88     BaseNode *LowerIread(IreadNode &iread)
89     {
90         /* use PTY_u8 for boolean type in dread/iread */
91         if (iread.GetPrimType() == PTY_u1) {
92             iread.SetPrimType(PTY_u8);
93         }
94         CHECK_FATAL(iread.GetFieldID() == 0, "fieldID must be 0");
95         return &iread;
96     }
97 
98     BaseNode *LowerCastExpr(BaseNode &expr);
99 
100     BaseNode *ExtractSymbolAddress(const StIdx &stIdx);
101     BaseNode *LowerDreadToThreadLocal(BaseNode &expr, const BlockNode &block);
102     StmtNode *LowerDassignToThreadLocal(StmtNode &stmt, const BlockNode &block);
103 
104     void LowerDassign(DassignNode &dassign, BlockNode &block);
105 
106     void LowerIassign(IassignNode &iassign, BlockNode &block);
107 
108     void LowerRegassign(RegassignNode &regAssign, BlockNode &block);
109 
LowerAddrof(AddrofNode & addrof)110     BaseNode *LowerAddrof(AddrofNode &addrof) const
111     {
112         return &addrof;
113     }
114 
115     DassignNode *SaveReturnValueInLocal(StIdx, uint16);
116     BaseNode *NeedRetypeWhenLowerCallAssigned(PrimType pType);
117     void LowerCallStmt(StmtNode &, StmtNode *&, BlockNode &, MIRType *retty = nullptr, bool uselvar = false,
118                        bool isIntrinAssign = false);
119     BlockNode *LowerIntrinsiccallAassignedToAssignStmt(IntrinsiccallNode &intrinsicCall);
120     BlockNode *LowerCallAssignedStmt(StmtNode &stmt, bool uselvar = false);
121     /* Intrinsiccall will processe return and vector as a call separately.
122      * To be able to handle them in a unified manner, we lower intrinsiccall to Intrinsicsicop.
123      */
124     BlockNode *LowerIntrinsiccallToIntrinsicop(StmtNode &stmt);
125 
126     void LowerStmt(StmtNode &stmt, BlockNode &block);
127 
128     void LowerSwitchOpnd(StmtNode &stmt, BlockNode &block);
129 
130     BlockNode *LowerBlock(BlockNode &block);
131 
132 #if TARGARM32 || TARGAARCH64 || TARGRISCV64 || TARGX86_64
133     BlockNode *LowerReturnStructUsingFakeParm(NaryStmtNode &retNode);
134 #endif
135     BlockNode *LowerReturn(NaryStmtNode &retNode);
136     void LowerEntry(MIRFunction &func);
137 
138     void CleanupBranches(MIRFunction &func) const;
139 
140     void LowerTypePtr(BaseNode &expr) const;
141 
142     /* A pseudo register refers to a symbol when DreadNode is converted to RegreadNode. */
GetSymbolReferredToByPseudoRegister(PregIdx regNO)143     StIdx GetSymbolReferredToByPseudoRegister(PregIdx regNO) const
144     {
145         (void)regNO;
146         return StIdx();
147     }
148 
SetOptions(OptionFlag option)149     void SetOptions(OptionFlag option)
150     {
151         options = option;
152     }
153 
SetCheckLoadStore(bool value)154     void SetCheckLoadStore(bool value)
155     {
156         checkLoadStore = value;
157     }
158 
159     /* if it defines a built-in to use for the given intrinsic, return the name. otherwise, return nullptr */
160     PUIdx GetBuiltinToUse(BuiltinFunctionID id) const;
161 
162     MIRModule &mirModule;
163     BECommon &beCommon;
164     BlockNode *currentBlock = nullptr; /* current block for lowered statements to be inserted to */
165     bool checkLoadStore = false;
166     int64 seed = 0;
167 
168     static constexpr PUIdx kFuncNotFound = PUIdx(-1);
169     static constexpr int kThreeDimArray = 3;
170     static constexpr int kNodeThirdOpnd = 2;
171     static constexpr int kMCCSyncEnterFast0 = 0;
172     static constexpr int kMCCSyncEnterFast1 = 1;
173     static constexpr int kMCCSyncEnterFast2 = 2;
174     static constexpr int kMCCSyncEnterFast3 = 3;
175 
176 protected:
177     /*
178      * true if the lower level (e.g. mplcg) can handle the intrinsic directly.
179      * For example, the INTRN_MPL_ATOMIC_EXCHANGE_PTR can be directly handled by mplcg,
180      * and generate machine code sequences not containing any function calls.
181      * Such intrinsics will bypass the lowering of "assigned",
182      * and let mplcg handle the intrinsic results which are not return values.
183      */
184     bool IsIntrinsicCallHandledAtLowerLevel(MIRIntrinsicID intrinsic) const;
185 
186 private:
SetCurrentFunc(MIRFunction * func)187     void SetCurrentFunc(MIRFunction *func)
188     {
189         mirModule.SetCurFunction(func);
190     }
191 
ShouldAddAdditionalComment()192     bool ShouldAddAdditionalComment() const
193     {
194         return (options & kVerboseCG) != 0;
195     }
196 
197     LabelIdx GetLabelIdx(MIRFunction &curFunc) const;
198     StmtNode *GenCallNode(const StmtNode &stmt, PUIdx &funcCalled, CallNode &origCall);
199     StmtNode *GenIntrinsiccallNode(const StmtNode &stmt, PUIdx &funcCalled, bool &handledAtLowerLevel,
200                                    IntrinsiccallNode &origCall);
201     StmtNode *GenIcallNode(PUIdx &funcCalled, IcallNode &origCall);
202     BlockNode *GenBlockNode(StmtNode &newCall, const CallReturnVector &p2nRets, const Opcode &opcode,
203                             const PUIdx &funcCalled, bool handledAtLowerLevel, bool uselvar);
204 
205     OptionFlag options = 0;
206     bool needBranchCleanup = false;
207 
208     static std::vector<std::pair<BuiltinFunctionID, PUIdx>> builtinFuncIDs;
209     MIRBuilder *mirBuilder = nullptr;
210     uint32 labelIdx = 0;
211 };
212 } /* namespace maplebe */
213 
214 #endif /* MAPLEBE_INCLUDE_BE_LOWERER_H */