xref: /llvm-project/llvm/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h (revision 2946cd701067404b99c39fb29dc9c74bd7193eb3)
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/Support/Host.h"
21 #include "llvm/Support/TargetRegistry.h"
22 #include "llvm/Support/TargetSelect.h"
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 
26 namespace llvm {
27 namespace exegesis {
28 
29 class MachineFunctionGeneratorBaseTest : public ::testing::Test {
30 protected:
31   MachineFunctionGeneratorBaseTest(const std::string &TT,
32                                    const std::string &CpuName)
33       : TT(TT), CpuName(CpuName),
34         CanExecute(llvm::Triple(TT).getArch() ==
35                    llvm::Triple(llvm::sys::getProcessTriple()).getArch()),
36         ET(ExegesisTarget::lookup(llvm::Triple(TT))) {
37     assert(ET);
38     if (!CanExecute) {
39       llvm::outs() << "Skipping execution, host:"
40                    << llvm::sys::getProcessTriple() << ", target:" << TT
41                    << "\n";
42     }
43   }
44 
45   template <class... Bs>
46   inline void Check(llvm::ArrayRef<RegisterValue> RegisterInitialValues,
47                     llvm::MCInst MCInst, Bs... Bytes) {
48     ExecutableFunction Function =
49         (MCInst.getOpcode() == 0)
50             ? assembleToFunction(RegisterInitialValues, {})
51             : assembleToFunction(RegisterInitialValues, {MCInst});
52     ASSERT_THAT(Function.getFunctionBytes().str(),
53                 testing::ElementsAre(Bytes...));
54     if (CanExecute) {
55       BenchmarkRunner::ScratchSpace Scratch;
56       Function(Scratch.ptr());
57     }
58   }
59 
60 private:
61   std::unique_ptr<llvm::LLVMTargetMachine> createTargetMachine() {
62     std::string Error;
63     const llvm::Target *TheTarget =
64         llvm::TargetRegistry::lookupTarget(TT, Error);
65     EXPECT_TRUE(TheTarget) << Error << " " << TT;
66     const llvm::TargetOptions Options;
67     llvm::TargetMachine *TM = TheTarget->createTargetMachine(
68         TT, CpuName, "", Options, llvm::Reloc::Model::Static);
69     EXPECT_TRUE(TM) << TT << " " << CpuName;
70     return std::unique_ptr<llvm::LLVMTargetMachine>(
71         static_cast<llvm::LLVMTargetMachine *>(TM));
72   }
73 
74   ExecutableFunction
75   assembleToFunction(llvm::ArrayRef<RegisterValue> RegisterInitialValues,
76                      llvm::ArrayRef<llvm::MCInst> Instructions) {
77     llvm::SmallString<256> Buffer;
78     llvm::raw_svector_ostream AsmStream(Buffer);
79     assembleToStream(*ET, createTargetMachine(), /*LiveIns=*/{},
80                      RegisterInitialValues, Instructions, AsmStream);
81     return ExecutableFunction(createTargetMachine(),
82                               getObjectFromBuffer(AsmStream.str()));
83   }
84 
85   const std::string TT;
86   const std::string CpuName;
87   const bool CanExecute;
88   const ExegesisTarget *const ET;
89 };
90 
91 } // namespace exegesis
92 } // namespace llvm
93 
94 #endif
95