//===-- AssemblerUtils.h ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Assembler.h" #include "Target.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/MC/MCInstBuilder.h" #include "llvm/Support/Host.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "gmock/gmock.h" #include "gtest/gtest.h" namespace exegesis { class MachineFunctionGeneratorBaseTest : public ::testing::Test { protected: MachineFunctionGeneratorBaseTest(const std::string &TT, const std::string &CpuName) : TT(TT), CpuName(CpuName), CanExecute(llvm::Triple(TT).getArch() == llvm::Triple(llvm::sys::getProcessTriple()).getArch()) { if (!CanExecute) { llvm::outs() << "Skipping execution, host:" << llvm::sys::getProcessTriple() << ", target:" << TT << "\n"; } } template inline void Check(llvm::MCInst MCInst, Bs... Bytes) { CheckWithSetup(ExegesisTarget::getDefault(), {}, MCInst, Bytes...); } template inline void CheckWithSetup(const ExegesisTarget &ET, llvm::ArrayRef RegsToDef, llvm::MCInst MCInst, Bs... Bytes) { ExecutableFunction Function = (MCInst.getOpcode() == 0) ? assembleToFunction(ET, RegsToDef, {}) : assembleToFunction(ET, RegsToDef, {MCInst}); ASSERT_THAT(Function.getFunctionBytes().str(), testing::ElementsAre(Bytes...)); if (CanExecute) Function(); } private: std::unique_ptr createTargetMachine() { std::string Error; const llvm::Target *TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error); EXPECT_TRUE(TheTarget) << Error << " " << TT; const llvm::TargetOptions Options; llvm::TargetMachine *TM = TheTarget->createTargetMachine( TT, CpuName, "", Options, llvm::Reloc::Model::Static); EXPECT_TRUE(TM) << TT << " " << CpuName; return std::unique_ptr( static_cast(TM)); } ExecutableFunction assembleToFunction(const ExegesisTarget &ET, llvm::ArrayRef RegsToDef, llvm::ArrayRef Instructions) { llvm::SmallString<256> Buffer; llvm::raw_svector_ostream AsmStream(Buffer); assembleToStream(ET, createTargetMachine(), RegsToDef, Instructions, AsmStream); return ExecutableFunction(createTargetMachine(), getObjectFromBuffer(AsmStream.str())); } const std::string TT; const std::string CpuName; const bool CanExecute; }; } // namespace exegesis