brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.5 KiB · 7b6f162 Raw
498 lines · cpp
1//===- bolt/unittest/Core/MCPlusBuilder.cpp -------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#ifdef AARCH64_AVAILABLE10#include "AArch64Subtarget.h"11#include "MCTargetDesc/AArch64MCTargetDesc.h"12#endif // AARCH64_AVAILABLE13 14#ifdef X86_AVAILABLE15#include "X86Subtarget.h"16#endif // X86_AVAILABLE17 18#include "bolt/Core/BinaryBasicBlock.h"19#include "bolt/Core/BinaryFunction.h"20#include "bolt/Rewrite/RewriteInstance.h"21#include "llvm/BinaryFormat/ELF.h"22#include "llvm/DebugInfo/DWARF/DWARFContext.h"23#include "llvm/MC/MCInstBuilder.h"24#include "llvm/Support/TargetSelect.h"25#include "gtest/gtest.h"26 27using namespace llvm;28using namespace llvm::object;29using namespace llvm::ELF;30using namespace bolt;31 32namespace {33struct MCPlusBuilderTester : public testing::TestWithParam<Triple::ArchType> {34  void SetUp() override {35    initalizeLLVM();36    prepareElf();37    initializeBolt();38  }39 40protected:41  void initalizeLLVM() {42#define BOLT_TARGET(target)                                                    \43  LLVMInitialize##target##TargetInfo();                                        \44  LLVMInitialize##target##TargetMC();                                          \45  LLVMInitialize##target##AsmParser();                                         \46  LLVMInitialize##target##Disassembler();                                      \47  LLVMInitialize##target##Target();                                            \48  LLVMInitialize##target##AsmPrinter();49 50#include "bolt/Core/TargetConfig.def"51  }52 53  void prepareElf() {54    memcpy(ElfBuf, "\177ELF", 4);55    ELF64LE::Ehdr *EHdr = reinterpret_cast<typename ELF64LE::Ehdr *>(ElfBuf);56    EHdr->e_ident[llvm::ELF::EI_CLASS] = llvm::ELF::ELFCLASS64;57    EHdr->e_ident[llvm::ELF::EI_DATA] = llvm::ELF::ELFDATA2LSB;58    EHdr->e_machine = GetParam() == Triple::aarch64 ? EM_AARCH64 : EM_X86_64;59    MemoryBufferRef Source(StringRef(ElfBuf, sizeof(ElfBuf)), "ELF");60    ObjFile = cantFail(ObjectFile::createObjectFile(Source));61  }62 63  void initializeBolt() {64    Relocation::Arch = ObjFile->makeTriple().getArch();65    BC = cantFail(BinaryContext::createBinaryContext(66        ObjFile->makeTriple(), std::make_shared<orc::SymbolStringPool>(),67        ObjFile->getFileName(), nullptr, true, DWARFContext::create(*ObjFile),68        {llvm::outs(), llvm::errs()}));69    ASSERT_FALSE(!BC);70    BC->initializeTarget(std::unique_ptr<MCPlusBuilder>(71        createMCPlusBuilder(GetParam(), BC->MIA.get(), BC->MII.get(),72                            BC->MRI.get(), BC->STI.get())));73  }74 75  void assertRegMask(const BitVector &RegMask,76                     std::initializer_list<MCPhysReg> ExpectedRegs) {77    ASSERT_EQ(RegMask.count(), ExpectedRegs.size());78    for (MCPhysReg Reg : ExpectedRegs)79      ASSERT_TRUE(RegMask[Reg]) << "Expected " << BC->MRI->getName(Reg) << ".";80  }81 82  void assertRegMask(std::function<void(BitVector &)> FillRegMask,83                     std::initializer_list<MCPhysReg> ExpectedRegs) {84    BitVector RegMask(BC->MRI->getNumRegs());85    FillRegMask(RegMask);86    assertRegMask(RegMask, ExpectedRegs);87  }88 89  void testRegAliases(Triple::ArchType Arch, uint64_t Register,90                      std::initializer_list<MCPhysReg> ExpectedAliases,91                      bool OnlySmaller = false) {92    if (GetParam() != Arch)93      GTEST_SKIP();94 95    const BitVector &BV = BC->MIB->getAliases(Register, OnlySmaller);96    assertRegMask(BV, ExpectedAliases);97  }98 99  char ElfBuf[sizeof(typename ELF64LE::Ehdr)] = {};100  std::unique_ptr<ObjectFile> ObjFile;101  std::unique_ptr<BinaryContext> BC;102};103} // namespace104 105#ifdef AARCH64_AVAILABLE106 107INSTANTIATE_TEST_SUITE_P(AArch64, MCPlusBuilderTester,108                         ::testing::Values(Triple::aarch64));109 110TEST_P(MCPlusBuilderTester, AliasX0) {111  testRegAliases(Triple::aarch64, AArch64::X0,112                 {AArch64::W0, AArch64::W0_HI, AArch64::X0, AArch64::W0_W1,113                  AArch64::X0_X1, AArch64::X0_X1_X2_X3_X4_X5_X6_X7});114}115 116TEST_P(MCPlusBuilderTester, AliasSmallerX0) {117  testRegAliases(Triple::aarch64, AArch64::X0,118                 {AArch64::W0, AArch64::W0_HI, AArch64::X0},119                 /*OnlySmaller=*/true);120}121 122TEST_P(MCPlusBuilderTester, AArch64_CmpJE) {123  if (GetParam() != Triple::aarch64)124    GTEST_SKIP();125  BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);126  std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();127 128  InstructionListType Instrs =129      BC->MIB->createCmpJE(AArch64::X0, 2, BB->getLabel(), BC->Ctx.get());130  BB->addInstructions(Instrs.begin(), Instrs.end());131  BB->addSuccessor(BB.get());132 133  auto II = BB->begin();134  ASSERT_EQ(II->getOpcode(), AArch64::SUBSXri);135  ASSERT_EQ(II->getOperand(0).getReg(), AArch64::XZR);136  ASSERT_EQ(II->getOperand(1).getReg(), AArch64::X0);137  ASSERT_EQ(II->getOperand(2).getImm(), 2);138  ASSERT_EQ(II->getOperand(3).getImm(), 0);139  II++;140  ASSERT_EQ(II->getOpcode(), AArch64::Bcc);141  ASSERT_EQ(II->getOperand(0).getImm(), AArch64CC::EQ);142  const MCSymbol *Label = BC->MIB->getTargetSymbol(*II, 1);143  ASSERT_EQ(Label, BB->getLabel());144}145 146TEST_P(MCPlusBuilderTester, AArch64_BTI) {147  if (GetParam() != Triple::aarch64)148    GTEST_SKIP();149  BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);150  std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();151 152  MCInst BTIjc;153  BC->MIB->createBTI(BTIjc, true, true);154  BB->addInstruction(BTIjc);155  auto II = BB->begin();156  ASSERT_EQ(II->getOpcode(), AArch64::HINT);157  ASSERT_EQ(II->getOperand(0).getImm(), 38);158  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, true));159  BC->MIB->updateBTIVariant(*II, true, false);160  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, false));161 162  MCInst BTIj;163  BC->MIB->createBTI(BTIj, false, true);164  II = BB->addInstruction(BTIj);165  ASSERT_EQ(II->getOpcode(), AArch64::HINT);166  ASSERT_EQ(II->getOperand(0).getImm(), 36);167  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, false, true));168  BC->MIB->updateBTIVariant(*II, true, true);169  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, true));170 171  MCInst BTIc;172  BC->MIB->createBTI(BTIc, true, false);173  II = BB->addInstruction(BTIc);174  ASSERT_EQ(II->getOpcode(), AArch64::HINT);175  ASSERT_EQ(II->getOperand(0).getImm(), 34);176  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, false));177  BC->MIB->updateBTIVariant(*II, false, true);178  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, false, true));179 180#ifndef NDEBUG181  MCInst BTIinvalid;182  ASSERT_DEATH(BC->MIB->createBTI(BTIinvalid, false, false),183               "No target kinds!");184#endif185 186  MCInst Paciasp = MCInstBuilder(AArch64::PACIASP);187  II = BB->addInstruction(Paciasp);188  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, false));189  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, true, true));190  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, false, true));191  ASSERT_TRUE(BC->MIB->isImplicitBTIC(*II));192 193  MCInst Pacibsp = MCInstBuilder(AArch64::PACIBSP);194  II = BB->addInstruction(Pacibsp);195  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, false));196  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, true, true));197  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, false, true));198  ASSERT_TRUE(BC->MIB->isImplicitBTIC(*II));199}200 201TEST_P(MCPlusBuilderTester, AArch64_CmpJNE) {202  if (GetParam() != Triple::aarch64)203    GTEST_SKIP();204  BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);205  std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();206 207  InstructionListType Instrs =208      BC->MIB->createCmpJNE(AArch64::X0, 2, BB->getLabel(), BC->Ctx.get());209  BB->addInstructions(Instrs.begin(), Instrs.end());210  BB->addSuccessor(BB.get());211 212  auto II = BB->begin();213  ASSERT_EQ(II->getOpcode(), AArch64::SUBSXri);214  ASSERT_EQ(II->getOperand(0).getReg(), AArch64::XZR);215  ASSERT_EQ(II->getOperand(1).getReg(), AArch64::X0);216  ASSERT_EQ(II->getOperand(2).getImm(), 2);217  ASSERT_EQ(II->getOperand(3).getImm(), 0);218  II++;219  ASSERT_EQ(II->getOpcode(), AArch64::Bcc);220  ASSERT_EQ(II->getOperand(0).getImm(), AArch64CC::NE);221  const MCSymbol *Label = BC->MIB->getTargetSymbol(*II, 1);222  ASSERT_EQ(Label, BB->getLabel());223}224 225TEST_P(MCPlusBuilderTester, testAccessedRegsImplicitDef) {226  if (GetParam() != Triple::aarch64)227    GTEST_SKIP();228 229  // adds x0, x5, #42230  MCInst Inst = MCInstBuilder(AArch64::ADDSXri)231                    .addReg(AArch64::X0)232                    .addReg(AArch64::X5)233                    .addImm(42)234                    .addImm(0);235 236  assertRegMask([&](BitVector &BV) { BC->MIB->getClobberedRegs(Inst, BV); },237                {AArch64::NZCV, AArch64::W0, AArch64::X0, AArch64::W0_HI,238                 AArch64::X0_X1_X2_X3_X4_X5_X6_X7, AArch64::W0_W1,239                 AArch64::X0_X1});240 241  assertRegMask(242      [&](BitVector &BV) { BC->MIB->getTouchedRegs(Inst, BV); },243      {AArch64::NZCV, AArch64::W0, AArch64::W5, AArch64::X0, AArch64::X5,244       AArch64::W0_HI, AArch64::W5_HI, AArch64::X0_X1_X2_X3_X4_X5_X6_X7,245       AArch64::X2_X3_X4_X5_X6_X7_X8_X9, AArch64::X4_X5_X6_X7_X8_X9_X10_X11,246       AArch64::W0_W1, AArch64::W4_W5, AArch64::X0_X1, AArch64::X4_X5});247 248  assertRegMask([&](BitVector &BV) { BC->MIB->getWrittenRegs(Inst, BV); },249                {AArch64::NZCV, AArch64::W0, AArch64::X0, AArch64::W0_HI});250 251  assertRegMask([&](BitVector &BV) { BC->MIB->getUsedRegs(Inst, BV); },252                {AArch64::W5, AArch64::X5, AArch64::W5_HI});253 254  assertRegMask([&](BitVector &BV) { BC->MIB->getSrcRegs(Inst, BV); },255                {AArch64::W5, AArch64::X5, AArch64::W5_HI});256}257 258TEST_P(MCPlusBuilderTester, testAccessedRegsImplicitUse) {259  if (GetParam() != Triple::aarch64)260    GTEST_SKIP();261 262  // b.eq <label>263  MCInst Inst =264      MCInstBuilder(AArch64::Bcc)265          .addImm(AArch64CC::EQ)266          .addImm(0); // <label> - should be Expr, but immediate 0 works too.267 268  assertRegMask([&](BitVector &BV) { BC->MIB->getClobberedRegs(Inst, BV); },269                {});270 271  assertRegMask([&](BitVector &BV) { BC->MIB->getTouchedRegs(Inst, BV); },272                {AArch64::NZCV});273 274  assertRegMask([&](BitVector &BV) { BC->MIB->getWrittenRegs(Inst, BV); }, {});275 276  assertRegMask([&](BitVector &BV) { BC->MIB->getUsedRegs(Inst, BV); },277                {AArch64::NZCV});278 279  assertRegMask([&](BitVector &BV) { BC->MIB->getSrcRegs(Inst, BV); },280                {AArch64::NZCV});281}282 283TEST_P(MCPlusBuilderTester, testAccessedRegsMultipleDefs) {284  if (GetParam() != Triple::aarch64)285    GTEST_SKIP();286 287  // ldr x0, [x5], #16288  MCInst Inst = MCInstBuilder(AArch64::LDRXpost)289                    .addReg(AArch64::X5)290                    .addReg(AArch64::X0)291                    .addReg(AArch64::X5)292                    .addImm(16);293 294  assertRegMask(295      [&](BitVector &BV) { BC->MIB->getClobberedRegs(Inst, BV); },296      {AArch64::W0, AArch64::W5, AArch64::X0, AArch64::X5, AArch64::W0_HI,297       AArch64::W5_HI, AArch64::X0_X1_X2_X3_X4_X5_X6_X7,298       AArch64::X2_X3_X4_X5_X6_X7_X8_X9, AArch64::X4_X5_X6_X7_X8_X9_X10_X11,299       AArch64::W0_W1, AArch64::W4_W5, AArch64::X0_X1, AArch64::X4_X5});300 301  assertRegMask(302      [&](BitVector &BV) { BC->MIB->getTouchedRegs(Inst, BV); },303      {AArch64::W0, AArch64::W5, AArch64::X0, AArch64::X5, AArch64::W0_HI,304       AArch64::W5_HI, AArch64::X0_X1_X2_X3_X4_X5_X6_X7,305       AArch64::X2_X3_X4_X5_X6_X7_X8_X9, AArch64::X4_X5_X6_X7_X8_X9_X10_X11,306       AArch64::W0_W1, AArch64::W4_W5, AArch64::X0_X1, AArch64::X4_X5});307 308  assertRegMask([&](BitVector &BV) { BC->MIB->getWrittenRegs(Inst, BV); },309                {AArch64::W0, AArch64::X0, AArch64::W0_HI, AArch64::W5,310                 AArch64::X5, AArch64::W5_HI});311 312  assertRegMask([&](BitVector &BV) { BC->MIB->getUsedRegs(Inst, BV); },313                {AArch64::W5, AArch64::X5, AArch64::W5_HI});314 315  assertRegMask([&](BitVector &BV) { BC->MIB->getSrcRegs(Inst, BV); },316                {AArch64::W5, AArch64::X5, AArch64::W5_HI});317}318 319TEST_P(MCPlusBuilderTester, AArch64_Psign_Pauth_variants) {320  if (GetParam() != Triple::aarch64)321    GTEST_SKIP();322 323  MCInst Paciasp = MCInstBuilder(AArch64::PACIASP);324  MCInst Pacibsp = MCInstBuilder(AArch64::PACIBSP);325  ASSERT_TRUE(BC->MIB->isPSignOnLR(Paciasp));326  ASSERT_TRUE(BC->MIB->isPSignOnLR(Pacibsp));327 328  MCInst PaciaSPLR =329      MCInstBuilder(AArch64::PACIA).addReg(AArch64::LR).addReg(AArch64::SP);330  MCInst PacibSPLR =331      MCInstBuilder(AArch64::PACIB).addReg(AArch64::LR).addReg(AArch64::SP);332  ASSERT_TRUE(BC->MIB->isPSignOnLR(PaciaSPLR));333  ASSERT_TRUE(BC->MIB->isPSignOnLR(PacibSPLR));334 335  MCInst PacizaX5 = MCInstBuilder(AArch64::PACIZA).addReg(AArch64::X5);336  MCInst PacizbX5 = MCInstBuilder(AArch64::PACIZB).addReg(AArch64::X5);337  ASSERT_FALSE(BC->MIB->isPSignOnLR(PacizaX5));338  ASSERT_FALSE(BC->MIB->isPSignOnLR(PacizbX5));339 340  MCInst Paciaz = MCInstBuilder(AArch64::PACIZA).addReg(AArch64::LR);341  MCInst Pacibz = MCInstBuilder(AArch64::PACIZB).addReg(AArch64::LR);342  ASSERT_TRUE(BC->MIB->isPSignOnLR(Paciaz));343  ASSERT_TRUE(BC->MIB->isPSignOnLR(Pacibz));344 345  MCInst Pacia1716 = MCInstBuilder(AArch64::PACIA1716);346  MCInst Pacib1716 = MCInstBuilder(AArch64::PACIB1716);347  ASSERT_FALSE(BC->MIB->isPSignOnLR(Pacia1716));348  ASSERT_FALSE(BC->MIB->isPSignOnLR(Pacib1716));349 350  MCInst Pacia171615 = MCInstBuilder(AArch64::PACIA171615);351  MCInst Pacib171615 = MCInstBuilder(AArch64::PACIB171615);352  ASSERT_FALSE(BC->MIB->isPSignOnLR(Pacia171615));353  ASSERT_FALSE(BC->MIB->isPSignOnLR(Pacib171615));354 355  MCInst Autiasp = MCInstBuilder(AArch64::AUTIASP);356  MCInst Autibsp = MCInstBuilder(AArch64::AUTIBSP);357  ASSERT_TRUE(BC->MIB->isPAuthOnLR(Autiasp));358  ASSERT_TRUE(BC->MIB->isPAuthOnLR(Autibsp));359 360  MCInst AutiaSPLR =361      MCInstBuilder(AArch64::AUTIA).addReg(AArch64::LR).addReg(AArch64::SP);362  MCInst AutibSPLR =363      MCInstBuilder(AArch64::AUTIB).addReg(AArch64::LR).addReg(AArch64::SP);364  ASSERT_TRUE(BC->MIB->isPAuthOnLR(AutiaSPLR));365  ASSERT_TRUE(BC->MIB->isPAuthOnLR(AutibSPLR));366 367  MCInst AutizaX5 = MCInstBuilder(AArch64::AUTIZA).addReg(AArch64::X5);368  MCInst AutizbX5 = MCInstBuilder(AArch64::AUTIZB).addReg(AArch64::X5);369  ASSERT_FALSE(BC->MIB->isPAuthOnLR(AutizaX5));370  ASSERT_FALSE(BC->MIB->isPAuthOnLR(AutizbX5));371 372  MCInst Autiaz = MCInstBuilder(AArch64::AUTIZA).addReg(AArch64::LR);373  MCInst Autibz = MCInstBuilder(AArch64::AUTIZB).addReg(AArch64::LR);374  ASSERT_TRUE(BC->MIB->isPAuthOnLR(Autiaz));375  ASSERT_TRUE(BC->MIB->isPAuthOnLR(Autibz));376 377  MCInst Autia1716 = MCInstBuilder(AArch64::AUTIA1716);378  MCInst Autib1716 = MCInstBuilder(AArch64::AUTIB1716);379  ASSERT_FALSE(BC->MIB->isPAuthOnLR(Autia1716));380  ASSERT_FALSE(BC->MIB->isPAuthOnLR(Autib1716));381 382  MCInst Autia171615 = MCInstBuilder(AArch64::AUTIA171615);383  MCInst Autib171615 = MCInstBuilder(AArch64::AUTIB171615);384  ASSERT_FALSE(BC->MIB->isPAuthOnLR(Autia171615));385  ASSERT_FALSE(BC->MIB->isPAuthOnLR(Autib171615));386 387  MCInst Retaa = MCInstBuilder(AArch64::RETAA);388  MCInst Retab = MCInstBuilder(AArch64::RETAB);389  ASSERT_FALSE(BC->MIB->isPAuthOnLR(Retaa));390  ASSERT_FALSE(BC->MIB->isPAuthOnLR(Retab));391  ASSERT_TRUE(BC->MIB->isPAuthAndRet(Retaa));392  ASSERT_TRUE(BC->MIB->isPAuthAndRet(Retab));393}394 395#endif // AARCH64_AVAILABLE396 397#ifdef X86_AVAILABLE398 399INSTANTIATE_TEST_SUITE_P(X86, MCPlusBuilderTester,400                         ::testing::Values(Triple::x86_64));401 402TEST_P(MCPlusBuilderTester, AliasAX) {403  testRegAliases(Triple::x86_64, X86::AX,404                 {X86::RAX, X86::EAX, X86::AX, X86::AL, X86::AH});405}406 407TEST_P(MCPlusBuilderTester, AliasSmallerAX) {408  testRegAliases(Triple::x86_64, X86::AX, {X86::AX, X86::AL, X86::AH},409                 /*OnlySmaller=*/true);410}411 412TEST_P(MCPlusBuilderTester, ReplaceRegWithImm) {413  if (GetParam() != Triple::x86_64)414    GTEST_SKIP();415  BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);416  std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();417  MCInst Inst; // cmpl    %eax, %ebx418  Inst.setOpcode(X86::CMP32rr);419  Inst.addOperand(MCOperand::createReg(X86::EAX));420  Inst.addOperand(MCOperand::createReg(X86::EBX));421  auto II = BB->addInstruction(Inst);422  bool Replaced = BC->MIB->replaceRegWithImm(*II, X86::EBX, 1);423  ASSERT_TRUE(Replaced);424  ASSERT_EQ(II->getOpcode(), X86::CMP32ri8);425  ASSERT_EQ(II->getOperand(0).getReg(), X86::EAX);426  ASSERT_EQ(II->getOperand(1).getImm(), 1);427}428 429TEST_P(MCPlusBuilderTester, X86_CmpJE) {430  if (GetParam() != Triple::x86_64)431    GTEST_SKIP();432  BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);433  std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();434 435  InstructionListType Instrs =436      BC->MIB->createCmpJE(X86::EAX, 2, BB->getLabel(), BC->Ctx.get());437  BB->addInstructions(Instrs.begin(), Instrs.end());438  BB->addSuccessor(BB.get());439 440  auto II = BB->begin();441  ASSERT_EQ(II->getOpcode(), X86::CMP64ri8);442  ASSERT_EQ(II->getOperand(0).getReg(), X86::EAX);443  ASSERT_EQ(II->getOperand(1).getImm(), 2);444  II++;445  ASSERT_EQ(II->getOpcode(), X86::JCC_1);446  const MCSymbol *Label = BC->MIB->getTargetSymbol(*II, 0);447  ASSERT_EQ(Label, BB->getLabel());448  ASSERT_EQ(II->getOperand(1).getImm(), X86::COND_E);449}450 451TEST_P(MCPlusBuilderTester, X86_CmpJNE) {452  if (GetParam() != Triple::x86_64)453    GTEST_SKIP();454  BinaryFunction *BF = BC->createInjectedBinaryFunction("BF", true);455  std::unique_ptr<BinaryBasicBlock> BB = BF->createBasicBlock();456 457  InstructionListType Instrs =458      BC->MIB->createCmpJNE(X86::EAX, 2, BB->getLabel(), BC->Ctx.get());459  BB->addInstructions(Instrs.begin(), Instrs.end());460  BB->addSuccessor(BB.get());461 462  auto II = BB->begin();463  ASSERT_EQ(II->getOpcode(), X86::CMP64ri8);464  ASSERT_EQ(II->getOperand(0).getReg(), X86::EAX);465  ASSERT_EQ(II->getOperand(1).getImm(), 2);466  II++;467  ASSERT_EQ(II->getOpcode(), X86::JCC_1);468  const MCSymbol *Label = BC->MIB->getTargetSymbol(*II, 0);469  ASSERT_EQ(Label, BB->getLabel());470  ASSERT_EQ(II->getOperand(1).getImm(), X86::COND_NE);471}472 473#endif // X86_AVAILABLE474 475TEST_P(MCPlusBuilderTester, Annotation) {476  MCInst Inst;477  BC->MIB->createTailCall(Inst, BC->Ctx->createNamedTempSymbol(),478                          BC->Ctx.get());479  MCSymbol *LPSymbol = BC->Ctx->createNamedTempSymbol("LP");480  uint64_t Value = INT32_MIN;481  // Test encodeAnnotationImm using this indirect way482  BC->MIB->addEHInfo(Inst, MCPlus::MCLandingPad(LPSymbol, Value));483  // Round-trip encoding-decoding check for negative values484  std::optional<MCPlus::MCLandingPad> EHInfo = BC->MIB->getEHInfo(Inst);485  ASSERT_TRUE(EHInfo.has_value());486  MCPlus::MCLandingPad LP = EHInfo.value();487  uint64_t DecodedValue = LP.second;488  ASSERT_EQ(Value, DecodedValue);489 490  // Large int64 should trigger an out of range assertion491  Value = 0x1FF'FFFF'FFFF'FFFFULL;492  Inst.clear();493  BC->MIB->createTailCall(Inst, BC->Ctx->createNamedTempSymbol(),494                          BC->Ctx.get());495  ASSERT_DEATH(BC->MIB->addEHInfo(Inst, MCPlus::MCLandingPad(LPSymbol, Value)),496               "annotation value out of range");497}498