view unittests/ExecutionEngine/JITLink/JITLinkTestCommon.h @ 148:63bd29f05246

merged
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 14 Aug 2019 19:46:37 +0900
parents c2174574ed3a
children
line wrap: on
line source

//===---- JITLinkTestCommon.h - Utilities for Orc Unit Tests ----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Common utilities for JITLink unit tests.
//
//===----------------------------------------------------------------------===//


#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTCOMMON_H
#define LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTCOMMON_H

#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"

#include "gtest/gtest.h"

namespace llvm {

class JITLinkTestCommon {
public:

  class TestResources {
  public:
    static Expected<std::unique_ptr<TestResources>>
    Create(StringRef AsmSrc, StringRef TripleStr, bool PIC, bool LargeCodeModel,
           MCTargetOptions Options);

    MemoryBufferRef getTestObjectBufferRef() const;

    const MCDisassembler &getDisassembler() const { return *Dis; }

  private:
    TestResources(StringRef AsmSrc, StringRef TripleStr, bool PIC,
                  bool LargeCodeModel, MCTargetOptions Options, Error &Err);

    Error initializeTripleSpecifics(Triple &TT);
    void initializeTestSpecifics(StringRef AsmSource, const Triple &TT,
                                 bool PIC, bool LargeCodeModel);

    const Target *TheTarget = nullptr;
    SourceMgr SrcMgr;
    SmallVector<char, 0> ObjBuffer;
    raw_svector_ostream ObjStream;

    MCTargetOptions Options;
    std::unique_ptr<MCRegisterInfo> MRI;
    std::unique_ptr<MCAsmInfo> MAI;
    std::unique_ptr<MCInstrInfo> MCII;
    std::unique_ptr<MCSubtargetInfo> STI;

    MCObjectFileInfo MOFI;
    std::unique_ptr<MCContext> AsCtx;
    std::unique_ptr<MCStreamer> MOS;

    std::unique_ptr<MCContext> DisCtx;
    std::unique_ptr<const MCDisassembler> Dis;
  };

  class TestJITLinkContext : public jitlink::JITLinkContext {
  public:
    using TestCaseFunction = std::function<void(jitlink::AtomGraph &)>;

    using NotifyResolvedFunction = std::function<void(jitlink::AtomGraph &G)>;

    using NotifyFinalizedFunction = std::function<void(
        std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation>)>;

    TestJITLinkContext(TestResources &TR, TestCaseFunction TestCase);

    StringMap<JITEvaluatedSymbol> &externals() { return Externals; }

    TestJITLinkContext &
    setNotifyResolved(NotifyResolvedFunction NotifyResolved);

    TestJITLinkContext &
    setNotifyFinalized(NotifyFinalizedFunction NotifyFinalized);

    TestJITLinkContext &
    setMemoryManager(std::unique_ptr<jitlink::JITLinkMemoryManager> MM);

    jitlink::JITLinkMemoryManager &getMemoryManager() override;

    MemoryBufferRef getObjectBuffer() const override;

    void notifyFailed(Error Err) override;

    void
    lookup(const DenseSet<StringRef> &Symbols,
           jitlink::JITLinkAsyncLookupContinuation LookupContinuation) override;

    void notifyResolved(jitlink::AtomGraph &G) override;

    void notifyFinalized(
        std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation> A) override;

    Error modifyPassConfig(const Triple &TT,
                           jitlink::PassConfiguration &Config) override;

  private:
    TestResources &TR;
    TestCaseFunction TestCase;
    NotifyResolvedFunction NotifyResolved;
    NotifyFinalizedFunction NotifyFinalized;
    std::unique_ptr<MemoryBuffer> ObjBuffer;
    std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr;
    StringMap<JITEvaluatedSymbol> Externals;
  };

  JITLinkTestCommon();

  /// Get TestResources for this target/test.
  ///
  /// If this method fails it is likely because the target is not supported in
  /// this build. The test should bail out without failing (possibly logging a
  /// diagnostic).
  Expected<std::unique_ptr<TestResources>>
  getTestResources(StringRef AsmSrc, StringRef Triple, bool PIC,
                   bool LargeCodeModel, MCTargetOptions Options) const {
    return TestResources::Create(AsmSrc, Triple, PIC, LargeCodeModel,
                                 std::move(Options));
  }

  template <typename T>
  static Expected<T> readInt(jitlink::AtomGraph &G, jitlink::DefinedAtom &A,
                             size_t Offset = 0) {
    if (Offset + sizeof(T) > A.getContent().size())
      return make_error<StringError>("Reading past end of atom content",
                                     inconvertibleErrorCode());
    return support::endian::read<T, 1>(A.getContent().data() + Offset,
                                       G.getEndianness());
  }

  template <typename T>
  static Expected<T> readInt(jitlink::AtomGraph &G, StringRef AtomName,
                             size_t Offset = 0) {
    auto DA = G.findDefinedAtomByName(AtomName);
    if (!DA)
      return DA.takeError();
    return readInt<T>(G, *DA);
  }

  static Expected<std::pair<MCInst, size_t>>
  disassemble(const MCDisassembler &Dis, jitlink::DefinedAtom &Atom,
              size_t Offset = 0);

  static Expected<int64_t> decodeImmediateOperand(const MCDisassembler &Dis,
                                                  jitlink::DefinedAtom &Atom,
                                                  size_t OpIdx,
                                                  size_t Offset = 0);

  static jitlink::Atom &atom(jitlink::AtomGraph &G, StringRef Name) {
    return G.getAtomByName(Name);
  }

  static jitlink::DefinedAtom &definedAtom(jitlink::AtomGraph &G,
                                           StringRef Name) {
    return G.getDefinedAtomByName(Name);
  }

  static JITTargetAddress atomAddr(jitlink::AtomGraph &G, StringRef Name) {
    return atom(G, Name).getAddress();
  }

  template <typename PredT>
  static size_t countEdgesMatching(jitlink::DefinedAtom &DA,
                                   const PredT &Pred) {
    return std::count_if(DA.edges().begin(), DA.edges().end(), Pred);
  }

  template <typename PredT>
  static size_t countEdgesMatching(jitlink::AtomGraph &G, StringRef Name,
                                   const PredT &Pred) {
    return countEdgesMatching(definedAtom(G, Name), Pred);
  }

private:

  static bool AreTargetsInitialized;
  void initializeLLVMTargets();

  DenseMap<StringRef, JITEvaluatedSymbol> Externals;
};

} // end namespace llvm

#endif