• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
MachineFunctionGeneratorBaseTest(const std::string & TT,const std::string & CpuName)31   MachineFunctionGeneratorBaseTest(const std::string &TT,
32                                    const std::string &CpuName)
33       : TT(TT), CpuName(CpuName),
34         CanExecute(Triple(TT).getArch() ==
35                    Triple(sys::getProcessTriple()).getArch()),
36         ET(ExegesisTarget::lookup(Triple(TT))) {
37     assert(ET);
38     if (!CanExecute) {
39       outs() << "Skipping execution, host:" << sys::getProcessTriple()
40              << ", target:" << TT << "\n";
41     }
42   }
43 
44   template <class... Bs>
Check(ArrayRef<RegisterValue> RegisterInitialValues,MCInst Inst,Bs...Bytes)45   inline void Check(ArrayRef<RegisterValue> RegisterInitialValues, MCInst Inst,
46                     Bs... Bytes) {
47     ExecutableFunction Function =
48         (Inst.getOpcode() == 0)
49             ? assembleToFunction(RegisterInitialValues, [](FunctionFiller &) {})
50             : assembleToFunction(RegisterInitialValues,
51                                  [Inst](FunctionFiller &Filler) {
52                                    Filler.getEntry().addInstruction(Inst);
53                                  });
54     ASSERT_THAT(Function.getFunctionBytes().str(),
55                 testing::ElementsAre(Bytes...));
56     if (CanExecute) {
57       BenchmarkRunner::ScratchSpace Scratch;
58       Function(Scratch.ptr());
59     }
60   }
61 
62 private:
createTargetMachine()63   std::unique_ptr<LLVMTargetMachine> createTargetMachine() {
64     std::string Error;
65     const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
66     EXPECT_TRUE(TheTarget) << Error << " " << TT;
67     const TargetOptions Options;
68     TargetMachine *TM = TheTarget->createTargetMachine(TT, CpuName, "", Options,
69                                                        Reloc::Model::Static);
70     EXPECT_TRUE(TM) << TT << " " << CpuName;
71     return std::unique_ptr<LLVMTargetMachine>(
72         static_cast<LLVMTargetMachine *>(TM));
73   }
74 
75   ExecutableFunction
assembleToFunction(ArrayRef<RegisterValue> RegisterInitialValues,FillFunction Fill)76   assembleToFunction(ArrayRef<RegisterValue> RegisterInitialValues,
77                      FillFunction Fill) {
78     SmallString<256> Buffer;
79     raw_svector_ostream AsmStream(Buffer);
80     EXPECT_FALSE(assembleToStream(*ET, createTargetMachine(), /*LiveIns=*/{},
81                                   RegisterInitialValues, Fill, AsmStream));
82     return ExecutableFunction(createTargetMachine(),
83                               getObjectFromBuffer(AsmStream.str()));
84   }
85 
86   const std::string TT;
87   const std::string CpuName;
88   const bool CanExecute;
89   const ExegesisTarget *const ET;
90 };
91 
92 } // namespace exegesis
93 } // namespace llvm
94 
95 #endif
96