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<TargetMachine> 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   assert(TheTarget && "Target not registered");
25 
26   return std::unique_ptr<TargetMachine>(
27       TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), None,
28                                      CodeModel::Default, CodeGenOpt::Default));
29 }
30 
31 std::unique_ptr<AArch64InstrInfo> createInstrInfo(TargetMachine *TM) {
32   AArch64Subtarget ST(TM->getTargetTriple(), TM->getTargetCPU(),
33                       TM->getTargetFeatureString(), *TM, /* isLittle */ false);
34   return llvm::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.
41 void runChecks(
42     TargetMachine *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(MParser && "Couldn't create MIR parser");
62 
63   std::unique_ptr<Module> M = MParser->parseLLVMModule();
64   assert(M && "Couldn't parse module");
65 
66   M->setTargetTriple(TM->getTargetTriple().getTriple());
67   M->setDataLayout(TM->createDataLayout());
68 
69   auto F = M->getFunction("sizes");
70   assert(F && "Couldn't find intended function");
71 
72   MachineModuleInfo MMI(TM);
73   MMI.setMachineFunctionInitializer(MParser.get());
74   auto &MF = MMI.getMachineFunction(*F);
75 
76   Checks(*II, MF);
77 }
78 
79 } // anonymous namespace
80 
81 TEST(InstSizes, STACKMAP) {
82   std::unique_ptr<TargetMachine> TM = createTargetMachine();
83   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
84 
85   runChecks(TM.get(), II.get(), "", "    STACKMAP 0, 16\n"
86                                     "    STACKMAP 1, 32\n",
87             [](AArch64InstrInfo &II, MachineFunction &MF) {
88               auto I = MF.begin()->begin();
89               EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
90               ++I;
91               EXPECT_EQ(32u, II.getInstSizeInBytes(*I));
92             });
93 }
94 
95 TEST(InstSizes, PATCHPOINT) {
96   std::unique_ptr<TargetMachine> TM = createTargetMachine();
97   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
98 
99   runChecks(TM.get(), II.get(), "",
100             "    PATCHPOINT 0, 16, 0, 0, 0, csr_aarch64_aapcs\n"
101             "    PATCHPOINT 1, 32, 0, 0, 0, csr_aarch64_aapcs\n",
102             [](AArch64InstrInfo &II, MachineFunction &MF) {
103               auto I = MF.begin()->begin();
104               EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
105               ++I;
106               EXPECT_EQ(32u, II.getInstSizeInBytes(*I));
107             });
108 }
109 
110 TEST(InstSizes, TLSDESC_CALLSEQ) {
111   std::unique_ptr<TargetMachine> TM = createTargetMachine();
112   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
113 
114   runChecks(
115       TM.get(), II.get(),
116       "  @ThreadLocalGlobal = external thread_local global i32, align 8\n",
117       "    TLSDESC_CALLSEQ target-flags(aarch64-tls) @ThreadLocalGlobal\n",
118       [](AArch64InstrInfo &II, MachineFunction &MF) {
119         auto I = MF.begin()->begin();
120         EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
121       });
122 }
123