1 //===- bolt/Core/MCPlusBuilder.cpp - Interface for MCPlus -----------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the MCPlusBuilder class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "bolt/Core/MCPlusBuilder.h" 14 #include "bolt/Core/MCPlus.h" 15 #include "llvm/MC/MCContext.h" 16 #include "llvm/MC/MCInst.h" 17 #include "llvm/MC/MCInstrAnalysis.h" 18 #include "llvm/MC/MCInstrDesc.h" 19 #include "llvm/MC/MCInstrInfo.h" 20 #include "llvm/MC/MCRegisterInfo.h" 21 #include "llvm/Support/Debug.h" 22 #include <cstdint> 23 #include <queue> 24 25 #define DEBUG_TYPE "mcplus" 26 27 using namespace llvm; 28 using namespace bolt; 29 using namespace MCPlus; 30 31 bool MCPlusBuilder::equals(const MCInst &A, const MCInst &B, 32 CompFuncTy Comp) const { 33 if (A.getOpcode() != B.getOpcode()) 34 return false; 35 36 unsigned NumOperands = MCPlus::getNumPrimeOperands(A); 37 if (NumOperands != MCPlus::getNumPrimeOperands(B)) 38 return false; 39 40 for (unsigned Index = 0; Index < NumOperands; ++Index) 41 if (!equals(A.getOperand(Index), B.getOperand(Index), Comp)) 42 return false; 43 44 return true; 45 } 46 47 bool MCPlusBuilder::equals(const MCOperand &A, const MCOperand &B, 48 CompFuncTy Comp) const { 49 if (A.isReg()) { 50 if (!B.isReg()) 51 return false; 52 return A.getReg() == B.getReg(); 53 } else if (A.isImm()) { 54 if (!B.isImm()) 55 return false; 56 return A.getImm() == B.getImm(); 57 } else if (A.isSFPImm()) { 58 if (!B.isSFPImm()) 59 return false; 60 return A.getSFPImm() == B.getSFPImm(); 61 } else if (A.isDFPImm()) { 62 if (!B.isDFPImm()) 63 return false; 64 return A.getDFPImm() == B.getDFPImm(); 65 } else if (A.isExpr()) { 66 if (!B.isExpr()) 67 return false; 68 return equals(*A.getExpr(), *B.getExpr(), Comp); 69 } else { 70 llvm_unreachable("unexpected operand kind"); 71 return false; 72 } 73 } 74 75 bool MCPlusBuilder::equals(const MCExpr &A, const MCExpr &B, 76 CompFuncTy Comp) const { 77 if (A.getKind() != B.getKind()) 78 return false; 79 80 switch (A.getKind()) { 81 case MCExpr::Constant: { 82 const auto &ConstA = cast<MCConstantExpr>(A); 83 const auto &ConstB = cast<MCConstantExpr>(B); 84 return ConstA.getValue() == ConstB.getValue(); 85 } 86 87 case MCExpr::SymbolRef: { 88 const MCSymbolRefExpr &SymbolA = cast<MCSymbolRefExpr>(A); 89 const MCSymbolRefExpr &SymbolB = cast<MCSymbolRefExpr>(B); 90 return SymbolA.getKind() == SymbolB.getKind() && 91 Comp(&SymbolA.getSymbol(), &SymbolB.getSymbol()); 92 } 93 94 case MCExpr::Unary: { 95 const auto &UnaryA = cast<MCUnaryExpr>(A); 96 const auto &UnaryB = cast<MCUnaryExpr>(B); 97 return UnaryA.getOpcode() == UnaryB.getOpcode() && 98 equals(*UnaryA.getSubExpr(), *UnaryB.getSubExpr(), Comp); 99 } 100 101 case MCExpr::Binary: { 102 const auto &BinaryA = cast<MCBinaryExpr>(A); 103 const auto &BinaryB = cast<MCBinaryExpr>(B); 104 return BinaryA.getOpcode() == BinaryB.getOpcode() && 105 equals(*BinaryA.getLHS(), *BinaryB.getLHS(), Comp) && 106 equals(*BinaryA.getRHS(), *BinaryB.getRHS(), Comp); 107 } 108 109 case MCExpr::Target: { 110 const auto &TargetExprA = cast<MCTargetExpr>(A); 111 const auto &TargetExprB = cast<MCTargetExpr>(B); 112 return equals(TargetExprA, TargetExprB, Comp); 113 } 114 } 115 116 llvm_unreachable("Invalid expression kind!"); 117 } 118 119 bool MCPlusBuilder::equals(const MCTargetExpr &A, const MCTargetExpr &B, 120 CompFuncTy Comp) const { 121 llvm_unreachable("target-specific expressions are unsupported"); 122 } 123 124 void MCPlusBuilder::setTailCall(MCInst &Inst) const { 125 assert(!hasAnnotation(Inst, MCAnnotation::kTailCall)); 126 setAnnotationOpValue(Inst, MCAnnotation::kTailCall, true); 127 } 128 129 bool MCPlusBuilder::isTailCall(const MCInst &Inst) const { 130 if (hasAnnotation(Inst, MCAnnotation::kTailCall)) 131 return true; 132 if (getConditionalTailCall(Inst)) 133 return true; 134 return false; 135 } 136 137 std::optional<MCLandingPad> MCPlusBuilder::getEHInfo(const MCInst &Inst) const { 138 if (!isCall(Inst)) 139 return std::nullopt; 140 std::optional<int64_t> LPSym = 141 getAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad); 142 if (!LPSym) 143 return std::nullopt; 144 std::optional<int64_t> Action = 145 getAnnotationOpValue(Inst, MCAnnotation::kEHAction); 146 if (!Action) 147 return std::nullopt; 148 149 return std::make_pair(reinterpret_cast<const MCSymbol *>(*LPSym), 150 static_cast<uint64_t>(*Action)); 151 } 152 153 void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) const { 154 if (isCall(Inst)) { 155 assert(!getEHInfo(Inst)); 156 setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad, 157 reinterpret_cast<int64_t>(LP.first)); 158 setAnnotationOpValue(Inst, MCAnnotation::kEHAction, 159 static_cast<int64_t>(LP.second)); 160 } 161 } 162 163 bool MCPlusBuilder::updateEHInfo(MCInst &Inst, const MCLandingPad &LP) const { 164 if (!isInvoke(Inst)) 165 return false; 166 167 setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad, 168 reinterpret_cast<int64_t>(LP.first)); 169 setAnnotationOpValue(Inst, MCAnnotation::kEHAction, 170 static_cast<int64_t>(LP.second)); 171 return true; 172 } 173 174 int64_t MCPlusBuilder::getGnuArgsSize(const MCInst &Inst) const { 175 std::optional<int64_t> Value = 176 getAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize); 177 if (!Value) 178 return -1LL; 179 return *Value; 180 } 181 182 void MCPlusBuilder::addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize) const { 183 assert(GnuArgsSize >= 0 && "cannot set GNU_args_size to negative value"); 184 assert(getGnuArgsSize(Inst) == -1LL && "GNU_args_size already set"); 185 assert(isInvoke(Inst) && "GNU_args_size can only be set for invoke"); 186 187 setAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize, GnuArgsSize); 188 } 189 190 uint64_t MCPlusBuilder::getJumpTable(const MCInst &Inst) const { 191 std::optional<int64_t> Value = 192 getAnnotationOpValue(Inst, MCAnnotation::kJumpTable); 193 if (!Value) 194 return 0; 195 return *Value; 196 } 197 198 uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst &Inst) const { 199 return getAnnotationAs<uint16_t>(Inst, "JTIndexReg"); 200 } 201 202 bool MCPlusBuilder::setJumpTable(MCInst &Inst, uint64_t Value, 203 uint16_t IndexReg, AllocatorIdTy AllocId) { 204 if (!isIndirectBranch(Inst)) 205 return false; 206 setAnnotationOpValue(Inst, MCAnnotation::kJumpTable, Value); 207 getOrCreateAnnotationAs<uint16_t>(Inst, "JTIndexReg", AllocId) = IndexReg; 208 return true; 209 } 210 211 bool MCPlusBuilder::unsetJumpTable(MCInst &Inst) const { 212 if (!getJumpTable(Inst)) 213 return false; 214 removeAnnotation(Inst, MCAnnotation::kJumpTable); 215 removeAnnotation(Inst, "JTIndexReg"); 216 return true; 217 } 218 219 std::optional<uint64_t> 220 MCPlusBuilder::getConditionalTailCall(const MCInst &Inst) const { 221 std::optional<int64_t> Value = 222 getAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall); 223 if (!Value) 224 return std::nullopt; 225 return static_cast<uint64_t>(*Value); 226 } 227 228 bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) const { 229 if (!isConditionalBranch(Inst)) 230 return false; 231 232 setAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall, Dest); 233 return true; 234 } 235 236 bool MCPlusBuilder::unsetConditionalTailCall(MCInst &Inst) const { 237 if (!getConditionalTailCall(Inst)) 238 return false; 239 removeAnnotation(Inst, MCAnnotation::kConditionalTailCall); 240 return true; 241 } 242 243 std::optional<uint32_t> MCPlusBuilder::getOffset(const MCInst &Inst) const { 244 std::optional<int64_t> Value = 245 getAnnotationOpValue(Inst, MCAnnotation::kOffset); 246 if (!Value) 247 return std::nullopt; 248 return static_cast<uint32_t>(*Value); 249 } 250 251 uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst &Inst, 252 uint32_t Default) const { 253 if (std::optional<uint32_t> Offset = getOffset(Inst)) 254 return *Offset; 255 return Default; 256 } 257 258 bool MCPlusBuilder::setOffset(MCInst &Inst, uint32_t Offset) const { 259 setAnnotationOpValue(Inst, MCAnnotation::kOffset, Offset); 260 return true; 261 } 262 263 bool MCPlusBuilder::clearOffset(MCInst &Inst) const { 264 if (!hasAnnotation(Inst, MCAnnotation::kOffset)) 265 return false; 266 removeAnnotation(Inst, MCAnnotation::kOffset); 267 return true; 268 } 269 270 MCSymbol *MCPlusBuilder::getInstLabel(const MCInst &Inst) const { 271 if (std::optional<int64_t> Label = 272 getAnnotationOpValue(Inst, MCAnnotation::kLabel)) 273 return reinterpret_cast<MCSymbol *>(*Label); 274 return nullptr; 275 } 276 277 MCSymbol *MCPlusBuilder::getOrCreateInstLabel(MCInst &Inst, const Twine &Name, 278 MCContext *Ctx) const { 279 MCSymbol *Label = getInstLabel(Inst); 280 if (Label) 281 return Label; 282 283 Label = Ctx->createNamedTempSymbol(Name); 284 setAnnotationOpValue(Inst, MCAnnotation::kLabel, 285 reinterpret_cast<int64_t>(Label)); 286 return Label; 287 } 288 289 void MCPlusBuilder::setInstLabel(MCInst &Inst, MCSymbol *Label) const { 290 assert(!getInstLabel(Inst) && "Instruction already has assigned label."); 291 setAnnotationOpValue(Inst, MCAnnotation::kLabel, 292 reinterpret_cast<int64_t>(Label)); 293 } 294 295 std::optional<uint32_t> MCPlusBuilder::getSize(const MCInst &Inst) const { 296 if (std::optional<int64_t> Value = 297 getAnnotationOpValue(Inst, MCAnnotation::kSize)) 298 return static_cast<uint32_t>(*Value); 299 return std::nullopt; 300 } 301 302 void MCPlusBuilder::setSize(MCInst &Inst, uint32_t Size) const { 303 setAnnotationOpValue(Inst, MCAnnotation::kSize, Size); 304 } 305 306 bool MCPlusBuilder::isDynamicBranch(const MCInst &Inst) const { 307 if (!hasAnnotation(Inst, MCAnnotation::kDynamicBranch)) 308 return false; 309 assert(isBranch(Inst) && "Branch expected."); 310 return true; 311 } 312 313 std::optional<uint32_t> 314 MCPlusBuilder::getDynamicBranchID(const MCInst &Inst) const { 315 if (std::optional<int64_t> Value = 316 getAnnotationOpValue(Inst, MCAnnotation::kDynamicBranch)) { 317 assert(isBranch(Inst) && "Branch expected."); 318 return static_cast<uint32_t>(*Value); 319 } 320 return std::nullopt; 321 } 322 323 void MCPlusBuilder::setDynamicBranch(MCInst &Inst, uint32_t ID) const { 324 assert(isBranch(Inst) && "Branch expected."); 325 setAnnotationOpValue(Inst, MCAnnotation::kDynamicBranch, ID); 326 } 327 328 bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const { 329 return (bool)getAnnotationOpValue(Inst, Index); 330 } 331 332 bool MCPlusBuilder::removeAnnotation(MCInst &Inst, unsigned Index) const { 333 std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst); 334 if (!FirstAnnotationOp) 335 return false; 336 337 for (unsigned I = Inst.getNumOperands() - 1; I >= *FirstAnnotationOp; --I) { 338 const int64_t ImmValue = Inst.getOperand(I).getImm(); 339 if (extractAnnotationIndex(ImmValue) == Index) { 340 Inst.erase(Inst.begin() + I); 341 return true; 342 } 343 } 344 return false; 345 } 346 347 void MCPlusBuilder::stripAnnotations(MCInst &Inst, bool KeepTC) const { 348 KeepTC &= hasAnnotation(Inst, MCAnnotation::kTailCall); 349 350 removeAnnotations(Inst); 351 352 if (KeepTC) 353 setTailCall(Inst); 354 } 355 356 void MCPlusBuilder::printAnnotations(const MCInst &Inst, 357 raw_ostream &OS) const { 358 std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst); 359 if (!FirstAnnotationOp) 360 return; 361 362 for (unsigned I = *FirstAnnotationOp; I < Inst.getNumOperands(); ++I) { 363 const int64_t Imm = Inst.getOperand(I).getImm(); 364 const unsigned Index = extractAnnotationIndex(Imm); 365 const int64_t Value = extractAnnotationValue(Imm); 366 const auto *Annotation = reinterpret_cast<const MCAnnotation *>(Value); 367 if (Index >= MCAnnotation::kGeneric) { 368 OS << " # " << AnnotationNames[Index - MCAnnotation::kGeneric] << ": "; 369 Annotation->print(OS); 370 } 371 } 372 } 373 374 void MCPlusBuilder::getClobberedRegs(const MCInst &Inst, 375 BitVector &Regs) const { 376 if (isPrefix(Inst) || isCFI(Inst)) 377 return; 378 379 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode()); 380 381 for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) 382 Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/false); 383 384 for (const MCOperand &Operand : defOperands(Inst)) { 385 assert(Operand.isReg()); 386 Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/false); 387 } 388 } 389 390 void MCPlusBuilder::getTouchedRegs(const MCInst &Inst, BitVector &Regs) const { 391 if (isPrefix(Inst) || isCFI(Inst)) 392 return; 393 394 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode()); 395 396 for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) 397 Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/false); 398 for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) 399 Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/false); 400 401 for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) { 402 if (!Inst.getOperand(I).isReg()) 403 continue; 404 Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/false); 405 } 406 } 407 408 void MCPlusBuilder::getWrittenRegs(const MCInst &Inst, BitVector &Regs) const { 409 if (isPrefix(Inst) || isCFI(Inst)) 410 return; 411 412 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode()); 413 414 for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) 415 Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/true); 416 417 for (const MCOperand &Operand : defOperands(Inst)) { 418 assert(Operand.isReg()); 419 Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true); 420 } 421 } 422 423 void MCPlusBuilder::getUsedRegs(const MCInst &Inst, BitVector &Regs) const { 424 if (isPrefix(Inst) || isCFI(Inst)) 425 return; 426 427 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode()); 428 429 for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) 430 Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/true); 431 432 for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) { 433 if (!Inst.getOperand(I).isReg()) 434 continue; 435 Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/true); 436 } 437 } 438 439 void MCPlusBuilder::getSrcRegs(const MCInst &Inst, BitVector &Regs) const { 440 if (isPrefix(Inst) || isCFI(Inst)) 441 return; 442 443 if (isCall(Inst)) { 444 BitVector CallRegs = BitVector(Regs.size(), false); 445 getCalleeSavedRegs(CallRegs); 446 CallRegs.flip(); 447 Regs |= CallRegs; 448 return; 449 } 450 451 if (isReturn(Inst)) { 452 getDefaultLiveOut(Regs); 453 return; 454 } 455 456 if (isRep(Inst)) 457 getRepRegs(Regs); 458 459 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode()); 460 461 for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) 462 Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/true); 463 464 for (const MCOperand &Operand : useOperands(Inst)) 465 if (Operand.isReg()) 466 Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true); 467 } 468 469 bool MCPlusBuilder::hasDefOfPhysReg(const MCInst &MI, unsigned Reg) const { 470 const MCInstrDesc &InstInfo = Info->get(MI.getOpcode()); 471 return InstInfo.hasDefOfPhysReg(MI, Reg, *RegInfo); 472 } 473 474 bool MCPlusBuilder::hasUseOfPhysReg(const MCInst &MI, unsigned Reg) const { 475 const MCInstrDesc &InstInfo = Info->get(MI.getOpcode()); 476 for (int I = InstInfo.NumDefs; I < InstInfo.NumOperands; ++I) 477 if (MI.getOperand(I).isReg() && MI.getOperand(I).getReg() && 478 RegInfo->isSubRegisterEq(Reg, MI.getOperand(I).getReg())) 479 return true; 480 for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) { 481 if (ImplicitUse == Reg || RegInfo->isSubRegister(Reg, ImplicitUse)) 482 return true; 483 } 484 return false; 485 } 486 487 const BitVector &MCPlusBuilder::getAliases(MCPhysReg Reg, 488 bool OnlySmaller) const { 489 if (OnlySmaller) 490 return SmallerAliasMap[Reg]; 491 return AliasMap[Reg]; 492 } 493 494 void MCPlusBuilder::initAliases() { 495 assert(AliasMap.size() == 0 && SmallerAliasMap.size() == 0); 496 // Build alias map 497 for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) { 498 BitVector BV(RegInfo->getNumRegs(), false); 499 BV.set(I); 500 AliasMap.emplace_back(BV); 501 SmallerAliasMap.emplace_back(BV); 502 } 503 504 // Cache all aliases for each register 505 for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I != E; ++I) { 506 for (MCRegAliasIterator AI(I, RegInfo, true); AI.isValid(); ++AI) 507 AliasMap[I].set(*AI); 508 } 509 510 // Propagate smaller alias info upwards. Skip reg 0 (mapped to NoRegister) 511 for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I < E; ++I) 512 for (MCSubRegIterator SI(I, RegInfo); SI.isValid(); ++SI) 513 SmallerAliasMap[I] |= SmallerAliasMap[*SI]; 514 515 LLVM_DEBUG({ 516 dbgs() << "Dumping reg alias table:\n"; 517 for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) { 518 dbgs() << "Reg " << I << ": "; 519 const BitVector &BV = AliasMap[I]; 520 int Idx = BV.find_first(); 521 while (Idx != -1) { 522 dbgs() << Idx << " "; 523 Idx = BV.find_next(Idx); 524 } 525 dbgs() << "\n"; 526 } 527 }); 528 } 529 530 void MCPlusBuilder::initSizeMap() { 531 SizeMap.resize(RegInfo->getNumRegs()); 532 // Build size map 533 for (auto RC : RegInfo->regclasses()) 534 for (MCPhysReg Reg : RC) 535 SizeMap[Reg] = RC.getSizeInBits() / 8; 536 } 537 538 bool MCPlusBuilder::setOperandToSymbolRef(MCInst &Inst, int OpNum, 539 const MCSymbol *Symbol, 540 int64_t Addend, MCContext *Ctx, 541 uint64_t RelType) const { 542 MCOperand Operand; 543 if (!Addend) { 544 Operand = MCOperand::createExpr(getTargetExprFor( 545 Inst, MCSymbolRefExpr::create(Symbol, *Ctx), *Ctx, RelType)); 546 } else { 547 Operand = MCOperand::createExpr(getTargetExprFor( 548 Inst, 549 MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, *Ctx), 550 MCConstantExpr::create(Addend, *Ctx), *Ctx), 551 *Ctx, RelType)); 552 } 553 Inst.getOperand(OpNum) = Operand; 554 return true; 555 } 556