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