From dc4260db2a8df312268771fdfb8e9db5cd522508 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Mon, 20 Apr 2015 20:41:45 +0000 Subject: [PATCH] [Orc] Make the makeStub function propagate argument attributes onto the call to the function body. This is necessary for correctness when lazily compiling. Also, flesh out the Orc unit test infrastructure slightly, and add a unit test for this. llvm-svn: 235347 --- llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp | 1 + llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt | 3 + .../ExecutionEngine/Orc/IndirectionUtilsTest.cpp | 48 ++++++++++++++++ .../ExecutionEngine/Orc/OrcTestCommon.cpp | 23 ++++++++ llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h | 65 ++++++++++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp create mode 100644 llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp create mode 100644 llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp index ebeedef..75b6108 100644 --- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -49,6 +49,7 @@ void makeStub(Function &F, GlobalVariable &ImplPointer) { CallArgs.push_back(&A); CallInst *Call = Builder.CreateCall(ImplAddr, CallArgs); Call->setTailCall(); + Call->setAttributes(F.getAttributes()); Builder.CreateRet(Call); } diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt index 7bc13a1..67b215e 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt @@ -1,8 +1,11 @@ set(LLVM_LINK_COMPONENTS Core + OrcJIT Support ) add_llvm_unittest(OrcJITTests + IndirectionUtilsTest.cpp LazyEmittingLayerTest.cpp + OrcTestCommon.cpp ) diff --git a/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp new file mode 100644 index 0000000..1a533b05 --- /dev/null +++ b/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp @@ -0,0 +1,48 @@ +//===- LazyEmittingLayerTest.cpp - Unit tests for the lazy emitting layer -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "OrcTestCommon.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(IndirectionUtilsTest, MakeStub) { + ModuleBuilder MB(getGlobalContext(), "x86_64-apple-macosx10.10", ""); + Function *F = MB.createFunctionDecl(MB.getModule(), ""); + SmallVector Attrs; + Attrs.push_back( + AttributeSet::get(MB.getModule()->getContext(), 1U, + AttrBuilder().addAttribute(Attribute::StructRet))); + Attrs.push_back( + AttributeSet::get(MB.getModule()->getContext(), 2U, + AttrBuilder().addAttribute(Attribute::ByVal))); + Attrs.push_back( + AttributeSet::get(MB.getModule()->getContext(), ~0U, + AttrBuilder().addAttribute(Attribute::NoUnwind))); + F->setAttributes(AttributeSet::get(MB.getModule()->getContext(), Attrs)); + + auto ImplPtr = orc::createImplPointer(*F->getType(), *MB.getModule(), "", nullptr); + orc::makeStub(*F, *ImplPtr); + + auto II = F->getEntryBlock().begin(); + EXPECT_TRUE(isa(*II)) << "First instruction of stub should be a load."; + auto *Call = dyn_cast(std::next(II)); + EXPECT_TRUE(Call != nullptr) << "Second instruction of stub should be a call."; + EXPECT_TRUE(Call->isTailCall()) << "Indirect call from stub should be tail call."; + EXPECT_TRUE(Call->hasStructRetAttr()) + << "makeStub should propagate sret attr on 1st argument."; + EXPECT_TRUE(Call->paramHasAttr(2U, Attribute::ByVal)) + << "makeStub should propagate byval attr on 2nd argument."; +} + +} diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp new file mode 100644 index 0000000..5fea3c8 --- /dev/null +++ b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp @@ -0,0 +1,23 @@ +//===--------- OrcTestCommon.cpp - Utilities for Orc Unit Tests -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Common utilities for Orc unit tests. +// +//===----------------------------------------------------------------------===// + +#include "OrcTestCommon.h" + +using namespace llvm; + +ModuleBuilder::ModuleBuilder(LLVMContext &Context, StringRef Triple, + StringRef Name) + : M(new Module(Name, Context)), + Builder(Context) { + M->setTargetTriple(Triple); +} diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h new file mode 100644 index 0000000..3ae2ed8 --- /dev/null +++ b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h @@ -0,0 +1,65 @@ +//===------ OrcTestCommon.h - Utilities for Orc Unit Tests ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Common utilities for the Orc unit tests. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H +#define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/TypeBuilder.h" +#include + +namespace llvm { + + class ModuleBuilder { + public: + ModuleBuilder(LLVMContext &Context, StringRef Triple, + StringRef Name); + + template + Function* createFunctionDecl(Module *M, StringRef Name) { + return Function::Create( + TypeBuilder::get(M->getContext()), + GlobalValue::ExternalLinkage, Name, M); + } + + Module* getModule() { return M.get(); } + const Module* getModule() const { return M.get(); } + std::unique_ptr takeModule() { return std::move(M); } + + private: + std::unique_ptr M; + IRBuilder<> Builder; + }; + + // Dummy struct type. + struct DummyStruct { + int X[256]; + }; + + // TypeBuilder specialization for DummyStruct. + template + class TypeBuilder { + public: + static StructType *get(LLVMContext &Context) { + return StructType::get(TypeBuilder[256], XCompile>::get(Context), NULL); + } + }; + + +} // namespace llvm + +#endif -- 2.7.4