1 #include "AArch64Subtarget.h"
2 #include "AArch64TargetMachine.h"
3 #include "llvm/CodeGen/MIRParser/MIRParser.h"
4 #include "llvm/CodeGen/MachineModuleInfo.h"
5 #include "llvm/Support/TargetRegistry.h"
6 #include "llvm/Support/TargetSelect.h"
7
8 #include "gtest/gtest.h"
9
10 using namespace llvm;
11
12 namespace {
createTargetMachine()13 std::unique_ptr<LLVMTargetMachine> createTargetMachine() {
14 auto TT(Triple::normalize("aarch64--"));
15 std::string CPU("generic");
16 std::string FS("");
17
18 LLVMInitializeAArch64TargetInfo();
19 LLVMInitializeAArch64Target();
20 LLVMInitializeAArch64TargetMC();
21
22 std::string Error;
23 const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
24
25 return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine*>(
26 TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), None, None,
27 CodeGenOpt::Default)));
28 }
29
createInstrInfo(TargetMachine * TM)30 std::unique_ptr<AArch64InstrInfo> createInstrInfo(TargetMachine *TM) {
31 AArch64Subtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
32 std::string(TM->getTargetFeatureString()), *TM,
33 /* isLittle */ false);
34 return std::make_unique<AArch64InstrInfo>(ST);
35 }
36
37 /// The \p InputIRSnippet is only needed for things that can't be expressed in
38 /// the \p InputMIRSnippet (global variables etc)
39 /// TODO: Some of this might be useful for other architectures as well - extract
40 /// the platform-independent parts somewhere they can be reused.
runChecks(LLVMTargetMachine * TM,AArch64InstrInfo * II,const StringRef InputIRSnippet,const StringRef InputMIRSnippet,std::function<void (AArch64InstrInfo &,MachineFunction &)> Checks)41 void runChecks(
42 LLVMTargetMachine *TM, AArch64InstrInfo *II, const StringRef InputIRSnippet,
43 const StringRef InputMIRSnippet,
44 std::function<void(AArch64InstrInfo &, MachineFunction &)> Checks) {
45 LLVMContext Context;
46
47 auto MIRString =
48 "--- |\n"
49 " declare void @sizes()\n"
50 + InputIRSnippet.str() +
51 "...\n"
52 "---\n"
53 "name: sizes\n"
54 "body: |\n"
55 " bb.0:\n"
56 + InputMIRSnippet.str();
57
58 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString);
59 std::unique_ptr<MIRParser> MParser =
60 createMIRParser(std::move(MBuffer), Context);
61 ASSERT_TRUE(MParser);
62
63 std::unique_ptr<Module> M = MParser->parseIRModule();
64 ASSERT_TRUE(M);
65
66 M->setTargetTriple(TM->getTargetTriple().getTriple());
67 M->setDataLayout(TM->createDataLayout());
68
69 MachineModuleInfo MMI(TM);
70 bool Res = MParser->parseMachineFunctions(*M, MMI);
71 ASSERT_FALSE(Res);
72
73 auto F = M->getFunction("sizes");
74 ASSERT_TRUE(F != nullptr);
75 auto &MF = MMI.getOrCreateMachineFunction(*F);
76
77 Checks(*II, MF);
78 }
79
80 } // anonymous namespace
81
TEST(InstSizes,Authenticated)82 TEST(InstSizes, Authenticated) {
83 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
84 ASSERT_TRUE(TM);
85 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
86
87 auto isAuthInst = [](AArch64InstrInfo &II, MachineFunction &MF) {
88 auto I = MF.begin()->begin();
89 EXPECT_EQ(4u, II.getInstSizeInBytes(*I));
90 EXPECT_TRUE(I->getDesc().isAuthenticated());
91 };
92
93 runChecks(TM.get(), II.get(), "",
94 " \n"
95 " BLRAA $x10, $x9\n",
96 isAuthInst);
97
98 runChecks(TM.get(), II.get(), "",
99 " \n"
100 " RETAB implicit $lr, implicit $sp, implicit killed $x0\n",
101 isAuthInst);
102
103 runChecks(TM.get(), II.get(), "",
104 " \n"
105 " frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp\n",
106 isAuthInst);
107
108 runChecks(TM.get(), II.get(), "",
109 " \n"
110 " frame-destroy AUTIBSP implicit-def $lr, implicit killed $lr, implicit $sp\n",
111 isAuthInst);
112 }
113
TEST(InstSizes,STACKMAP)114 TEST(InstSizes, STACKMAP) {
115 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
116 ASSERT_TRUE(TM);
117 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
118
119 runChecks(TM.get(), II.get(), "", " STACKMAP 0, 16\n"
120 " STACKMAP 1, 32\n",
121 [](AArch64InstrInfo &II, MachineFunction &MF) {
122 auto I = MF.begin()->begin();
123 EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
124 ++I;
125 EXPECT_EQ(32u, II.getInstSizeInBytes(*I));
126 });
127 }
128
TEST(InstSizes,PATCHPOINT)129 TEST(InstSizes, PATCHPOINT) {
130 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
131 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
132
133 runChecks(TM.get(), II.get(), "",
134 " PATCHPOINT 0, 16, 0, 0, 0, csr_aarch64_aapcs\n"
135 " PATCHPOINT 1, 32, 0, 0, 0, csr_aarch64_aapcs\n",
136 [](AArch64InstrInfo &II, MachineFunction &MF) {
137 auto I = MF.begin()->begin();
138 EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
139 ++I;
140 EXPECT_EQ(32u, II.getInstSizeInBytes(*I));
141 });
142 }
143
TEST(InstSizes,TLSDESC_CALLSEQ)144 TEST(InstSizes, TLSDESC_CALLSEQ) {
145 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
146 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
147
148 runChecks(
149 TM.get(), II.get(),
150 " @ThreadLocalGlobal = external thread_local global i32, align 8\n",
151 " TLSDESC_CALLSEQ target-flags(aarch64-tls) @ThreadLocalGlobal\n",
152 [](AArch64InstrInfo &II, MachineFunction &MF) {
153 auto I = MF.begin()->begin();
154 EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
155 });
156 }
157