diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2013-06-10 20:36:52 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2013-06-10 20:36:52 +0000 |
commit | 59d6cff90eecf31cb3dd860c4e786674cfdd42eb (patch) | |
tree | 909310b2e05119d1d6efda049977042abbb58bb1 /unittests | |
parent | 4a16efa3e43e35f0cc9efe3a67f620f0017c3d36 (diff) | |
download | src-test2-59d6cff90eecf31cb3dd860c4e786674cfdd42eb.tar.gz src-test2-59d6cff90eecf31cb3dd860c4e786674cfdd42eb.zip |
Notes
Diffstat (limited to 'unittests')
23 files changed, 1064 insertions, 84 deletions
diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index a3f8bf34e731..4b7e418cd180 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -13,3 +13,4 @@ add_subdirectory(Option) add_subdirectory(Support) add_subdirectory(Transforms) add_subdirectory(IR) +add_subdirectory(DebugInfo) diff --git a/unittests/DebugInfo/CMakeLists.txt b/unittests/DebugInfo/CMakeLists.txt new file mode 100644 index 000000000000..ec580b7f69a4 --- /dev/null +++ b/unittests/DebugInfo/CMakeLists.txt @@ -0,0 +1,13 @@ +set(LLVM_LINK_COMPONENTS + debuginfo + object + support + ) + +set(DebugInfoSources + DWARFFormValueTest.cpp + ) + +add_llvm_unittest(DebugInfoTests + ${DebugInfoSources} + ) diff --git a/unittests/DebugInfo/DWARFFormValueTest.cpp b/unittests/DebugInfo/DWARFFormValueTest.cpp new file mode 100644 index 000000000000..04b859bdb9db --- /dev/null +++ b/unittests/DebugInfo/DWARFFormValueTest.cpp @@ -0,0 +1,31 @@ +//===- llvm/unittest/DebugInfo/DWARFFormValueTest.cpp ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARFFormValue.h" +#include "llvm/Support/Dwarf.h" +#include "gtest/gtest.h" +using namespace llvm; +using namespace dwarf; + +namespace { + +TEST(DWARFFormValue, FixedFormSizes) { + // Size of DW_FORM_addr and DW_FORM_ref_addr are equal in DWARF2, + // DW_FORM_ref_addr is always 4 bytes in DWARF32 starting from DWARF3. + const uint8_t *sizes = DWARFFormValue::getFixedFormSizes(4, 2); + EXPECT_EQ(sizes[DW_FORM_addr], sizes[DW_FORM_ref_addr]); + sizes = DWARFFormValue::getFixedFormSizes(8, 2); + EXPECT_EQ(sizes[DW_FORM_addr], sizes[DW_FORM_ref_addr]); + sizes = DWARFFormValue::getFixedFormSizes(8, 3); + EXPECT_EQ(4, sizes[DW_FORM_ref_addr]); + // Check that we don't have fixed form sizes for weird address sizes. + EXPECT_EQ(0, DWARFFormValue::getFixedFormSizes(16, 2)); +} + +} // end anonymous namespace diff --git a/unittests/DebugInfo/Makefile b/unittests/DebugInfo/Makefile new file mode 100644 index 000000000000..999ded90b0f6 --- /dev/null +++ b/unittests/DebugInfo/Makefile @@ -0,0 +1,16 @@ +##===- unittests/DebugInfo/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 = DebugInfo +LINK_COMPONENTS := debuginfo object support + +include $(LEVEL)/Makefile.config + +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp index 6ba8bc42d12c..87f482444f41 100644 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp @@ -74,6 +74,8 @@ class JITEventListenerTest : public testing::Test { const OwningPtr<ExecutionEngine> EE; }; +// Tests on SystemZ disabled as we're running the old JIT +#if !defined(__s390__) Function *buildFunction(Module *M) { Function *Result = Function::Create( TypeBuilder<int32_t(int32_t), false>::get(getGlobalContext()), @@ -224,6 +226,7 @@ TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) { EXPECT_EQ(1U, Listener.FreedEvents[0].Index); EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code); } +#endif class JITEnvironment : public testing::Environment { virtual void SetUp() { diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp index 30dadc9f3e3b..e6f4cb9af25f 100644 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITTest.cpp @@ -35,6 +35,9 @@ using namespace llvm; namespace { +// Tests on ARM, PowerPC and SystemZ disabled as we're running the old jit +#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) + Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) { std::vector<Type*> params; FunctionType *FTy = FunctionType::get(G->getType()->getElementType(), @@ -231,9 +234,6 @@ class JITTest : public testing::Test { OwningPtr<ExecutionEngine> TheJIT; }; -// Tests on ARM and PowerPC disabled as we're running the old jit -#if !defined(__arm__) && !defined(__powerpc__) - // Regression test for a bug. The JIT used to allocate globals inside the same // memory block used for the function, and when the function code was freed, // the global was left in the same place. This test allocates a function @@ -302,8 +302,6 @@ TEST(JIT, GlobalInFunction) { EXPECT_EQ(3, *GPtr); } -#endif // !defined(__arm__) && !defined(__powerpc__) - // Regression test for a bug. The JITEmitter wasn't checking to verify that // it hadn't run out of space while generating the DWARF exception information // for an emitted function. @@ -348,8 +346,6 @@ int PlusOne(int arg) { return arg + 1; } -// ARM and PowerPC tests disabled pending fix for PR10783. -#if !defined(__arm__) && !defined(__powerpc__) TEST_F(JITTest, FarCallToKnownFunction) { // x86-64 can only make direct calls to functions within 32 bits of // the current PC. To call anything farther away, we have to load @@ -527,7 +523,6 @@ TEST_F(JITTest, ModuleDeletion) { EXPECT_EQ(RJMM->startExceptionTableCalls.size(), NumTablesDeallocated); } -#endif // !defined(__arm__) && !defined(__powerpc__) // ARM, MIPS and PPC still emit stubs for calls since the target may be // too far away to call directly. This #if can probably be removed when @@ -573,9 +568,6 @@ TEST_F(JITTest, NoStubs) { } #endif // !ARM && !PPC -// Tests on ARM and PowerPC disabled as we're running the old jit -#if !defined(__arm__) && !defined(__powerpc__) - TEST_F(JITTest, FunctionPointersOutliveTheirCreator) { TheJIT->DisableLazyCompilation(true); LoadAssembly("define i8()* @get_foo_addr() { " @@ -610,13 +602,9 @@ TEST_F(JITTest, FunctionPointersOutliveTheirCreator) { #endif } -#endif //!defined(__arm__) && !defined(__powerpc__) - -// Tests on ARM and PowerPC disabled as we're running the old jit -// In addition, ARM does not have an implementation -// of replaceMachineCodeForFunction(), so recompileAndRelinkFunction -// doesn't work. -#if !defined(__arm__) && !defined(__powerpc__) +// ARM does not have an implementation of replaceMachineCodeForFunction(), +// so recompileAndRelinkFunction doesn't work. +#if !defined(__arm__) TEST_F(JITTest, FunctionIsRecompiledAndRelinked) { Function *F = Function::Create(TypeBuilder<int(void), false>::get(Context), GlobalValue::ExternalLinkage, "test", M); @@ -647,7 +635,7 @@ TEST_F(JITTest, FunctionIsRecompiledAndRelinked) { EXPECT_EQ(2, OrigFPtr()) << "The old pointer's target should now jump to the new version"; } -#endif // !defined(__arm__) && !defined(__powerpc__) +#endif // !defined(__arm__) } // anonymous namespace // This variable is intentionally defined differently in the statically-compiled @@ -657,9 +645,6 @@ extern "C" int32_t JITTest_AvailableExternallyGlobal; int32_t JITTest_AvailableExternallyGlobal LLVM_ATTRIBUTE_USED = 42; namespace { -// Tests on ARM and PowerPC disabled as we're running the old jit -#if !defined(__arm__) && !defined(__powerpc__) - TEST_F(JITTest, AvailableExternallyGlobalIsntEmitted) { TheJIT->DisableLazyCompilation(true); LoadAssembly("@JITTest_AvailableExternallyGlobal = " @@ -676,7 +661,6 @@ TEST_F(JITTest, AvailableExternallyGlobalIsntEmitted) { EXPECT_EQ(42, loader()) << "func should return 42 from the external global," << " not 7 from the IR version."; } -#endif //!defined(__arm__) && !defined(__powerpc__) } // anonymous namespace // This function is intentionally defined differently in the statically-compiled // program from the IR input to the JIT to assert that the JIT doesn't use its @@ -687,8 +671,6 @@ extern "C" int32_t JITTest_AvailableExternallyFunction() { } namespace { -// ARM and PowerPC tests disabled pending fix for PR10783. -#if !defined(__arm__) && !defined(__powerpc__) TEST_F(JITTest, AvailableExternallyFunctionIsntCompiled) { TheJIT->DisableLazyCompilation(true); LoadAssembly("define available_externally i32 " @@ -844,7 +826,7 @@ TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) { (intptr_t)TheJIT->getPointerToFunction(recur1IR)); EXPECT_EQ(3, recur1(4)); } -#endif // !defined(__arm__) && !defined(__powerpc__) +#endif // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) // This code is copied from JITEventListenerTest, but it only runs once for all // the tests in this directory. Everything seems fine, but that's strange diff --git a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp index 53014672c268..4018cd5ce2f2 100644 --- a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp +++ b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp @@ -20,6 +20,9 @@ using namespace llvm; namespace { +// ARM, PowerPC and SystemZ tests disabled pending fix for PR10783. +#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) + bool LoadAssemblyInto(Module *M, const char *assembly) { SMDiagnostic Error; bool success = @@ -65,9 +68,6 @@ void createModule2(LLVMContext &Context2, Module *&M2, Function *&FooF2) { FooF2 = M2->getFunction("foo2"); } -// ARM and PowerPC tests disabled pending fix for PR10783. -#if !defined(__arm__) && !defined(__powerpc__) - TEST(MultiJitTest, EagerMode) { LLVMContext Context1; Module *M1 = 0; @@ -176,6 +176,6 @@ TEST(MultiJitTest, JitPool) { #endif EXPECT_TRUE(sa == fa); } -#endif // !defined(__arm__) && !defined(__powerpc__) +#endif // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) } // anonymous namespace diff --git a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt index c6b1f77e3e8b..922cb7efd5eb 100644 --- a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt @@ -9,7 +9,9 @@ set(LLVM_LINK_COMPONENTS set(MCJITTestsSources MCJITTest.cpp + MCJITCAPITest.cpp MCJITMemoryManagerTest.cpp + MCJITObjectCacheTest.cpp ) if(MSVC) diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp new file mode 100644 index 000000000000..07ea1afe1a85 --- /dev/null +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -0,0 +1,97 @@ +//===- MCJITTest.cpp - Unit tests for the MCJIT ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This test suite verifies basic MCJIT functionality when invoked form the C +// API. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Analysis.h" +#include "llvm-c/Core.h" +#include "llvm-c/ExecutionEngine.h" +#include "llvm-c/Target.h" +#include "llvm-c/Transforms/Scalar.h" +#include "llvm/Support/Host.h" +#include "MCJITTestAPICommon.h" +#include "gtest/gtest.h" + +using namespace llvm; + +class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon { +protected: + MCJITCAPITest() { + // The architectures below are known to be compatible with MCJIT as they + // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be + // kept in sync. + SupportedArchs.push_back(Triple::arm); + SupportedArchs.push_back(Triple::mips); + SupportedArchs.push_back(Triple::x86); + SupportedArchs.push_back(Triple::x86_64); + + // The operating systems below are known to be sufficiently incompatible + // that they will fail the MCJIT C API tests. + UnsupportedOSs.push_back(Triple::Cygwin); + } +}; + +TEST_F(MCJITCAPITest, simple_function) { + SKIP_UNSUPPORTED_PLATFORM; + + char *error = 0; + + // Creates a function that returns 42, compiles it, and runs it. + + LLVMModuleRef module = LLVMModuleCreateWithName("simple_module"); + + LLVMSetTarget(module, HostTriple.c_str()); + + LLVMValueRef function = LLVMAddFunction( + module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0)); + LLVMSetFunctionCallConv(function, LLVMCCallConv); + + LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry"); + LLVMBuilderRef builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(builder, entry); + LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0)); + + LLVMVerifyModule(module, LLVMAbortProcessAction, &error); + LLVMDisposeMessage(error); + + LLVMDisposeBuilder(builder); + + LLVMMCJITCompilerOptions options; + LLVMInitializeMCJITCompilerOptions(&options, sizeof(options)); + options.OptLevel = 2; + + // Just ensure that this field still exists. + options.NoFramePointerElim = false; + + LLVMExecutionEngineRef engine; + ASSERT_EQ( + 0, LLVMCreateMCJITCompilerForModule(&engine, module, &options, + sizeof(options), &error)); + + LLVMPassManagerRef pass = LLVMCreatePassManager(); + LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); + LLVMAddConstantPropagationPass(pass); + LLVMAddInstructionCombiningPass(pass); + LLVMRunPassManager(pass, module); + LLVMDisposePassManager(pass); + + union { + void *raw; + int (*usable)(); + } functionPointer; + functionPointer.raw = LLVMGetPointerToGlobal(engine, function); + + EXPECT_EQ(42, functionPointer.usable()); + + LLVMDisposeExecutionEngine(engine); +} + diff --git a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp new file mode 100644 index 000000000000..0061e30e7a54 --- /dev/null +++ b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp @@ -0,0 +1,240 @@ +//===- MCJITObjectCacheTest.cpp - Unit tests for MCJIT object caching -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "MCJITTestBase.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +class TestObjectCache : public ObjectCache { +public: + TestObjectCache() : DuplicateInserted(false) { } + + virtual ~TestObjectCache() { + // Free any buffers we've allocated. + SmallVector<MemoryBuffer *, 2>::iterator it, end; + end = AllocatedBuffers.end(); + for (it = AllocatedBuffers.begin(); it != end; ++it) { + delete *it; + } + AllocatedBuffers.clear(); + } + + virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) { + // If we've seen this module before, note that. + const std::string ModuleID = M->getModuleIdentifier(); + if (ObjMap.find(ModuleID) != ObjMap.end()) + DuplicateInserted = true; + // Store a copy of the buffer in our map. + ObjMap[ModuleID] = copyBuffer(Obj); + } + + // Test-harness-specific functions + bool wereDuplicatesInserted() { return DuplicateInserted; } + + bool wasModuleLookedUp(const Module *M) { + return ModulesLookedUp.find(M->getModuleIdentifier()) + != ModulesLookedUp.end(); + } + + const MemoryBuffer* getObjectInternal(const Module* M) { + // Look for the module in our map. + const std::string ModuleID = M->getModuleIdentifier(); + StringMap<const MemoryBuffer *>::iterator it = ObjMap.find(ModuleID); + if (it == ObjMap.end()) + return 0; + return it->second; + } + +protected: + virtual const MemoryBuffer* getObject(const Module* M) { + const MemoryBuffer* BufferFound = getObjectInternal(M); + ModulesLookedUp.insert(M->getModuleIdentifier()); + return BufferFound; + } + +private: + MemoryBuffer *copyBuffer(const MemoryBuffer *Buf) { + // Create a local copy of the buffer. + MemoryBuffer *NewBuffer = MemoryBuffer::getMemBufferCopy(Buf->getBuffer()); + AllocatedBuffers.push_back(NewBuffer); + return NewBuffer; + } + + StringMap<const MemoryBuffer *> ObjMap; + StringSet<> ModulesLookedUp; + SmallVector<MemoryBuffer *, 2> AllocatedBuffers; + bool DuplicateInserted; +}; + +class MCJITObjectCacheTest : public testing::Test, public MCJITTestBase { +protected: + + enum { + OriginalRC = 6, + ReplacementRC = 7 + }; + + virtual void SetUp() { + M.reset(createEmptyModule("<main>")); + Main = insertMainFunction(M.get(), OriginalRC); + } + + void compileAndRun(int ExpectedRC = OriginalRC) { + // This function shouldn't be called until after SetUp. + ASSERT_TRUE(0 != TheJIT); + ASSERT_TRUE(0 != Main); + + TheJIT->finalizeObject(); + void *vPtr = TheJIT->getPointerToFunction(Main); + + static_cast<SectionMemoryManager*>(MM)->invalidateInstructionCache(); + + EXPECT_TRUE(0 != vPtr) + << "Unable to get pointer to main() from JIT"; + + int (*FuncPtr)(void) = (int(*)(void))(intptr_t)vPtr; + int returnCode = FuncPtr(); + EXPECT_EQ(returnCode, ExpectedRC); + } + + Function *Main; +}; + +TEST_F(MCJITObjectCacheTest, SetNullObjectCache) { + SKIP_UNSUPPORTED_PLATFORM; + + createJIT(M.take()); + + TheJIT->setObjectCache(NULL); + + compileAndRun(); +} + + +TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) { + SKIP_UNSUPPORTED_PLATFORM; + + OwningPtr<TestObjectCache> Cache(new TestObjectCache); + + // Save a copy of the module pointer before handing it off to MCJIT. + const Module * SavedModulePointer = M.get(); + + createJIT(M.take()); + + TheJIT->setObjectCache(Cache.get()); + + // Verify that our object cache does not contain the module yet. + const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SavedModulePointer); + EXPECT_EQ(0, ObjBuffer); + + compileAndRun(); + + // Verify that MCJIT tried to look-up this module in the cache. + EXPECT_TRUE(Cache->wasModuleLookedUp(SavedModulePointer)); + + // Verify that our object cache now contains the module. + ObjBuffer = Cache->getObjectInternal(SavedModulePointer); + EXPECT_TRUE(0 != ObjBuffer); + + // Verify that the cache was only notified once. + EXPECT_FALSE(Cache->wereDuplicatesInserted()); +} + +TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { + SKIP_UNSUPPORTED_PLATFORM; + + OwningPtr<TestObjectCache> Cache(new TestObjectCache); + + // Compile this module with an MCJIT engine + createJIT(M.take()); + TheJIT->setObjectCache(Cache.get()); + TheJIT->finalizeObject(); + + // Destroy the MCJIT engine we just used + TheJIT.reset(); + + // Create a new memory manager. + MM = new SectionMemoryManager; + + // Create a new module and save it. Use a different return code so we can + // tell if MCJIT compiled this module or used the cache. + M.reset(createEmptyModule("<main>")); + Main = insertMainFunction(M.get(), ReplacementRC); + const Module * SecondModulePointer = M.get(); + + // Create a new MCJIT instance to load this module then execute it. + createJIT(M.take()); + TheJIT->setObjectCache(Cache.get()); + compileAndRun(); + + // Verify that MCJIT tried to look-up this module in the cache. + EXPECT_TRUE(Cache->wasModuleLookedUp(SecondModulePointer)); + + // Verify that MCJIT didn't try to cache this again. + EXPECT_FALSE(Cache->wereDuplicatesInserted()); +} + +TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { + SKIP_UNSUPPORTED_PLATFORM; + + OwningPtr<TestObjectCache> Cache(new TestObjectCache); + + // Compile this module with an MCJIT engine + createJIT(M.take()); + TheJIT->setObjectCache(Cache.get()); + TheJIT->finalizeObject(); + + // Destroy the MCJIT engine we just used + TheJIT.reset(); + + // Create a new memory manager. + MM = new SectionMemoryManager; + + // Create a new module and save it. Use a different return code so we can + // tell if MCJIT compiled this module or used the cache. Note that we use + // a new module name here so the module shouldn't be found in the cache. + M.reset(createEmptyModule("<not-main>")); + Main = insertMainFunction(M.get(), ReplacementRC); + const Module * SecondModulePointer = M.get(); + + // Create a new MCJIT instance to load this module then execute it. + createJIT(M.take()); + TheJIT->setObjectCache(Cache.get()); + + // Verify that our object cache does not contain the module yet. + const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SecondModulePointer); + EXPECT_EQ(0, ObjBuffer); + + // Run the function and look for the replacement return code. + compileAndRun(ReplacementRC); + + // Verify that MCJIT tried to look-up this module in the cache. + EXPECT_TRUE(Cache->wasModuleLookedUp(SecondModulePointer)); + + // Verify that our object cache now contains the module. + ObjBuffer = Cache->getObjectInternal(SecondModulePointer); + EXPECT_TRUE(0 != ObjBuffer); + + // Verify that MCJIT didn't try to cache this again. + EXPECT_FALSE(Cache->wereDuplicatesInserted()); +} + +} // Namespace + diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h new file mode 100644 index 000000000000..8160a186f413 --- /dev/null +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h @@ -0,0 +1,77 @@ +//===- MCJITTestBase.h - Common base class for MCJIT Unit tests ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements functionality shared by both MCJIT C API tests, and +// the C++ API tests. +// +//===----------------------------------------------------------------------===// + +#ifndef MCJIT_TEST_API_COMMON_H +#define MCJIT_TEST_API_COMMON_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/TargetSelect.h" + +// Used to skip tests on unsupported architectures and operating systems. +// To skip a test, add this macro at the top of a test-case in a suite that +// inherits from MCJITTestBase. See MCJITTest.cpp for examples. +#define SKIP_UNSUPPORTED_PLATFORM \ + do \ + if (!ArchSupportsMCJIT() || !OSSupportsMCJIT()) \ + return; \ + while(0) + +namespace llvm { + +class MCJITTestAPICommon { +protected: + MCJITTestAPICommon() + : HostTriple(sys::getProcessTriple()) + { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + +#ifdef LLVM_ON_WIN32 + // On Windows, generate ELF objects by specifying "-elf" in triple + HostTriple += "-elf"; +#endif // LLVM_ON_WIN32 + HostTriple = Triple::normalize(HostTriple); + } + + /// Returns true if the host architecture is known to support MCJIT + bool ArchSupportsMCJIT() { + Triple Host(HostTriple); + if (std::find(SupportedArchs.begin(), SupportedArchs.end(), Host.getArch()) + == SupportedArchs.end()) { + return false; + } + return true; + } + + /// Returns true if the host OS is known to support MCJIT + bool OSSupportsMCJIT() { + Triple Host(HostTriple); + if (std::find(UnsupportedOSs.begin(), UnsupportedOSs.end(), Host.getOS()) + == UnsupportedOSs.end()) { + return true; + } + return false; + } + + std::string HostTriple; + SmallVector<Triple::ArchType, 4> SupportedArchs; + SmallVector<Triple::OSType, 4> UnsupportedOSs; +}; + +} // namespace llvm + +#endif // MCJIT_TEST_API_COMMON_H + diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h index fc774abd6215..b0e98a88defc 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h @@ -17,8 +17,6 @@ #ifndef MCJIT_TEST_BASE_H #define MCJIT_TEST_BASE_H -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" #include "llvm/Config/config.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" @@ -28,21 +26,11 @@ #include "llvm/IR/Module.h" #include "llvm/IR/TypeBuilder.h" #include "llvm/Support/CodeGen.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/TargetSelect.h" - -// Used to skip tests on unsupported architectures and operating systems. -// To skip a test, add this macro at the top of a test-case in a suite that -// inherits from MCJITTestBase. See MCJITTest.cpp for examples. -#define SKIP_UNSUPPORTED_PLATFORM \ - do \ - if (!ArchSupportsMCJIT() || !OSSupportsMCJIT()) \ - return; \ - while(0); +#include "MCJITTestAPICommon.h" namespace llvm { -class MCJITTestBase { +class MCJITTestBase : public MCJITTestAPICommon { protected: MCJITTestBase() @@ -52,17 +40,7 @@ protected: , MArch("") , Builder(Context) , MM(new SectionMemoryManager) - , HostTriple(sys::getProcessTriple()) { - InitializeNativeTarget(); - InitializeNativeTargetAsmPrinter(); - -#ifdef LLVM_ON_WIN32 - // On Windows, generate ELF objects by specifying "-elf" in triple - HostTriple += "-elf"; -#endif // LLVM_ON_WIN32 - HostTriple = Triple::normalize(HostTriple); - // The architectures below are known to be compatible with MCJIT as they // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be // kept in sync. @@ -78,26 +56,6 @@ protected: UnsupportedOSs.push_back(Triple::Darwin); } - /// Returns true if the host architecture is known to support MCJIT - bool ArchSupportsMCJIT() { - Triple Host(HostTriple); - if (std::find(SupportedArchs.begin(), SupportedArchs.end(), Host.getArch()) - == SupportedArchs.end()) { - return false; - } - return true; - } - - /// Returns true if the host OS is known to support MCJIT - bool OSSupportsMCJIT() { - Triple Host(HostTriple); - if (std::find(UnsupportedOSs.begin(), UnsupportedOSs.end(), Host.getOS()) - == UnsupportedOSs.end()) { - return true; - } - return false; - } - Module *createEmptyModule(StringRef Name) { Module * M = new Module(Name, Context); M->setTargetTriple(Triple::normalize(HostTriple)); @@ -232,10 +190,6 @@ protected: IRBuilder<> Builder; JITMemoryManager *MM; - std::string HostTriple; - SmallVector<Triple::ArchType, 4> SupportedArchs; - SmallVector<Triple::OSType, 4> UnsupportedOSs; - OwningPtr<Module> M; }; diff --git a/unittests/ExecutionEngine/Makefile b/unittests/ExecutionEngine/Makefile index c779a6a47c14..38e667ff9888 100644 --- a/unittests/ExecutionEngine/Makefile +++ b/unittests/ExecutionEngine/Makefile @@ -11,9 +11,10 @@ LEVEL = ../.. TESTNAME = ExecutionEngine LINK_COMPONENTS :=interpreter +include $(LEVEL)/Makefile.config + ifeq ($(TARGET_HAS_JIT),1) - PARALLEL_DIRS = JIT MCJIT + PARALLEL_DIRS = JIT MCJIT endif -include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index aed45979c069..c53043ef80e1 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -13,9 +13,11 @@ set(IRSources MDBuilderTest.cpp MetadataTest.cpp PassManagerTest.cpp + PatternMatch.cpp TypeBuilderTest.cpp TypesTest.cpp ValueMapTest.cpp + ValueTest.cpp VerifierTest.cpp WaymarkTest.cpp ) diff --git a/unittests/IR/PatternMatch.cpp b/unittests/IR/PatternMatch.cpp new file mode 100644 index 000000000000..7c6d8ce61586 --- /dev/null +++ b/unittests/IR/PatternMatch.cpp @@ -0,0 +1,265 @@ +//===---- llvm/unittest/IR/PatternMatch.cpp - PatternMatch unit tests ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Operator.h" +#include "llvm/Support/NoFolder.h" +#include "llvm/Support/PatternMatch.h" +#include "gtest/gtest.h" + +using namespace llvm::PatternMatch; + +namespace llvm { +namespace { + +/// Ordered floating point minimum/maximum tests. + +static void m_OrdFMin_expect_match_and_delete(Value *Cmp, Value *Select, + Value *L, Value *R) { + Value *MatchL, *MatchR; + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + delete Select; + delete Cmp; +} + +static void m_OrdFMin_expect_nomatch_and_delete(Value *Cmp, Value *Select, + Value *L, Value *R) { + Value *MatchL, *MatchR; + EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); + delete Select; + delete Cmp; +} + +static void m_OrdFMax_expect_match_and_delete(Value *Cmp, Value *Select, + Value *L, Value *R) { + Value *MatchL, *MatchR; + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + delete Select; + delete Cmp; +} + +static void m_OrdFMax_expect_nomatch_and_delete(Value *Cmp, Value *Select, + Value *L, Value *R) { + Value *MatchL, *MatchR; + EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); + delete Select; + delete Cmp; +} + + + +TEST(PatternMatchTest, FloatingPointOrderedMin) { + LLVMContext &C(getGlobalContext()); + IRBuilder<true, NoFolder> Builder(C); + + Type *FltTy = Builder.getFloatTy(); + Value *L = ConstantFP::get(FltTy, 1.0); + Value *R = ConstantFP::get(FltTy, 2.0); + + // Test OLT. + Value *Cmp = Builder.CreateFCmpOLT(L, R); + Value *Select = Builder.CreateSelect(Cmp, L, R); + m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + + // Test OLE. + Cmp = Builder.CreateFCmpOLE(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + + // Test no match on OGE. + Cmp = Builder.CreateFCmpOGE(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_OrdFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + + // Test no match on OGT. + Cmp = Builder.CreateFCmpOGT(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_OrdFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + + // Test match on OGE with inverted select. + Cmp = Builder.CreateFCmpOGE(L, R); + Select = Builder.CreateSelect(Cmp, R, L); + m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + + // Test match on OGT with inverted select. + Cmp = Builder.CreateFCmpOGT(L, R); + Select = Builder.CreateSelect(Cmp, R, L); + m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); +} + +TEST(PatternMatchTest, FloatingPointOrderedMax) { + LLVMContext &C(getGlobalContext()); + IRBuilder<true, NoFolder> Builder(C); + + Type *FltTy = Builder.getFloatTy(); + Value *L = ConstantFP::get(FltTy, 1.0); + Value *R = ConstantFP::get(FltTy, 2.0); + + // Test OGT. + Value *Cmp = Builder.CreateFCmpOGT(L, R); + Value *Select = Builder.CreateSelect(Cmp, L, R); + m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); + + // Test OGE. + Cmp = Builder.CreateFCmpOGE(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); + + // Test no match on OLE. + Cmp = Builder.CreateFCmpOLE(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_OrdFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + + // Test no match on OLT. + Cmp = Builder.CreateFCmpOLT(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_OrdFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + + // Test match on OLE with inverted select. + Cmp = Builder.CreateFCmpOLE(L, R); + Select = Builder.CreateSelect(Cmp, R, L); + m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); + + // Test match on OLT with inverted select. + Cmp = Builder.CreateFCmpOLT(L, R); + Select = Builder.CreateSelect(Cmp, R, L); + m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); +} + +/// Unordered floating point minimum/maximum tests. + +static void m_UnordFMin_expect_match_and_delete(Value *Cmp, Value *Select, + Value *L, Value *R) { + Value *MatchL, *MatchR; + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + delete Select; + delete Cmp; +} + +static void m_UnordFMin_expect_nomatch_and_delete(Value *Cmp, Value *Select, + Value *L, Value *R) { + Value *MatchL, *MatchR; + EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); + delete Select; + delete Cmp; +} + +static void m_UnordFMax_expect_match_and_delete(Value *Cmp, Value *Select, + Value *L, Value *R) { + Value *MatchL, *MatchR; + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + delete Select; + delete Cmp; +} + +static void m_UnordFMax_expect_nomatch_and_delete(Value *Cmp, Value *Select, + Value *L, Value *R) { + Value *MatchL, *MatchR; + EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); + delete Select; + delete Cmp; +} + +TEST(PatternMatchTest, FloatingPointUnorderedMin) { + LLVMContext &C(getGlobalContext()); + IRBuilder<true, NoFolder> Builder(C); + + Type *FltTy = Builder.getFloatTy(); + Value *L = ConstantFP::get(FltTy, 1.0); + Value *R = ConstantFP::get(FltTy, 2.0); + + // Test ULT. + Value *Cmp = Builder.CreateFCmpULT(L, R); + Value *Select = Builder.CreateSelect(Cmp, L, R); + m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + + // Test ULE. + Cmp = Builder.CreateFCmpULE(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + + // Test no match on UGE. + Cmp = Builder.CreateFCmpUGE(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_UnordFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + + // Test no match on UGT. + Cmp = Builder.CreateFCmpUGT(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_UnordFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + + // Test match on UGE with inverted select. + Cmp = Builder.CreateFCmpUGE(L, R); + Select = Builder.CreateSelect(Cmp, R, L); + m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + + // Test match on UGT with inverted select. + Cmp = Builder.CreateFCmpUGT(L, R); + Select = Builder.CreateSelect(Cmp, R, L); + m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); +} + +TEST(PatternMatchTest, FloatingPointUnorderedMax) { + LLVMContext &C(getGlobalContext()); + IRBuilder<true, NoFolder> Builder(C); + + Type *FltTy = Builder.getFloatTy(); + Value *L = ConstantFP::get(FltTy, 1.0); + Value *R = ConstantFP::get(FltTy, 2.0); + + // Test UGT. + Value *Cmp = Builder.CreateFCmpUGT(L, R); + Value *Select = Builder.CreateSelect(Cmp, L, R); + m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + + // Test UGE. + Cmp = Builder.CreateFCmpUGE(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + + // Test no match on ULE. + Cmp = Builder.CreateFCmpULE(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_UnordFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + + // Test no match on ULT. + Cmp = Builder.CreateFCmpULT(L, R); + Select = Builder.CreateSelect(Cmp, L, R); + m_UnordFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + + // Test match on ULE with inverted select. + Cmp = Builder.CreateFCmpULE(L, R); + Select = Builder.CreateSelect(Cmp, R, L); + m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + + // Test match on ULT with inverted select. + Cmp = Builder.CreateFCmpULT(L, R); + Select = Builder.CreateSelect(Cmp, R, L); + m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); +} + +} // anonymous namespace. +} // llvm namespace. diff --git a/unittests/IR/ValueTest.cpp b/unittests/IR/ValueTest.cpp new file mode 100644 index 000000000000..52efb1a220aa --- /dev/null +++ b/unittests/IR/ValueTest.cpp @@ -0,0 +1,46 @@ +//===- llvm/unittest/IR/ValueTest.cpp - Value unit tests ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Assembly/Parser.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" +using namespace llvm; + +namespace { + +TEST(ValueTest, UsedInBasicBlock) { + LLVMContext C; + + const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n" + "bb0:\n" + " %y1 = add i32 %y, 1\n" + " %y2 = add i32 %y, 1\n" + " %y3 = add i32 %y, 1\n" + " %y4 = add i32 %y, 1\n" + " %y5 = add i32 %y, 1\n" + " %y6 = add i32 %y, 1\n" + " %y7 = add i32 %y, 1\n" + " %y8 = add i32 %x, 1\n" + " ret void\n" + "}\n"; + SMDiagnostic Err; + Module *M = ParseAssemblyString(ModuleString, NULL, Err, C); + + Function *F = M->getFunction("f"); + + EXPECT_FALSE(F->isUsedInBasicBlock(F->begin())); + EXPECT_TRUE((++F->arg_begin())->isUsedInBasicBlock(F->begin())); + EXPECT_TRUE(F->arg_begin()->isUsedInBasicBlock(F->begin())); +} + +} // end anonymous namespace diff --git a/unittests/Makefile b/unittests/Makefile index 926459ac08f8..61d60611be9c 100644 --- a/unittests/Makefile +++ b/unittests/Makefile @@ -9,7 +9,8 @@ LEVEL = .. -PARALLEL_DIRS = ADT ExecutionEngine Support Transforms IR Analysis Bitcode +PARALLEL_DIRS = ADT ExecutionEngine Support Transforms IR Analysis Bitcode \ + DebugInfo include $(LEVEL)/Makefile.common diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index b4b982f2ef23..e6cafbcaf158 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -10,6 +10,7 @@ add_llvm_unittest(SupportTests BlockFrequencyTest.cpp Casting.cpp CommandLineTest.cpp + CompressionTest.cpp ConstantRangeTest.cpp DataExtractorTest.cpp EndianTest.cpp @@ -23,6 +24,7 @@ add_llvm_unittest(SupportTests MemoryTest.cpp Path.cpp ProcessTest.cpp + ProgramTest.cpp RegexTest.cpp SwapByteOrderTest.cpp TimeValue.cpp diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index 43c8cbd123b4..cd235d274e6c 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -41,6 +41,45 @@ class TempEnvVar { const char *const name; }; +cl::OptionCategory TestCategory("Test Options", "Description"); +cl::opt<int> TestOption("test-option", cl::desc("old description")); +TEST(CommandLineTest, ModifyExisitingOption) { + const char Description[] = "New description"; + const char ArgString[] = "new-test-option"; + const char ValueString[] = "Integer"; + + StringMap<cl::Option*> Map; + cl::getRegisteredOptions(Map); + + ASSERT_TRUE(Map.count("test-option") == 1) << + "Could not find option in map."; + + cl::Option *Retrieved = Map["test-option"]; + ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option."; + + ASSERT_EQ(&cl::GeneralCategory,Retrieved->Category) << + "Incorrect default option category."; + + Retrieved->setCategory(TestCategory); + ASSERT_EQ(&TestCategory,Retrieved->Category) << + "Failed to modify option's option category."; + + Retrieved->setDescription(Description); + ASSERT_STREQ(Retrieved->HelpStr, Description) << + "Changing option description failed."; + + Retrieved->setArgStr(ArgString); + ASSERT_STREQ(ArgString, Retrieved->ArgStr) << + "Failed to modify option's Argument string."; + + Retrieved->setValueStr(ValueString); + ASSERT_STREQ(Retrieved->ValueStr, ValueString) << + "Failed to modify option's Value string."; + + Retrieved->setHiddenFlag(cl::Hidden); + ASSERT_EQ(cl::Hidden, TestOption.getOptionHiddenFlag()) << + "Failed to modify option's hidden flag."; +} #ifndef SKIP_ENVIRONMENT_TESTS const char test_env_var[] = "LLVM_TEST_COMMAND_LINE_FLAGS"; @@ -55,6 +94,12 @@ TEST(CommandLineTest, ParseEnvironment) { // This test used to make valgrind complain // ("Conditional jump or move depends on uninitialised value(s)") +// +// Warning: Do not run any tests after this one that try to gain access to +// registered command line options because this will likely result in a +// SEGFAULT. This can occur because the cl::opt in the test below is declared +// on the stack which will be destroyed after the test completes but the +// command line system will still hold a pointer to a deallocated cl::Option. TEST(CommandLineTest, ParseEnvironmentToLocalVar) { // Put cl::opt on stack to check for proper initialization of fields. cl::opt<std::string> EnvironmentTestOptionLocal("env-test-opt-local"); @@ -66,4 +111,11 @@ TEST(CommandLineTest, ParseEnvironmentToLocalVar) { #endif // SKIP_ENVIRONMENT_TESTS +TEST(CommandLineTest, UseOptionCategory) { + cl::opt<int> TestOption2("test-option", cl::cat(TestCategory)); + + ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option " + "Category."; +} + } // anonymous namespace diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp new file mode 100644 index 000000000000..c8e2cd9f02b6 --- /dev/null +++ b/unittests/Support/CompressionTest.cpp @@ -0,0 +1,68 @@ +//===- llvm/unittest/Support/CompressionTest.cpp - Compression tests ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements unit tests for the Compression functions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Compression.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Config/config.h" +#include "llvm/Support/MemoryBuffer.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +#if LLVM_ENABLE_ZLIB == 1 && HAVE_LIBZ + +void TestZlibCompression(StringRef Input, zlib::CompressionLevel Level) { + OwningPtr<MemoryBuffer> Compressed; + OwningPtr<MemoryBuffer> Uncompressed; + EXPECT_EQ(zlib::StatusOK, zlib::compress(Input, Compressed, Level)); + // Check that uncompressed buffer is the same as original. + EXPECT_EQ(zlib::StatusOK, zlib::uncompress(Compressed->getBuffer(), + Uncompressed, Input.size())); + EXPECT_EQ(Input.size(), Uncompressed->getBufferSize()); + EXPECT_EQ(0, + memcmp(Input.data(), Uncompressed->getBufferStart(), Input.size())); + if (Input.size() > 0) { + // Uncompression fails if expected length is too short. + EXPECT_EQ(zlib::StatusBufferTooShort, + zlib::uncompress(Compressed->getBuffer(), Uncompressed, + Input.size() - 1)); + } +} + +TEST(CompressionTest, Zlib) { + TestZlibCompression("", zlib::DefaultCompression); + + TestZlibCompression("hello, world!", zlib::NoCompression); + TestZlibCompression("hello, world!", zlib::BestSizeCompression); + TestZlibCompression("hello, world!", zlib::BestSpeedCompression); + TestZlibCompression("hello, world!", zlib::DefaultCompression); + + const size_t kSize = 1024; + char BinaryData[kSize]; + for (size_t i = 0; i < kSize; ++i) { + BinaryData[i] = i & 255; + } + StringRef BinaryDataStr(BinaryData, kSize); + + TestZlibCompression(BinaryDataStr, zlib::NoCompression); + TestZlibCompression(BinaryDataStr, zlib::BestSizeCompression); + TestZlibCompression(BinaryDataStr, zlib::BestSpeedCompression); + TestZlibCompression(BinaryDataStr, zlib::DefaultCompression); +} + +#endif + +} diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index 45112597979c..eec8c62d8c84 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -298,12 +298,19 @@ TEST_F(FileSystemTest, DirectoryIteration) { ASSERT_LT(z0, za1); } +const char elf[] = {0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + TEST_F(FileSystemTest, Magic) { struct type { const char *filename; const char *magic_str; - size_t magic_str_len; - } types [] = {{"magic.archive", "!<arch>\x0A", 8}}; + size_t magic_str_len; + fs::file_magic magic; + } types [] = { + {"magic.archive", "!<arch>\x0A", 8, fs::file_magic::archive}, + {"magic.elf", elf, sizeof(elf), + fs::file_magic::elf_relocatable} + }; // Create some files filled with magic. for (type *i = types, *e = types + (sizeof(types) / sizeof(type)); i != e; @@ -320,6 +327,7 @@ TEST_F(FileSystemTest, Magic) { bool res = false; ASSERT_NO_ERROR(fs::has_magic(file_pathname.c_str(), magic, res)); EXPECT_TRUE(res); + EXPECT_EQ(i->magic, fs::identify_magic(magic)); } } diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp new file mode 100644 index 000000000000..6cbb05454f80 --- /dev/null +++ b/unittests/Support/ProgramTest.cpp @@ -0,0 +1,89 @@ +//===- unittest/Support/ProgramTest.cpp -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" +#include "gtest/gtest.h" + +#include <stdlib.h> +#if defined(__APPLE__) +# include <crt_externs.h> +#elif !defined(_MSC_VER) +// Forward declare environ in case it's not provided by stdlib.h. +extern char **environ; +#endif + +// From TestMain.cpp. +extern const char *TestMainArgv0; + +namespace { + +using namespace llvm; +using namespace sys; + +static cl::opt<std::string> +ProgramTestStringArg1("program-test-string-arg1"); +static cl::opt<std::string> +ProgramTestStringArg2("program-test-string-arg2"); + +static void CopyEnvironment(std::vector<const char *> &out) { +#ifdef __APPLE__ + char **envp = *_NSGetEnviron(); +#else + // environ seems to work for Windows and most other Unices. + char **envp = environ; +#endif + while (*envp != 0) { + out.push_back(*envp); + ++envp; + } +} + +TEST(ProgramTest, CreateProcessTrailingSlash) { + if (getenv("LLVM_PROGRAM_TEST_CHILD")) { + if (ProgramTestStringArg1 == "has\\\\ trailing\\" && + ProgramTestStringArg2 == "has\\\\ trailing\\") { + exit(0); // Success! The arguments were passed and parsed. + } + exit(1); + } + + Path my_exe = Path::GetMainExecutable(TestMainArgv0, &ProgramTestStringArg1); + const char *argv[] = { + my_exe.c_str(), + "--gtest_filter=ProgramTest.CreateProcessTrailingSlashChild", + "-program-test-string-arg1", "has\\\\ trailing\\", + "-program-test-string-arg2", "has\\\\ trailing\\", + 0 + }; + + // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child. + std::vector<const char *> envp; + CopyEnvironment(envp); + envp.push_back("LLVM_PROGRAM_TEST_CHILD=1"); + envp.push_back(0); + + std::string error; + bool ExecutionFailed; + // Redirect stdout and stdin to NUL, but let stderr through. +#ifdef LLVM_ON_WIN32 + Path nul("NUL"); +#else + Path nul("/dev/null"); +#endif + const Path *redirects[] = { &nul, &nul, 0 }; + int rc = Program::ExecuteAndWait(my_exe, argv, &envp[0], redirects, + /*secondsToWait=*/10, /*memoryLimit=*/0, + &error, &ExecutionFailed); + EXPECT_FALSE(ExecutionFailed) << error; + EXPECT_EQ(0, rc); +} + +} // end anonymous namespace diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index cd304e720082..e19ae5bc2fb4 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -7,12 +7,15 @@ // //===----------------------------------------------------------------------===// -#include "llvm/IR/Instructions.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/Transforms/Utils/Cloning.h" #include "gtest/gtest.h" using namespace llvm; @@ -143,4 +146,31 @@ TEST_F(CloneInstruction, Exact) { EXPECT_TRUE(this->clone(SDiv)->isExact()); } +TEST_F(CloneInstruction, Attributes) { + Type *ArgTy1[] = { Type::getInt32PtrTy(context) }; + FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); + + Function *F1 = Function::Create(FT1, Function::ExternalLinkage); + BasicBlock *BB = BasicBlock::Create(context, "", F1); + IRBuilder<> Builder(BB); + Builder.CreateRetVoid(); + + Function *F2 = Function::Create(FT1, Function::ExternalLinkage); + + Attribute::AttrKind AK[] = { Attribute::NoCapture }; + AttributeSet AS = AttributeSet::get(context, 0, AK); + Argument *A = F1->arg_begin(); + A->addAttr(AS); + + SmallVector<ReturnInst*, 4> Returns; + ValueToValueMapTy VMap; + VMap[A] = UndefValue::get(A->getType()); + + CloneFunctionInto(F2, F1, VMap, false, Returns); + EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr()); + + delete F1; + delete F2; +} + } |