• 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_CG_CFI_H
17 #define MAPLEBE_INCLUDE_CG_CFI_H
18 
19 #include "insn.h"
20 #include "mempool_allocator.h"
21 #include "mir_symbol.h"
22 #include "operand.h"
23 #include "common_utils.h"
24 
25 /*
26  * Reference:
27  * GNU Binutils. AS documentation
28  * https://sourceware.org/binutils/docs-2.28/as/index.html
29  *
30  * CFI blog
31  * https://www.imperialviolet.org/2017/01/18/cfi.html
32  *
33  * System V Application Binary Interface
34  * AMD64 Architecture Processor Supplement. Draft Version 0.99.7
35  * https://www.uclibc.org/docs/psABI-x86_64.pdf $ 3.7 Figure 3.36
36  * (RBP->6, RSP->7)
37  *
38  * System V Application Binary Interface
39  * Inte386 Architecture Processor Supplement. Version 1.0
40  * https://www.uclibc.org/docs/psABI-i386.pdf $ 2.5 Table 2.14
41  * (EBP->5, ESP->4)
42  *
43  * DWARF for ARM Architecture (ARM IHI 0040B)
44  * infocenter.arm.com/help/topic/com.arm.doc.ihi0040b/IHI0040B_aadwarf.pdf
45  * $ 3.1 Table 1
46  * (0-15 -> R0-R15)
47  */
48 namespace cfi {
49 using namespace maple;
50 
51 enum CfiOpcode : uint8 {
52 #define CFI_DEFINE(k, sub, n, o0, o1, o2) OP_CFI_##k##sub,
53 #define ARM_DIRECTIVES_DEFINE(k, sub, n, o0, o1, o2) OP_ARM_DIRECTIVES_##k##sub,
54 #include "cfi.def"
55 #undef CFI_DEFINE
56 #undef ARM_DIRECTIVES_DEFINE
57     kOpCfiLast
58 };
59 
60 class CfiInsn : public maplebe::Insn {
61 public:
CfiInsn(MemPool & memPool,maplebe::MOperator op)62     CfiInsn(MemPool &memPool, maplebe::MOperator op) : Insn(memPool, op) {}
63 
CfiInsn(const CfiInsn & other)64     CfiInsn(const CfiInsn &other) : maplebe::Insn(other) {}
65 
CfiInsn(MemPool & memPool,maplebe::MOperator op,maplebe::Operand & opnd0)66     CfiInsn(MemPool &memPool, maplebe::MOperator op, maplebe::Operand &opnd0) : Insn(memPool, op, opnd0) {}
67 
CfiInsn(MemPool & memPool,maplebe::MOperator op,maplebe::Operand & opnd0,maplebe::Operand & opnd1)68     CfiInsn(MemPool &memPool, maplebe::MOperator op, maplebe::Operand &opnd0, maplebe::Operand &opnd1)
69         : Insn(memPool, op, opnd0, opnd1)
70     {
71     }
72 
CfiInsn(MemPool & memPool,maplebe::MOperator op,maplebe::Operand & opnd0,maplebe::Operand & opnd1,maplebe::Operand & opnd2)73     CfiInsn(MemPool &memPool, maplebe::MOperator op, maplebe::Operand &opnd0, maplebe::Operand &opnd1,
74             maplebe::Operand &opnd2)
75         : Insn(memPool, op, opnd0, opnd1, opnd2)
76     {
77     }
78 
79     ~CfiInsn() = default;
80 
CloneTree(MapleAllocator & allocator)81     CfiInsn *CloneTree(MapleAllocator &allocator) const override
82     {
83         auto *insn = allocator.GetMemPool()->New<CfiInsn>(*this);
84         insn->DeepClone(*this, allocator);
85         return insn;
86     }
87 
IsMachineInstruction()88     bool IsMachineInstruction() const override
89     {
90         return false;
91     }
92 
93     void Dump() const override;
94 
95     bool CheckMD() const override;
96 
IsCfiInsn()97     bool IsCfiInsn() const override
98     {
99         return true;
100     }
101 
IsTargetInsn()102     bool IsTargetInsn() const override
103     {
104         return false;
105     }
106 
IsRegDefined(maplebe::regno_t regNO)107     bool IsRegDefined(maplebe::regno_t regNO) const override
108     {
109         CHECK_FATAL(false, "cfi do not def regs");
110         return false;
111     }
112 
GetDefRegs()113     std::set<uint32> GetDefRegs() const override
114     {
115         CHECK_FATAL(false, "cfi do not def regs");
116         return std::set<uint32>();
117     }
118 
GetBothDefUseOpnd()119     uint32 GetBothDefUseOpnd() const override
120     {
121         return maplebe::kInsnMaxOpnd;
122     }
123 
124 private:
125     CfiInsn &operator=(const CfiInsn &);
126 };
127 
128 class RegOperand : public maplebe::OperandVisitable<RegOperand> {
129 public:
RegOperand(uint32 no,uint32 size)130     RegOperand(uint32 no, uint32 size) : OperandVisitable(kOpdRegister, size), regNO(no) {}
131 
132     ~RegOperand() = default;
133     using OperandVisitable<RegOperand>::OperandVisitable;
134 
GetRegisterNO()135     uint32 GetRegisterNO() const
136     {
137         return regNO;
138     }
139 
CloneTree(MapleAllocator & allocator)140     RegOperand *CloneTree(MapleAllocator &allocator) const override
141     {
142         return allocator.GetMemPool()->New<RegOperand>(*this);
143     }
144 
Clone(MemPool & memPool)145     Operand *Clone(MemPool &memPool) const override
146     {
147         Operand *opnd = memPool.Clone<RegOperand>(*this);
148         return opnd;
149     }
150 
151     void Dump() const override;
152 
Less(const Operand & right)153     bool Less(const Operand &right) const override
154     {
155         (void)right;
156         return false;
157     }
158 
159 private:
160     uint32 regNO;
161 };
162 
163 class ImmOperand : public maplebe::OperandVisitable<ImmOperand> {
164 public:
ImmOperand(int64 val,uint32 size)165     ImmOperand(int64 val, uint32 size) : OperandVisitable(kOpdImmediate, size), val(val) {}
166 
167     ~ImmOperand() = default;
168     using OperandVisitable<ImmOperand>::OperandVisitable;
169 
CloneTree(MapleAllocator & allocator)170     ImmOperand *CloneTree(MapleAllocator &allocator) const override
171     {
172         // const MIRSymbol is not changed in cg, so we can do shallow copy
173         return allocator.GetMemPool()->New<ImmOperand>(*this);
174     }
175 
Clone(MemPool & memPool)176     Operand *Clone(MemPool &memPool) const override
177     {
178         Operand *opnd = memPool.Clone<ImmOperand>(*this);
179         return opnd;
180     }
GetValue()181     int64 GetValue() const
182     {
183         return val;
184     }
185 
186     void Dump() const override;
187 
Less(const Operand & right)188     bool Less(const Operand &right) const override
189     {
190         (void)right;
191         return false;
192     }
193 
194 private:
195     int64 val;
196 };
197 
198 class SymbolOperand : public maplebe::OperandVisitable<SymbolOperand> {
199 public:
SymbolOperand(maple::MIRSymbol & mirSymbol,uint8 size)200     SymbolOperand(maple::MIRSymbol &mirSymbol, uint8 size) : OperandVisitable(kOpdStImmediate, size), symbol(&mirSymbol)
201     {
202     }
203     ~SymbolOperand() = default;
204     using OperandVisitable<SymbolOperand>::OperandVisitable;
205 
CloneTree(MapleAllocator & allocator)206     SymbolOperand *CloneTree(MapleAllocator &allocator) const override
207     {
208         // const MIRSymbol is not changed in cg, so we can do shallow copy
209         return allocator.GetMemPool()->New<SymbolOperand>(*this);
210     }
211 
Clone(MemPool & memPool)212     Operand *Clone(MemPool &memPool) const override
213     {
214         Operand *opnd = memPool.Clone<SymbolOperand>(*this);
215         return opnd;
216     }
217 
Less(const Operand & right)218     bool Less(const Operand &right) const override
219     {
220         (void)right;
221         return false;
222     }
223 
Dump()224     void Dump() const override
225     {
226         LogInfo::MapleLogger() << "symbol is  : " << symbol->GetName();
227     }
228 
229 private:
230     maple::MIRSymbol *symbol;
231 };
232 
233 class StrOperand : public maplebe::OperandVisitable<StrOperand> {
234 public:
StrOperand(const std::string & str,MemPool & memPool)235     StrOperand(const std::string &str, MemPool &memPool) : OperandVisitable(kOpdString, 0), str(str, &memPool) {}
236 
237     ~StrOperand() = default;
238     using OperandVisitable<StrOperand>::OperandVisitable;
239 
CloneTree(MapleAllocator & allocator)240     StrOperand *CloneTree(MapleAllocator &allocator) const override
241     {
242         return allocator.GetMemPool()->New<StrOperand>(*this);
243     }
244 
Clone(MemPool & memPool)245     Operand *Clone(MemPool &memPool) const override
246     {
247         Operand *opnd = memPool.Clone<StrOperand>(*this);
248         return opnd;
249     }
250 
Less(const Operand & right)251     bool Less(const Operand &right) const override
252     {
253         (void)right;
254         return false;
255     }
256 
GetStr()257     const MapleString &GetStr() const
258     {
259         return str;
260     }
261 
262     void Dump() const override;
263 
264 private:
265     const MapleString str;
266 };
267 
268 class LabelOperand : public maplebe::OperandVisitable<LabelOperand> {
269 public:
LabelOperand(const std::string & parent,LabelIdx labIdx,MemPool & memPool)270     LabelOperand(const std::string &parent, LabelIdx labIdx, MemPool &memPool)
271         : OperandVisitable(kOpdBBAddress, 0), parentFunc(parent, &memPool), labelIndex(labIdx)
272     {
273     }
274 
275     ~LabelOperand() = default;
276     using OperandVisitable<LabelOperand>::OperandVisitable;
277 
CloneTree(MapleAllocator & allocator)278     LabelOperand *CloneTree(MapleAllocator &allocator) const override
279     {
280         return allocator.GetMemPool()->New<LabelOperand>(*this);
281     }
282 
Clone(MemPool & memPool)283     Operand *Clone(MemPool &memPool) const override
284     {
285         Operand *opnd = memPool.Clone<LabelOperand>(*this);
286         return opnd;
287     }
288 
Less(const Operand & right)289     bool Less(const Operand &right) const override
290     {
291         (void)right;
292         return false;
293     }
294 
295     void Dump() const override;
296 
GetParentFunc()297     const MapleString &GetParentFunc() const
298     {
299         return parentFunc;
300     }
GetIabelIdx()301     LabelIdx GetIabelIdx() const
302     {
303         return labelIndex;
304     };
305 
306 private:
307     const MapleString parentFunc;
308     LabelIdx labelIndex;
309 };
310 
311 class CFIOpndEmitVisitor
312     : public maplebe::OperandVisitorBase,
313       public maplebe::OperandVisitors<RegOperand, ImmOperand, SymbolOperand, StrOperand, LabelOperand> {
314 public:
CFIOpndEmitVisitor(maplebe::Emitter & asmEmitter)315     explicit CFIOpndEmitVisitor(maplebe::Emitter &asmEmitter) : emitter(asmEmitter) {}
316     virtual ~CFIOpndEmitVisitor() = default;
317 
318 protected:
319     maplebe::Emitter &emitter;
320 
321 private:
322     void Visit(RegOperand *v) final;
323     void Visit(ImmOperand *v) final;
324     void Visit(SymbolOperand *v) final;
325     void Visit(StrOperand *v) final;
326     void Visit(LabelOperand *v) final;
327 };
328 } /* namespace cfi */
329 
330 #endif /* MAPLEBE_INCLUDE_CG_CFI_H */
331