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