xref: /llvm-project/llvm/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h (revision c30340b207493bc61acdea202dfda882be92df02)
1 //===-- AssemblerUtils.h ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_UNITTESTS_TOOLS_LLVMEXEGESIS_ASSEMBLERUTILS_H
11 #define LLVM_UNITTESTS_TOOLS_LLVMEXEGESIS_ASSEMBLERUTILS_H
12 
13 #include "Assembler.h"
14 #include "BenchmarkRunner.h"
15 #include "Target.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/TargetInstrInfo.h"
19 #include "llvm/CodeGen/TargetSubtargetInfo.h"
20 #include "llvm/MC/MCInstBuilder.h"
21 #include "llvm/Support/Host.h"
22 #include "llvm/Support/TargetRegistry.h"
23 #include "llvm/Support/TargetSelect.h"
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 
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     if (!CanExecute) {
37       llvm::outs() << "Skipping execution, host:"
38                    << llvm::sys::getProcessTriple() << ", target:" << TT
39                    << "\n";
40     }
41   }
42 
43   template <class... Bs>
44   inline void Check(const ExegesisTarget &ET,
45                     llvm::ArrayRef<unsigned> RegsToDef, llvm::MCInst MCInst,
46                     Bs... Bytes) {
47     ExecutableFunction Function =
48         (MCInst.getOpcode() == 0) ? assembleToFunction(ET, RegsToDef, {})
49                                   : assembleToFunction(ET, RegsToDef, {MCInst});
50     ASSERT_THAT(Function.getFunctionBytes().str(),
51                 testing::ElementsAre(Bytes...));
52     if (CanExecute) {
53       BenchmarkRunner::ScratchSpace Scratch;
54       Function(Scratch.ptr());
55     }
56   }
57 
58 private:
59   std::unique_ptr<llvm::LLVMTargetMachine> createTargetMachine() {
60     std::string Error;
61     const llvm::Target *TheTarget =
62         llvm::TargetRegistry::lookupTarget(TT, Error);
63     EXPECT_TRUE(TheTarget) << Error << " " << TT;
64     const llvm::TargetOptions Options;
65     llvm::TargetMachine *TM = TheTarget->createTargetMachine(
66         TT, CpuName, "", Options, llvm::Reloc::Model::Static);
67     EXPECT_TRUE(TM) << TT << " " << CpuName;
68     return std::unique_ptr<llvm::LLVMTargetMachine>(
69         static_cast<llvm::LLVMTargetMachine *>(TM));
70   }
71 
72   ExecutableFunction
73   assembleToFunction(const ExegesisTarget &ET,
74                      llvm::ArrayRef<unsigned> RegsToDef,
75                      llvm::ArrayRef<llvm::MCInst> Instructions) {
76     llvm::SmallString<256> Buffer;
77     llvm::raw_svector_ostream AsmStream(Buffer);
78     assembleToStream(ET, createTargetMachine(), /*LiveIns=*/{},
79                      RegsToDef, Instructions,
80                      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 };
89 
90 } // namespace exegesis
91 
92 #endif
93