102 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_UNITTESTS_TOOLS_LLVMEXEGESIS_ASSEMBLERUTILS_H10#define LLVM_UNITTESTS_TOOLS_LLVMEXEGESIS_ASSEMBLERUTILS_H11 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/MC/TargetRegistry.h"21#include "llvm/Support/TargetSelect.h"22#include "llvm/TargetParser/Host.h"23#include "llvm/Testing/Support/Error.h"24#include "gmock/gmock.h"25#include "gtest/gtest.h"26 27namespace llvm {28namespace exegesis {29 30class MachineFunctionGeneratorBaseTest : public ::testing::Test {31protected:32 MachineFunctionGeneratorBaseTest(const std::string &TargetStr,33 const std::string &CpuName)34 : TT(TargetStr), CpuName(CpuName),35 CanExecute(TT.getArch() == Triple(sys::getProcessTriple()).getArch()),36 ET(ExegesisTarget::lookup(TT)) {37 assert(ET);38 if (!CanExecute) {39 outs() << "Skipping execution, host:" << sys::getProcessTriple()40 << ", target:" << TT.str() << "\n";41 }42 }43 44 template <class... Bs>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 62private:63 std::unique_ptr<TargetMachine> createTargetMachine() {64 std::string Error;65 const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);66 EXPECT_TRUE(TheTarget) << Error << " " << TT.str();67 const TargetOptions Options;68 TargetMachine *TM = TheTarget->createTargetMachine(TT, CpuName, "", Options,69 Reloc::Model::Static);70 EXPECT_TRUE(TM) << TT.str() << " " << CpuName;71 return std::unique_ptr<TargetMachine>(TM);72 }73 74 ExecutableFunction75 assembleToFunction(ArrayRef<RegisterValue> RegisterInitialValues,76 FillFunction Fill) {77 SmallString<256> Buffer;78 raw_svector_ostream AsmStream(Buffer);79 BenchmarkKey Key;80 Key.RegisterInitialValues = RegisterInitialValues;81 EXPECT_FALSE(assembleToStream(*ET, createTargetMachine(), /*LiveIns=*/{},82 Fill, AsmStream, Key, false));83 Expected<ExecutableFunction> ExecFunc = ExecutableFunction::create(84 createTargetMachine(), getObjectFromBuffer(AsmStream.str()));85 86 // We can't use ASSERT_THAT_EXPECTED here as it doesn't work inside of87 // non-void functions.88 EXPECT_TRUE(detail::TakeExpected(ExecFunc).Success());89 return std::move(*ExecFunc);90 }91 92 const Triple TT;93 const std::string CpuName;94 const bool CanExecute;95 const ExegesisTarget *const ET;96};97 98} // namespace exegesis99} // namespace llvm100 101#endif102