//===- MCInstrAnalysisTest.cpp - AArch64MCInstrAnalysis unit tests --------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/MC/MCInstrAnalysis.h" #include "MCTargetDesc/AArch64MCTargetDesc.h" #include "Utils/AArch64BaseInfo.h" #include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "gtest/gtest.h" #include using namespace llvm; namespace { class InstrAnalysisTest : public testing::TestWithParam { protected: std::unique_ptr Info; std::unique_ptr Analysis; static void SetUpTestSuite() { LLVMInitializeAArch64TargetInfo(); LLVMInitializeAArch64Target(); LLVMInitializeAArch64TargetMC(); } InstrAnalysisTest() { std::string Error; Triple TT(Triple::normalize(GetParam())); const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); Info = std::unique_ptr(TheTarget->createMCInstrInfo()); Analysis = std::unique_ptr( TheTarget->createMCInstrAnalysis(Info.get())); } }; } // namespace static MCInst beq() { return MCInstBuilder(AArch64::Bcc).addImm(AArch64CC::EQ).addReg(AArch64::X0); } static MCInst tbz(unsigned Rt = AArch64::X0, unsigned Imm = 0, unsigned Label = 32) { return MCInstBuilder(AArch64::TBZX).addReg(Rt).addImm(Imm).addImm(Label); } static MCInst cbz(unsigned Rt = AArch64::X0, unsigned Label = 32) { return MCInstBuilder(AArch64::CBZX).addReg(Rt).addImm(Label); } static MCInst b() { return MCInstBuilder(AArch64::B).addImm(32); } static MCInst bl() { return MCInstBuilder(AArch64::BL).addImm(32); } static MCInst br(unsigned Rn = AArch64::X0) { return MCInstBuilder(AArch64::BR).addReg(Rn); } static MCInst blr(unsigned Rn = AArch64::X0) { return MCInstBuilder(AArch64::BLR).addReg(Rn); } static MCInst ret(unsigned Rn = AArch64::LR) { return MCInstBuilder(AArch64::RET).addReg(Rn); } static MCInst retaa() { return MCInstBuilder(AArch64::RETAA); } static MCInst eret() { return MCInstBuilder(AArch64::ERET); } static MCInst hlt() { return MCInstBuilder(AArch64::HLT); } static MCInst brk() { return MCInstBuilder(AArch64::BRK); } static MCInst svc() { return MCInstBuilder(AArch64::SVC); } static MCInst hvc() { return MCInstBuilder(AArch64::HVC); } static MCInst smc() { return MCInstBuilder(AArch64::SMC); } TEST_P(InstrAnalysisTest, IsTerminator) { EXPECT_TRUE(Analysis->isTerminator(beq())); EXPECT_TRUE(Analysis->isTerminator(tbz())); EXPECT_TRUE(Analysis->isTerminator(cbz())); EXPECT_TRUE(Analysis->isTerminator(b())); EXPECT_FALSE(Analysis->isTerminator(bl())); EXPECT_FALSE(Analysis->isTerminator(blr())); EXPECT_TRUE(Analysis->isTerminator(br())); EXPECT_TRUE(Analysis->isTerminator(ret())); EXPECT_TRUE(Analysis->isTerminator(retaa())); EXPECT_TRUE(Analysis->isTerminator(eret())); EXPECT_FALSE(Analysis->isTerminator(hlt())); EXPECT_FALSE(Analysis->isTerminator(brk())); EXPECT_FALSE(Analysis->isTerminator(svc())); EXPECT_FALSE(Analysis->isTerminator(hvc())); EXPECT_FALSE(Analysis->isTerminator(smc())); } TEST_P(InstrAnalysisTest, IsBarrier) { EXPECT_FALSE(Analysis->isBarrier(beq())); EXPECT_FALSE(Analysis->isBarrier(tbz())); EXPECT_FALSE(Analysis->isBarrier(cbz())); EXPECT_TRUE(Analysis->isBarrier(b())); EXPECT_FALSE(Analysis->isBarrier(bl())); EXPECT_FALSE(Analysis->isBarrier(blr())); EXPECT_TRUE(Analysis->isBarrier(br())); EXPECT_TRUE(Analysis->isBarrier(ret())); EXPECT_TRUE(Analysis->isBarrier(retaa())); EXPECT_TRUE(Analysis->isBarrier(eret())); EXPECT_FALSE(Analysis->isBarrier(hlt())); EXPECT_FALSE(Analysis->isBarrier(brk())); EXPECT_FALSE(Analysis->isBarrier(svc())); EXPECT_FALSE(Analysis->isBarrier(hvc())); EXPECT_FALSE(Analysis->isBarrier(smc())); } TEST_P(InstrAnalysisTest, IsCall) { EXPECT_FALSE(Analysis->isCall(beq())); EXPECT_FALSE(Analysis->isCall(tbz())); EXPECT_FALSE(Analysis->isCall(cbz())); EXPECT_FALSE(Analysis->isCall(b())); EXPECT_TRUE(Analysis->isCall(bl())); EXPECT_TRUE(Analysis->isCall(blr())); EXPECT_FALSE(Analysis->isCall(br())); EXPECT_FALSE(Analysis->isCall(ret())); EXPECT_FALSE(Analysis->isCall(retaa())); EXPECT_FALSE(Analysis->isCall(eret())); } TEST_P(InstrAnalysisTest, IsReturn) { EXPECT_FALSE(Analysis->isReturn(beq())); EXPECT_FALSE(Analysis->isReturn(tbz())); EXPECT_FALSE(Analysis->isReturn(cbz())); EXPECT_FALSE(Analysis->isReturn(b())); EXPECT_FALSE(Analysis->isReturn(bl())); EXPECT_FALSE(Analysis->isReturn(br())); EXPECT_FALSE(Analysis->isReturn(blr())); EXPECT_FALSE(Analysis->isReturn(br(AArch64::LR))); EXPECT_TRUE(Analysis->isReturn(ret())); EXPECT_TRUE(Analysis->isReturn(retaa())); EXPECT_TRUE(Analysis->isReturn(eret())); } TEST_P(InstrAnalysisTest, IsBranch) { EXPECT_TRUE(Analysis->isBranch(beq())); EXPECT_TRUE(Analysis->isBranch(tbz())); EXPECT_TRUE(Analysis->isBranch(cbz())); EXPECT_TRUE(Analysis->isBranch(b())); EXPECT_FALSE(Analysis->isBranch(bl())); EXPECT_FALSE(Analysis->isBranch(blr())); EXPECT_TRUE(Analysis->isBranch(br())); EXPECT_FALSE(Analysis->isBranch(ret())); EXPECT_FALSE(Analysis->isBranch(retaa())); EXPECT_FALSE(Analysis->isBranch(eret())); } TEST_P(InstrAnalysisTest, IsConditionalBranch) { EXPECT_TRUE(Analysis->isConditionalBranch(beq())); EXPECT_TRUE(Analysis->isConditionalBranch(tbz())); EXPECT_TRUE(Analysis->isConditionalBranch(cbz())); EXPECT_FALSE(Analysis->isConditionalBranch(b())); EXPECT_FALSE(Analysis->isConditionalBranch(bl())); EXPECT_FALSE(Analysis->isConditionalBranch(blr())); EXPECT_FALSE(Analysis->isConditionalBranch(ret())); EXPECT_FALSE(Analysis->isConditionalBranch(retaa())); EXPECT_FALSE(Analysis->isConditionalBranch(eret())); } TEST_P(InstrAnalysisTest, IsUnconditionalBranch) { EXPECT_FALSE(Analysis->isUnconditionalBranch(beq())); EXPECT_FALSE(Analysis->isUnconditionalBranch(tbz())); EXPECT_FALSE(Analysis->isUnconditionalBranch(cbz())); EXPECT_TRUE(Analysis->isUnconditionalBranch(b())); EXPECT_FALSE(Analysis->isUnconditionalBranch(bl())); EXPECT_FALSE(Analysis->isUnconditionalBranch(blr())); EXPECT_FALSE(Analysis->isUnconditionalBranch(br())); EXPECT_FALSE(Analysis->isUnconditionalBranch(ret())); EXPECT_FALSE(Analysis->isUnconditionalBranch(retaa())); EXPECT_FALSE(Analysis->isUnconditionalBranch(eret())); } TEST_P(InstrAnalysisTest, IsIndirectBranch) { EXPECT_FALSE(Analysis->isIndirectBranch(beq())); EXPECT_FALSE(Analysis->isIndirectBranch(tbz())); EXPECT_FALSE(Analysis->isIndirectBranch(cbz())); EXPECT_FALSE(Analysis->isIndirectBranch(b())); EXPECT_FALSE(Analysis->isIndirectBranch(bl())); EXPECT_FALSE(Analysis->isIndirectBranch(blr())); EXPECT_TRUE(Analysis->isIndirectBranch(br())); EXPECT_FALSE(Analysis->isIndirectBranch(ret())); EXPECT_FALSE(Analysis->isIndirectBranch(retaa())); EXPECT_FALSE(Analysis->isIndirectBranch(eret())); } INSTANTIATE_TEST_SUITE_P(AArch64, InstrAnalysisTest, testing::Values("aarch64"));