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