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 */