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