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 {
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 
30 std::unique_ptr<AArch64InstrInfo> createInstrInfo(TargetMachine *TM) {
31   AArch64Subtarget ST(TM->getTargetTriple(), TM->getTargetCPU(),
32                       TM->getTargetFeatureString(), *TM, /* isLittle */ false);
33   return std::make_unique<AArch64InstrInfo>(ST);
34 }
35 
36 /// The \p InputIRSnippet is only needed for things that can't be expressed in
37 /// the \p InputMIRSnippet (global variables etc)
38 /// TODO: Some of this might be useful for other architectures as well - extract
39 ///       the platform-independent parts somewhere they can be reused.
40 void runChecks(
41     LLVMTargetMachine *TM, AArch64InstrInfo *II, const StringRef InputIRSnippet,
42     const StringRef InputMIRSnippet,
43     std::function<void(AArch64InstrInfo &, MachineFunction &)> Checks) {
44   LLVMContext Context;
45 
46   auto MIRString =
47     "--- |\n"
48     "  declare void @sizes()\n"
49     + InputIRSnippet.str() +
50     "...\n"
51     "---\n"
52     "name: sizes\n"
53     "body: |\n"
54     "  bb.0:\n"
55     + InputMIRSnippet.str();
56 
57   std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString);
58   std::unique_ptr<MIRParser> MParser =
59       createMIRParser(std::move(MBuffer), Context);
60   ASSERT_TRUE(MParser);
61 
62   std::unique_ptr<Module> M = MParser->parseIRModule();
63   ASSERT_TRUE(M);
64 
65   M->setTargetTriple(TM->getTargetTriple().getTriple());
66   M->setDataLayout(TM->createDataLayout());
67 
68   MachineModuleInfo MMI(TM);
69   bool Res = MParser->parseMachineFunctions(*M, MMI);
70   ASSERT_FALSE(Res);
71 
72   auto F = M->getFunction("sizes");
73   ASSERT_TRUE(F != nullptr);
74   auto &MF = MMI.getOrCreateMachineFunction(*F);
75 
76   Checks(*II, MF);
77 }
78 
79 } // anonymous namespace
80 
81 TEST(InstSizes, STACKMAP) {
82   std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
83   ASSERT_TRUE(TM);
84   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
85 
86   runChecks(TM.get(), II.get(), "", "    STACKMAP 0, 16\n"
87                                     "    STACKMAP 1, 32\n",
88             [](AArch64InstrInfo &II, MachineFunction &MF) {
89               auto I = MF.begin()->begin();
90               EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
91               ++I;
92               EXPECT_EQ(32u, II.getInstSizeInBytes(*I));
93             });
94 }
95 
96 TEST(InstSizes, PATCHPOINT) {
97   std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
98   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
99 
100   runChecks(TM.get(), II.get(), "",
101             "    PATCHPOINT 0, 16, 0, 0, 0, csr_aarch64_aapcs\n"
102             "    PATCHPOINT 1, 32, 0, 0, 0, csr_aarch64_aapcs\n",
103             [](AArch64InstrInfo &II, MachineFunction &MF) {
104               auto I = MF.begin()->begin();
105               EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
106               ++I;
107               EXPECT_EQ(32u, II.getInstSizeInBytes(*I));
108             });
109 }
110 
111 TEST(InstSizes, TLSDESC_CALLSEQ) {
112   std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
113   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
114 
115   runChecks(
116       TM.get(), II.get(),
117       "  @ThreadLocalGlobal = external thread_local global i32, align 8\n",
118       "    TLSDESC_CALLSEQ target-flags(aarch64-tls) @ThreadLocalGlobal\n",
119       [](AArch64InstrInfo &II, MachineFunction &MF) {
120         auto I = MF.begin()->begin();
121         EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
122       });
123 }
124