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 #include "Assembler.h"
11 #include "Target.h"
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/CodeGen/MachineInstrBuilder.h"
14 #include "llvm/CodeGen/TargetInstrInfo.h"
15 #include "llvm/CodeGen/TargetSubtargetInfo.h"
16 #include "llvm/MC/MCInstBuilder.h"
17 #include "llvm/Support/Host.h"
18 #include "llvm/Support/TargetRegistry.h"
19 #include "llvm/Support/TargetSelect.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 
23 namespace exegesis {
24 
25 class MachineFunctionGeneratorBaseTest : public ::testing::Test {
26 protected:
MachineFunctionGeneratorBaseTest(const std::string & TT,const std::string & CpuName)27   MachineFunctionGeneratorBaseTest(const std::string &TT,
28                                    const std::string &CpuName)
29       : TT(TT), CpuName(CpuName),
30         CanExecute(llvm::Triple(TT).getArch() ==
31                    llvm::Triple(llvm::sys::getProcessTriple()).getArch()) {
32     if (!CanExecute) {
33       llvm::outs() << "Skipping execution, host:"
34                    << llvm::sys::getProcessTriple() << ", target:" << TT
35                    << "\n";
36     }
37   }
38 
Check(llvm::MCInst MCInst,Bs...Bytes)39   template <class... Bs> inline void Check(llvm::MCInst MCInst, Bs... Bytes) {
40     CheckWithSetup(ExegesisTarget::getDefault(), {}, MCInst, Bytes...);
41   }
42 
43   template <class... Bs>
CheckWithSetup(const ExegesisTarget & ET,llvm::ArrayRef<unsigned> RegsToDef,llvm::MCInst MCInst,Bs...Bytes)44   inline void CheckWithSetup(const ExegesisTarget &ET,
45                              llvm::ArrayRef<unsigned> RegsToDef,
46                              llvm::MCInst MCInst, 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       Function();
54   }
55 
56 private:
createTargetMachine()57   std::unique_ptr<llvm::LLVMTargetMachine> createTargetMachine() {
58     std::string Error;
59     const llvm::Target *TheTarget =
60         llvm::TargetRegistry::lookupTarget(TT, Error);
61     EXPECT_TRUE(TheTarget) << Error << " " << TT;
62     const llvm::TargetOptions Options;
63     llvm::TargetMachine *TM = TheTarget->createTargetMachine(
64         TT, CpuName, "", Options, llvm::Reloc::Model::Static);
65     EXPECT_TRUE(TM) << TT << " " << CpuName;
66     return std::unique_ptr<llvm::LLVMTargetMachine>(
67         static_cast<llvm::LLVMTargetMachine *>(TM));
68   }
69 
70   ExecutableFunction
assembleToFunction(const ExegesisTarget & ET,llvm::ArrayRef<unsigned> RegsToDef,llvm::ArrayRef<llvm::MCInst> Instructions)71   assembleToFunction(const ExegesisTarget &ET,
72                      llvm::ArrayRef<unsigned> RegsToDef,
73                      llvm::ArrayRef<llvm::MCInst> Instructions) {
74     llvm::SmallString<256> Buffer;
75     llvm::raw_svector_ostream AsmStream(Buffer);
76     assembleToStream(ET, createTargetMachine(), RegsToDef, Instructions,
77                      AsmStream);
78     return ExecutableFunction(createTargetMachine(),
79                               getObjectFromBuffer(AsmStream.str()));
80   }
81 
82   const std::string TT;
83   const std::string CpuName;
84   const bool CanExecute;
85 };
86 
87 } // namespace exegesis
88