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