diff options
Diffstat (limited to 'unittests')
| -rw-r--r-- | unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp | 241 | ||||
| -rw-r--r-- | unittests/ExecutionEngine/JIT/Makefile | 15 | ||||
| -rw-r--r-- | unittests/ExecutionEngine/Makefile | 19 | ||||
| -rw-r--r-- | unittests/MC/AsmStreamerTest.cpp | 103 | ||||
| -rw-r--r-- | unittests/MC/Makefile | 15 | ||||
| -rw-r--r-- | unittests/Makefile | 2 |
6 files changed, 394 insertions, 1 deletions
diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp new file mode 100644 index 000000000000..3c9beebba651 --- /dev/null +++ b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp @@ -0,0 +1,241 @@ +//===- JITEventListenerTest.cpp - Unit tests for JITEventListeners --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/JITEventListener.h" + +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/ModuleProvider.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/CodeGen/MachineCodeInfo.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/Support/TypeBuilder.h" +#include "llvm/Target/TargetSelect.h" +#include "gtest/gtest.h" +#include <vector> + +using namespace llvm; + +namespace { + +struct FunctionEmittedEvent { + // Indices are local to the RecordingJITEventListener, since the + // JITEventListener interface makes no guarantees about the order of + // calls between Listeners. + unsigned Index; + const Function *F; + void *Code; + size_t Size; + JITEvent_EmittedFunctionDetails Details; +}; +struct FunctionFreedEvent { + unsigned Index; + const Function *F; + void *Code; +}; + +struct RecordingJITEventListener : public JITEventListener { + std::vector<FunctionEmittedEvent> EmittedEvents; + std::vector<FunctionFreedEvent> FreedEvents; + + int NextIndex; + + RecordingJITEventListener() : NextIndex(0) {} + + virtual void NotifyFunctionEmitted(const Function &F, + void *Code, size_t Size, + const EmittedFunctionDetails &Details) { + FunctionEmittedEvent Event = {NextIndex++, &F, Code, Size, Details}; + EmittedEvents.push_back(Event); + } + + virtual void NotifyFreeingMachineCode(const Function &F, void *OldPtr) { + FunctionFreedEvent Event = {NextIndex++, &F, OldPtr}; + FreedEvents.push_back(Event); + } +}; + +class JITEventListenerTest : public testing::Test { + protected: + JITEventListenerTest() + : M(new Module("module")), + EE(ExecutionEngine::createJIT(new ExistingModuleProvider(M))) { + } + + Module *M; + const OwningPtr<ExecutionEngine> EE; +}; + +Function *buildFunction(Module *M) { + Function *Result = Function::Create( + TypeBuilder<int32_t(int32_t), false>::get(), + GlobalValue::ExternalLinkage, "id", M); + Value *Arg = Result->arg_begin(); + BasicBlock *BB = BasicBlock::Create("entry", Result); + ReturnInst::Create(Arg, BB); + return Result; +} + +// Tests that a single JITEventListener follows JIT events accurately. +TEST_F(JITEventListenerTest, Simple) { + RecordingJITEventListener Listener; + EE->RegisterJITEventListener(&Listener); + Function *F1 = buildFunction(M); + Function *F2 = buildFunction(M); + + void *F1_addr = EE->getPointerToFunction(F1); + void *F2_addr = EE->getPointerToFunction(F2); + EE->getPointerToFunction(F1); // Should do nothing. + EE->freeMachineCodeForFunction(F1); + EE->freeMachineCodeForFunction(F2); + + ASSERT_EQ(2U, Listener.EmittedEvents.size()); + ASSERT_EQ(2U, Listener.FreedEvents.size()); + + EXPECT_EQ(0U, Listener.EmittedEvents[0].Index); + EXPECT_EQ(F1, Listener.EmittedEvents[0].F); + EXPECT_EQ(F1_addr, Listener.EmittedEvents[0].Code); + EXPECT_LT(0U, Listener.EmittedEvents[0].Size) + << "We don't know how big the function will be, but it had better" + << " contain some bytes."; + + EXPECT_EQ(1U, Listener.EmittedEvents[1].Index); + EXPECT_EQ(F2, Listener.EmittedEvents[1].F); + EXPECT_EQ(F2_addr, Listener.EmittedEvents[1].Code); + EXPECT_LT(0U, Listener.EmittedEvents[1].Size) + << "We don't know how big the function will be, but it had better" + << " contain some bytes."; + + EXPECT_EQ(2U, Listener.FreedEvents[0].Index); + EXPECT_EQ(F1, Listener.FreedEvents[0].F); + EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code); + + EXPECT_EQ(3U, Listener.FreedEvents[1].Index); + EXPECT_EQ(F2, Listener.FreedEvents[1].F); + EXPECT_EQ(F2_addr, Listener.FreedEvents[1].Code); + + F1->eraseFromParent(); + F2->eraseFromParent(); +} + +// Tests that a single JITEventListener follows JIT events accurately. +TEST_F(JITEventListenerTest, MultipleListenersDontInterfere) { + RecordingJITEventListener Listener1; + RecordingJITEventListener Listener2; + RecordingJITEventListener Listener3; + Function *F1 = buildFunction(M); + Function *F2 = buildFunction(M); + + EE->RegisterJITEventListener(&Listener1); + EE->RegisterJITEventListener(&Listener2); + void *F1_addr = EE->getPointerToFunction(F1); + EE->RegisterJITEventListener(&Listener3); + EE->UnregisterJITEventListener(&Listener1); + void *F2_addr = EE->getPointerToFunction(F2); + EE->UnregisterJITEventListener(&Listener2); + EE->UnregisterJITEventListener(&Listener3); + EE->freeMachineCodeForFunction(F1); + EE->RegisterJITEventListener(&Listener2); + EE->RegisterJITEventListener(&Listener3); + EE->RegisterJITEventListener(&Listener1); + EE->freeMachineCodeForFunction(F2); + EE->UnregisterJITEventListener(&Listener1); + EE->UnregisterJITEventListener(&Listener2); + EE->UnregisterJITEventListener(&Listener3); + + // Listener 1. + ASSERT_EQ(1U, Listener1.EmittedEvents.size()); + ASSERT_EQ(1U, Listener1.FreedEvents.size()); + + EXPECT_EQ(0U, Listener1.EmittedEvents[0].Index); + EXPECT_EQ(F1, Listener1.EmittedEvents[0].F); + EXPECT_EQ(F1_addr, Listener1.EmittedEvents[0].Code); + EXPECT_LT(0U, Listener1.EmittedEvents[0].Size) + << "We don't know how big the function will be, but it had better" + << " contain some bytes."; + + EXPECT_EQ(1U, Listener1.FreedEvents[0].Index); + EXPECT_EQ(F2, Listener1.FreedEvents[0].F); + EXPECT_EQ(F2_addr, Listener1.FreedEvents[0].Code); + + // Listener 2. + ASSERT_EQ(2U, Listener2.EmittedEvents.size()); + ASSERT_EQ(1U, Listener2.FreedEvents.size()); + + EXPECT_EQ(0U, Listener2.EmittedEvents[0].Index); + EXPECT_EQ(F1, Listener2.EmittedEvents[0].F); + EXPECT_EQ(F1_addr, Listener2.EmittedEvents[0].Code); + EXPECT_LT(0U, Listener2.EmittedEvents[0].Size) + << "We don't know how big the function will be, but it had better" + << " contain some bytes."; + + EXPECT_EQ(1U, Listener2.EmittedEvents[1].Index); + EXPECT_EQ(F2, Listener2.EmittedEvents[1].F); + EXPECT_EQ(F2_addr, Listener2.EmittedEvents[1].Code); + EXPECT_LT(0U, Listener2.EmittedEvents[1].Size) + << "We don't know how big the function will be, but it had better" + << " contain some bytes."; + + EXPECT_EQ(2U, Listener2.FreedEvents[0].Index); + EXPECT_EQ(F2, Listener2.FreedEvents[0].F); + EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code); + + // Listener 3. + ASSERT_EQ(1U, Listener3.EmittedEvents.size()); + ASSERT_EQ(1U, Listener3.FreedEvents.size()); + + EXPECT_EQ(0U, Listener3.EmittedEvents[0].Index); + EXPECT_EQ(F2, Listener3.EmittedEvents[0].F); + EXPECT_EQ(F2_addr, Listener3.EmittedEvents[0].Code); + EXPECT_LT(0U, Listener3.EmittedEvents[0].Size) + << "We don't know how big the function will be, but it had better" + << " contain some bytes."; + + EXPECT_EQ(1U, Listener3.FreedEvents[0].Index); + EXPECT_EQ(F2, Listener3.FreedEvents[0].F); + EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code); + + F1->eraseFromParent(); + F2->eraseFromParent(); +} + +TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) { + RecordingJITEventListener Listener; + MachineCodeInfo MCI; + Function *F = buildFunction(M); + + EE->RegisterJITEventListener(&Listener); + EE->runJITOnFunction(F, &MCI); + void *F_addr = EE->getPointerToFunction(F); + EE->freeMachineCodeForFunction(F); + + ASSERT_EQ(1U, Listener.EmittedEvents.size()); + ASSERT_EQ(1U, Listener.FreedEvents.size()); + + EXPECT_EQ(0U, Listener.EmittedEvents[0].Index); + EXPECT_EQ(F, Listener.EmittedEvents[0].F); + EXPECT_EQ(F_addr, Listener.EmittedEvents[0].Code); + EXPECT_EQ(MCI.address(), Listener.EmittedEvents[0].Code); + EXPECT_EQ(MCI.size(), Listener.EmittedEvents[0].Size); + + EXPECT_EQ(1U, Listener.FreedEvents[0].Index); + EXPECT_EQ(F, Listener.FreedEvents[0].F); + EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code); +} + +class JITEnvironment : public testing::Environment { + virtual void SetUp() { + // Required for ExecutionEngine::createJIT to create a JIT. + InitializeNativeTarget(); + } +}; +testing::Environment* const jit_env = + testing::AddGlobalTestEnvironment(new JITEnvironment); + +} // anonymous namespace diff --git a/unittests/ExecutionEngine/JIT/Makefile b/unittests/ExecutionEngine/JIT/Makefile new file mode 100644 index 000000000000..0069c7687a01 --- /dev/null +++ b/unittests/ExecutionEngine/JIT/Makefile @@ -0,0 +1,15 @@ +##===- unittests/ExecutionEngine/JIT/Makefile --------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +TESTNAME = JIT +LINK_COMPONENTS := core support jit native + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/ExecutionEngine/Makefile b/unittests/ExecutionEngine/Makefile new file mode 100644 index 000000000000..e837a7d4fd3e --- /dev/null +++ b/unittests/ExecutionEngine/Makefile @@ -0,0 +1,19 @@ +##===- unittests/ExecutionEngine/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. + +include $(LEVEL)/Makefile.config + +PARALLEL_DIRS = JIT + +include $(LEVEL)/Makefile.common + +clean:: + $(Verb) $(RM) -f *Tests diff --git a/unittests/MC/AsmStreamerTest.cpp b/unittests/MC/AsmStreamerTest.cpp new file mode 100644 index 000000000000..d4b93eaaddab --- /dev/null +++ b/unittests/MC/AsmStreamerTest.cpp @@ -0,0 +1,103 @@ +//===- AsmStreamerTest.cpp - Triple unit tests ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + +// Helper class. +class StringAsmStreamer { + std::string Str; + raw_string_ostream OS; + MCContext Context; + MCStreamer *Streamer; + +public: + StringAsmStreamer() : OS(Str), Streamer(createAsmStreamer(Context, OS)) {} + ~StringAsmStreamer() { + delete Streamer; + } + + MCContext &getContext() { return Context; } + MCStreamer &getStreamer() { return *Streamer; } + + const std::string &getString() { + Streamer->Finish(); + return Str; + } +}; + +TEST(AsmStreamer, EmptyOutput) { + StringAsmStreamer S; + EXPECT_EQ(S.getString(), ""); +} + +TEST(AsmStreamer, Sections) { + StringAsmStreamer S; + MCSection *Sec0 = S.getContext().GetSection("foo"); + S.getStreamer().SwitchSection(Sec0); + EXPECT_EQ(S.getString(), ".section foo\n"); +} + +TEST(AsmStreamer, Values) { + StringAsmStreamer S; + MCSection *Sec0 = S.getContext().GetSection("foo"); + MCSymbol *A = S.getContext().CreateSymbol("a"); + MCSymbol *B = S.getContext().CreateSymbol("b"); + S.getStreamer().SwitchSection(Sec0); + S.getStreamer().EmitLabel(A); + S.getStreamer().EmitLabel(B); + S.getStreamer().EmitValue(MCValue::get(A, B, 10), 1); + S.getStreamer().EmitValue(MCValue::get(A, B, 10), 2); + S.getStreamer().EmitValue(MCValue::get(A, B, 10), 4); + S.getStreamer().EmitValue(MCValue::get(A, B, 10), 8); + EXPECT_EQ(S.getString(), ".section foo\n\ +a:\n\ +b:\n\ +.byte a - b + 10\n\ +.short a - b + 10\n\ +.long a - b + 10\n\ +.quad a - b + 10\n\ +"); +} + +TEST(AsmStreamer, Align) { + StringAsmStreamer S; + MCSection *Sec0 = S.getContext().GetSection("foo"); + S.getStreamer().SwitchSection(Sec0); + S.getStreamer().EmitValueToAlignment(4); + S.getStreamer().EmitValueToAlignment(4, /*Value=*/12, /*ValueSize=*/2); + S.getStreamer().EmitValueToAlignment(8, /*Value=*/12, /*ValueSize=*/4, + /*MaxBytesToEmit=*/24); + EXPECT_EQ(S.getString(), ".section foo\n\ +.p2align 2, 0\n\ +.p2alignw 2, 12\n\ +.p2alignl 3, 12, 24\n\ +"); +} + +TEST(AsmStreamer, Org) { + StringAsmStreamer S; + MCSection *Sec0 = S.getContext().GetSection("foo"); + S.getStreamer().SwitchSection(Sec0); + MCSymbol *A = S.getContext().CreateSymbol("a"); + S.getStreamer().EmitLabel(A); + S.getStreamer().EmitValueToOffset(MCValue::get(A, 0, 4), 32); + EXPECT_EQ(S.getString(), ".section foo\n\ +a:\n\ +.org a + 4, 32\n\ +"); +} + +} diff --git a/unittests/MC/Makefile b/unittests/MC/Makefile new file mode 100644 index 000000000000..410d3869cd5d --- /dev/null +++ b/unittests/MC/Makefile @@ -0,0 +1,15 @@ +##===- unittests/MC/Makefile -------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TESTNAME = MC +LINK_COMPONENTS := core support mc + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Makefile b/unittests/Makefile index 1ff541110266..1eb69abbc890 100644 --- a/unittests/Makefile +++ b/unittests/Makefile @@ -16,7 +16,7 @@ BUILD_ARCHIVE = 1 CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include/ CPP.Flags += -Wno-variadic-macros -PARALLEL_DIRS = ADT Support VMCore +PARALLEL_DIRS = ADT ExecutionEngine Support VMCore MC include $(LEVEL)/Makefile.common |
