xref: /llvm-project/llvm/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h (revision bb3f5e1fed7c6ba733b7f273e93f5d3930976185)
1 //===-- AssemblerUtils.h ----------------------------------------*- C++ -*-===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_UNITTESTS_TOOLS_LLVMEXEGESIS_ASSEMBLERUTILS_H
10 #define LLVM_UNITTESTS_TOOLS_LLVMEXEGESIS_ASSEMBLERUTILS_H
11 
12 #include "Assembler.h"
13 #include "BenchmarkRunner.h"
14 #include "Target.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/CodeGen/MachineInstrBuilder.h"
17 #include "llvm/CodeGen/TargetInstrInfo.h"
18 #include "llvm/CodeGen/TargetSubtargetInfo.h"
19 #include "llvm/MC/MCInstBuilder.h"
20 #include "llvm/MC/TargetRegistry.h"
21 #include "llvm/Support/TargetSelect.h"
22 #include "llvm/TargetParser/Host.h"
23 #include "llvm/Testing/Support/Error.h"
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 
27 namespace llvm {
28 namespace exegesis {
29 
30 class MachineFunctionGeneratorBaseTest : public ::testing::Test {
31 protected:
32   MachineFunctionGeneratorBaseTest(const std::string &TT,
33                                    const std::string &CpuName)
34       : TT(TT), CpuName(CpuName),
35         CanExecute(Triple(TT).getArch() ==
36                    Triple(sys::getProcessTriple()).getArch()),
37         ET(ExegesisTarget::lookup(Triple(TT))) {
38     assert(ET);
39     if (!CanExecute) {
40       outs() << "Skipping execution, host:" << sys::getProcessTriple()
41              << ", target:" << TT << "\n";
42     }
43   }
44 
45   template <class... Bs>
46   inline void Check(ArrayRef<RegisterValue> RegisterInitialValues, MCInst Inst,
47                     Bs... Bytes) {
48     ExecutableFunction Function =
49         (Inst.getOpcode() == 0)
50             ? assembleToFunction(RegisterInitialValues, [](FunctionFiller &) {})
51             : assembleToFunction(RegisterInitialValues,
52                                  [Inst](FunctionFiller &Filler) {
53                                    Filler.getEntry().addInstruction(Inst);
54                                  });
55     ASSERT_THAT(Function.getFunctionBytes().str(),
56                 testing::ElementsAre(Bytes...));
57     if (CanExecute) {
58       BenchmarkRunner::ScratchSpace Scratch;
59       Function(Scratch.ptr());
60     }
61   }
62 
63 private:
64   std::unique_ptr<TargetMachine> createTargetMachine() {
65     std::string Error;
66     const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
67     EXPECT_TRUE(TheTarget) << Error << " " << TT;
68     const TargetOptions Options;
69     TargetMachine *TM = TheTarget->createTargetMachine(TT, CpuName, "", Options,
70                                                        Reloc::Model::Static);
71     EXPECT_TRUE(TM) << TT << " " << CpuName;
72     return std::unique_ptr<TargetMachine>(TM);
73   }
74 
75   ExecutableFunction
76   assembleToFunction(ArrayRef<RegisterValue> RegisterInitialValues,
77                      FillFunction Fill) {
78     SmallString<256> Buffer;
79     raw_svector_ostream AsmStream(Buffer);
80     BenchmarkKey Key;
81     Key.RegisterInitialValues = RegisterInitialValues;
82     EXPECT_FALSE(assembleToStream(*ET, createTargetMachine(), /*LiveIns=*/{},
83                                   Fill, AsmStream, Key, false));
84     Expected<ExecutableFunction> ExecFunc = ExecutableFunction::create(
85         createTargetMachine(), getObjectFromBuffer(AsmStream.str()));
86 
87     // We can't use ASSERT_THAT_EXPECTED here as it doesn't work inside of
88     // non-void functions.
89     EXPECT_TRUE(detail::TakeExpected(ExecFunc).Success());
90     return std::move(*ExecFunc);
91   }
92 
93   const std::string TT;
94   const std::string CpuName;
95   const bool CanExecute;
96   const ExegesisTarget *const ET;
97 };
98 
99 } // namespace exegesis
100 } // namespace llvm
101 
102 #endif
103