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