• 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 X64_ASSEMBLER_H
17 #define X64_ASSEMBLER_H
18 
19 #ifndef NDEBUG
20 #define NDEBUG
21 #endif
22 
23 #include <cassert>
24 #include <fstream>
25 #include <unordered_map>
26 #include <vector>
27 #include <string>
28 #include "operand.h"
29 #include "stackmap.h"
30 
31 namespace assembler {
32 enum SymbolAttr {
33     kSAGlobal,
34     kSALocal,
35     kSAWeak,
36     kSAHidden,
37     kSAStatic,
38 };
39 
40 enum SectionKind {
41     kSBss,
42     kSComm,
43     kSData,
44     kSRodata,
45     kSTbss,
46     kSTdata,
47     kSText,
48     kSDebugInfo,
49     kSDebugAbbrev,
50     kSDebugStr,
51 };
52 
53 constexpr uint32 kDwarfVersion = 4;
54 constexpr uint32 kSizeOfPTR = 8;
55 constexpr uint32 k9ByteSize = 9;
56 
57 class Assembler {
58 public:
59     Assembler() = default;
60     virtual ~Assembler() = default;
61 
CloseOutput()62     void CloseOutput()
63     {
64         if (outStream.is_open()) {
65             outStream.close();
66         }
67     }
68 
Emit(int64 val)69     void Emit(int64 val)
70     {
71         outStream << val;
72     }
73 
Emit(const std::string & str)74     void Emit(const std::string &str)
75     {
76         outStream << str;
77     }
78 
Emit(const void * data,uint64 sizeInByte)79     void Emit(const void *data, uint64 sizeInByte)
80     {
81         outStream.write(reinterpret_cast<const char *>(data), sizeInByte);
82     }
83 
84     void StoreNameIntoSymMap(int64 symIdx, const std::string &name, bool isLocal = false)
85     {
86         if (isLocal) {
87             (void)localSymMap.emplace(symIdx, name);
88         } else {
89             (void)globalSymMap.emplace(symIdx, name);
90         }
91     }
92 
93     const std::string &GetNameFromSymMap(int64 symIdx, bool isLocal = false)
94     {
95         if (isLocal) {
96             return localSymMap.at(symIdx);
97         } else {
98             return globalSymMap.at(symIdx);
99         }
100     }
101 
ClearLocalSymMap()102     void ClearLocalSymMap()
103     {
104         localSymMap.clear();
105     }
106 
107     virtual void InitialFileInfo(const std::string &inputFileName) = 0;
108     virtual void EmitVariable(int64 symIdx, uint64 sizeInByte, uint8 alignInByte, SymbolAttr symAttr,
109                               SectionKind sectionKind) = 0;
110     virtual void EmitFunctionFoot(int64 symIdx, SymbolAttr funcAttr) = 0;
111     virtual void EmitFunctionHeader(int64 symIdx, SymbolAttr funcAttr, const std::string *secName = nullptr) = 0;
112     virtual void EmitBBLabel(int64 labelSymIdx, bool genVerboseInfo = false, uint32 freq = 0,
113                              const std::string *mirName = nullptr) = 0;
114     virtual void EmitJmpTableElem(int64 jmpLabelIdx, const std::vector<int64> &labelIdxs) = 0;
115     virtual void EmitDirectString(const std::string &ustr, bool belongsToDataSec = true, int64 strSymIdx = 0,
116                                   bool emitAscii = false) = 0;
117     /* Indirect strings refer to string pointers, such as "char *buf". */
118     virtual void EmitIndirectString(int64 strSymIdx, bool belongsToDataSec = true) = 0;
119     virtual void EmitIntValue(int64 value, size_t valueSize, bool belongsToDataSec = true) = 0;
120     virtual void EmitFloatValue(int64 symIdx, int64 value, size_t valueSize) = 0;
121     virtual void EmitAddrValue(int64 symIdx, int32 symAddrOfs, int32 structFieldOfs, bool belongsToDataSec = true) = 0;
122     virtual void EmitAddrOfFuncValue(int64 symIdx, bool belongsToDataSec = true) = 0;
123     virtual void EmitLabelValue(int64 symIdx, bool belongsToDataSec = true) = 0;
124     virtual void EmitBitFieldValue(uint64 combineBitFieldValue, bool belongsToDataSec = true) = 0;
125     virtual void EmitNull(uint64 sizeInByte) = 0;
126     virtual void PostEmitVariable(int64 symIdx, SymbolAttr symAttr, uint64 sizeInByte,
127                                   bool belongsToTextSec = false) = 0;
128     virtual void FinalizeFileInfo() = 0;
129 
130     /* emit debug info */
131     virtual void EmitDIHeader() = 0;
132     virtual void EmitDIFooter() = 0;
133     virtual void EmitDIHeaderFileInfo() = 0;
134     virtual void EmitDIDebugInfoSectionHeader(uint64 debugInfoLength) = 0;
135     virtual void EmitDIDebugInfoSectionAbbrevId(bool verbose, uint32 abbrevId, const std::string &dieTagName,
136                                                 uint32 offset, uint32 size) = 0;
137     virtual void EmitDIFormSpecification(unsigned int dwform) = 0;
138     /* EmitDIAttrValue */
139     virtual void EmitDwFormString(const std::string &name) = 0;
140     /* strTableSize is used to calculate unique id for the debug string */
141     virtual void EmitDwFormStrp(uint32 strLabelId, size_t strTableSize) = 0;
142     virtual void EmitDwFormData(int32 attrValue, uint8 sizeInByte) = 0;
143     virtual void EmitDwFormData8() = 0;
144     virtual void EmitDwFormData8(uint32 endLabelFuncPuIdx, uint32 startLabelFuncPuIdx, uint32 endLabelIdx,
145                                  uint32 startLabelIdx) = 0;
146     virtual void EmitLabel(uint32 funcPuIdx, uint32 labIdx) = 0;
147     virtual void EmitDwFormSecOffset() = 0;
148     virtual void EmitDwFormAddr(bool emitTextBegin = false) = 0;
149     virtual void EmitDwFormRef4(uint64 offsetOrValue, bool unknownType = false, bool emitOffset = false) = 0;
150     virtual void EmitDwFormExprlocCfa(uint32 dwOp) = 0;
151     virtual void EmitDwFormExprlocAddr(uint32 dwOp, const std::string &addrStr) = 0;
152     virtual void EmitDwFormExprlocFbreg(uint32 dwOp, int fboffset, size_t sleb128Size) = 0;
153     virtual void EmitDwFormExprlocBregn(uint32 dwOp, const std::string &dwOpName) = 0; /* n=0~7 */
154     virtual void EmitDwFormExprloc(uintptr elp) = 0;
155 
156     virtual void EmitDIDwName(const std::string &dwAtName, const std::string &dwForName) = 0;
157     virtual void EmitDIDWFormStr(const std::string &formStr) = 0;
158     virtual void EmitDIDWDataMemberLocaltion(unsigned int lableIdx, uintptr_t attr) = 0;
159     virtual void EmitDIDebugAbbrevSectionHeader() = 0;
160     virtual void EmitDIDebugAbbrevDiae(bool verbose, uint32 abbrevId, uint32 tag, const std::string &dwTagName,
161                                        bool withChildren) = 0;
162     virtual void EmitDIDebugAbbrevDiaePairItem(bool verbose, uint32 aplAt, uint32 aplFrom, const std::string &dwAtName,
163                                                const std::string &dwFromName) = 0;
164     virtual void EmitDIDebugSectionEnd(SectionKind secKind) = 0;
165     virtual void EmitDIDebugARangesSection() = 0;
166     virtual void EmitDIDebugRangesSection() = 0;
167     virtual void EmitDIDebugLineSection() = 0;
168     virtual void EmitDIDebugStrSection(const std::vector<uint32> &strps, const std::vector<std::string> &debugStrs,
169                                        uint64 size, size_t strTableSize) = 0;
170     virtual void EmitLine() = 0;
171 
172     /* start of X64 instructions */
173     /* mov */
174     virtual void Mov(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
175     virtual void Mov(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) = 0;
176     virtual void Mov(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
177     virtual void Mov(InsnSize insnSize, Reg reg, const Mem &mem) = 0;
178     virtual void Mov(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) = 0;
179     /* floating point mov */
180     virtual void Mov(Reg srcReg, Reg destReg, bool isMovD = true) = 0;
181     virtual void MovF(const Mem &mem, Reg reg, bool isSingle = true) = 0;
182     virtual void MovF(Reg reg, const Mem &mem, bool isSingle = true) = 0;
183     /* movabs */
184     virtual void Movabs(const ImmOpnd &immOpnd, Reg reg) = 0;
185     virtual void Movabs(int64 symIdx, Reg reg) = 0;
186     /* push */
187     virtual void Push(InsnSize insnSize, Reg reg) = 0;
188     /* pop */
189     virtual void Pop(InsnSize insnSize, Reg reg) = 0;
190     /* lea */
191     virtual void Lea(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
192     /* movzx */
193     virtual void MovZx(InsnSize sSize, InsnSize dSize, Reg srcReg, Reg destReg) = 0;
194     virtual void MovZx(InsnSize sSize, InsnSize dSize, const Mem &mem, Reg reg) = 0;
195     /* movsx */
196     virtual void MovSx(InsnSize sSize, InsnSize dSize, Reg srcReg, Reg destReg) = 0;
197     virtual void MovSx(InsnSize sSize, InsnSize dSize, const Mem &mem, Reg reg) = 0;
198     /* add */
199     virtual void Add(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
200     virtual void Add(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) = 0;
201     virtual void Add(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
202     virtual void Add(InsnSize insnSize, Reg reg, const Mem &mem) = 0;
203     virtual void Add(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) = 0;
204     /* add floating point */
205     virtual void Add(Reg srcReg, Reg destReg, bool isSingle = true) = 0;
206     virtual void Add(const Mem &mem, Reg reg, bool isSingle = true) = 0;
207     /* sub */
208     virtual void Sub(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
209     virtual void Sub(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) = 0;
210     virtual void Sub(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
211     virtual void Sub(InsnSize insnSize, Reg reg, const Mem &mem) = 0;
212     virtual void Sub(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) = 0;
213     /* sub floating point */
214     virtual void Sub(Reg srcReg, Reg destReg, bool isSingle = true) = 0;
215     virtual void Sub(const Mem &mem, Reg reg, bool isSingle = true) = 0;
216     /* and */
217     virtual void And(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
218     virtual void And(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
219     virtual void And(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) = 0;
220     virtual void And(InsnSize insnSize, Reg reg, const Mem &mem) = 0;
221     virtual void And(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) = 0;
222     /* or */
223     virtual void Or(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
224     virtual void Or(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
225     virtual void Or(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) = 0;
226     virtual void Or(InsnSize insnSize, Reg reg, const Mem &mem) = 0;
227     virtual void Or(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) = 0;
228     /* xor */
229     virtual void Xor(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
230     virtual void Xor(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) = 0;
231     virtual void Xor(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
232     virtual void Xor(InsnSize insnSize, Reg reg, const Mem &mem) = 0;
233     virtual void Xor(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) = 0;
234     /* not */
235     virtual void Not(InsnSize insnSize, Reg reg) = 0;
236     virtual void Not(InsnSize insnSize, const Mem &mem) = 0;
237     /* neg */
238     virtual void Neg(InsnSize insnSize, Reg reg) = 0;
239     virtual void Neg(InsnSize insnSize, const Mem &mem) = 0;
240     /* div & cwd, cdq, cqo */
241     virtual void Idiv(InsnSize insnSize, Reg reg) = 0;
242     virtual void Idiv(InsnSize insnSize, const Mem &mem) = 0;
243     virtual void Div(InsnSize insnSize, Reg reg) = 0;
244     virtual void Div(InsnSize insnSize, const Mem &mem) = 0;
245     virtual void Cwd() = 0;
246     virtual void Cdq() = 0;
247     virtual void Cqo() = 0;
248     /* shl */
249     virtual void Shl(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
250     virtual void Shl(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) = 0;
251     virtual void Shl(InsnSize insnSize, Reg reg, const Mem &mem) = 0;
252     virtual void Shl(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) = 0;
253     /* sar */
254     virtual void Sar(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
255     virtual void Sar(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) = 0;
256     virtual void Sar(InsnSize insnSize, Reg reg, const Mem &mem) = 0;
257     virtual void Sar(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) = 0;
258     /* shr */
259     virtual void Shr(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
260     virtual void Shr(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) = 0;
261     virtual void Shr(InsnSize insnSize, Reg reg, const Mem &mem) = 0;
262     virtual void Shr(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) = 0;
263     /* jmp */
264     virtual void Jmp(Reg reg) = 0;
265     virtual void Jmp(const Mem &mem) = 0;
266     virtual void Jmp(int64 symIdx) = 0;
267     /* jump condition */
268     virtual void Je(int64 symIdx) = 0;
269     virtual void Ja(int64 symIdx) = 0;
270     virtual void Jae(int64 symIdx) = 0;
271     virtual void Jne(int64 symIdx) = 0;
272     virtual void Jb(int64 symIdx) = 0;
273     virtual void Jbe(int64 symIdx) = 0;
274     virtual void Jg(int64 symIdx) = 0;
275     virtual void Jge(int64 symIdx) = 0;
276     virtual void Jl(int64 symIdx) = 0;
277     virtual void Jle(int64 symIdx) = 0;
278     /* cmp */
279     virtual void Cmp(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
280     virtual void Cmp(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
281     virtual void Cmp(InsnSize insnSize, Reg reg, const Mem &mem) = 0;
282     virtual void Cmp(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) = 0;
283     virtual void Cmp(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) = 0;
284     /* test */
285     virtual void Test(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
286     /* set */
287     virtual void Setbe(Reg reg) = 0;
288     virtual void Setbe(const Mem &mem) = 0;
289     virtual void Setle(Reg reg) = 0;
290     virtual void Setle(const Mem &mem) = 0;
291     virtual void Setae(Reg reg) = 0;
292     virtual void Setae(const Mem &mem) = 0;
293     virtual void Setge(Reg reg) = 0;
294     virtual void Setge(const Mem &mem) = 0;
295     virtual void Setne(Reg reg) = 0;
296     virtual void Setne(const Mem &mem) = 0;
297     virtual void Setb(Reg reg) = 0;
298     virtual void Setb(const Mem &mem) = 0;
299     virtual void Setl(Reg reg) = 0;
300     virtual void Setl(const Mem &mem) = 0;
301     virtual void Seta(Reg reg) = 0;
302     virtual void Seta(const Mem &mem) = 0;
303     virtual void Setg(Reg reg) = 0;
304     virtual void Setg(const Mem &mem) = 0;
305     virtual void Sete(Reg reg) = 0;
306     virtual void Sete(const Mem &mem) = 0;
307     virtual void Seto(Reg reg) = 0;
308     virtual void Seto(const Mem &mem) = 0;
309     /* cmov */
310     virtual void Cmova(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
311     virtual void Cmova(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
312     virtual void Cmovae(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
313     virtual void Cmovae(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
314     virtual void Cmovb(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
315     virtual void Cmovb(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
316     virtual void Cmovbe(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
317     virtual void Cmovbe(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
318     virtual void Cmove(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
319     virtual void Cmove(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
320     virtual void Cmovg(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
321     virtual void Cmovg(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
322     virtual void Cmovge(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
323     virtual void Cmovge(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
324     virtual void Cmovl(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
325     virtual void Cmovl(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
326     virtual void Cmovle(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
327     virtual void Cmovle(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
328     virtual void Cmovne(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
329     virtual void Cmovne(InsnSize insnSize, const Mem &mem, Reg reg) = 0;
330     virtual void Cmovo(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
331     /* call */
332     virtual void Call(InsnSize insnSize, Reg reg) = 0;
333     virtual void Call(InsnSize insnSize, const Mem &mem) = 0;
334     virtual void Call(InsnSize insnSize, int64 symIdx) = 0;
335     /* ret */
336     virtual void Ret() = 0;
337     /* leave */
338     virtual void Leave() = 0;
339     /* imul */
340     virtual void Imul(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
341     /* mul float */
342     virtual void Mul(Reg srcReg, Reg destReg, bool isSingle = true) = 0;
343     virtual void Mul(const Mem &mem, Reg reg, bool isSingle = true) = 0;
344     /* nop */
345     virtual void Nop(InsnSize insnSize, const Mem &mem) = 0;
346     virtual void Nop() = 0;
347     /* byte swap */
348     virtual void Bswap(InsnSize insnSize, Reg reg) = 0;
349     virtual void Xchg(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
350     /* pseudo insn */
351     virtual void DealWithPseudoInst(const std::string &insn) = 0;
352     /* floating point */
353     virtual void MovF(Reg srcReg, Reg destReg, bool isSingle = true) = 0;
354     /* floating point and */
355     virtual void And(Reg srcReg, Reg destReg, bool isSingle = true) = 0;
356     virtual void And(const Mem &mem, Reg reg, bool isSingle = true) = 0;
357     /* floating div */
358     virtual void Divsd(Reg srcReg, Reg destReg) = 0;
359     virtual void Divsd(const Mem &mem, Reg reg) = 0;
360     /* convert int2float */
361     virtual void Cvtsi2ss(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
362     virtual void Cvtsi2sd(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
363     /*convert float2int */
364     virtual void Cvttsd2si(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
365     virtual void Cvttss2si(InsnSize insnSize, Reg srcReg, Reg destReg) = 0;
366     /* convert float2float */
367     virtual void Cvtss2sd(Reg srcReg, Reg destReg) = 0;
368     virtual void Cvtsd2ss(Reg srcReg, Reg destReg) = 0;
369     /* unordered compare */
370     virtual void Ucomisd(Reg srcReg, Reg destReg) = 0;
371     virtual void Ucomiss(Reg srcReg, Reg destReg) = 0;
372     virtual void Cmpeqsd(Reg srcReg, Reg destReg) = 0;
373     /* float sqrt*/
374     virtual void Sqrtss_r(Reg srcReg, Reg destReg) = 0;
375     virtual void Sqrtsd_r(Reg srcReg, Reg destReg) = 0;
376     /* end of X64 instructions */
377     /* process stackmap */
378     virtual void RecordStackmap(const std::vector<uint64> &referenceMap, const std::vector<uint64> &deoptInfo) = 0;
379     virtual uint32 GetCurModulePC() = 0;
380     virtual void SetLastModulePC(uint32 pc) = 0;
381 
382 protected:
383     std::ofstream outStream;
384     std::string fileName;
385     std::unordered_map<int64, const std::string> globalSymMap; /* store global variable symbols */
386     std::unordered_map<int64, const std::string> localSymMap;  /* store local variable symbols for each function */
387 };
388 } /* namespace assembler */
389 
390 #endif /* X64_ASSEMBLER_H */