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