[Orc] Make the makeStub function propagate argument attributes onto the call to
authorLang Hames <lhames@gmail.com>
Mon, 20 Apr 2015 20:41:45 +0000 (20:41 +0000)
committerLang Hames <lhames@gmail.com>
Mon, 20 Apr 2015 20:41:45 +0000 (20:41 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235347 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ExecutionEngine/Orc/IndirectionUtils.cpp
unittests/ExecutionEngine/Orc/CMakeLists.txt
unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp [new file with mode: 0644]
unittests/ExecutionEngine/Orc/OrcTestCommon.cpp [new file with mode: 0644]
unittests/ExecutionEngine/Orc/OrcTestCommon.h [new file with mode: 0644]

index ebeedef7eae857c36d2e2c4431d63481a7c4119d..75b610876b7e707a15c817dfaf3b8c0140b96902 100644 (file)
@@ -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);
 }
 
index 7bc13a17524d2ef8a00e0c739059eb6cdde17d8c..67b215ebc6d4e4b7d8a630149bed1c51b9b9f975 100644 (file)
@@ -1,8 +1,11 @@
 set(LLVM_LINK_COMPONENTS
   Core
+  OrcJIT
   Support
   )
 
 add_llvm_unittest(OrcJITTests
+  IndirectionUtilsTest.cpp
   LazyEmittingLayerTest.cpp
+  OrcTestCommon.cpp
   )
diff --git a/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp b/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp
new file mode 100644 (file)
index 0000000..1a533b0
--- /dev/null
@@ -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<void(DummyStruct, DummyStruct)>(MB.getModule(), "");
+  SmallVector<AttributeSet, 4> 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<LoadInst>(*II)) << "First instruction of stub should be a load.";
+  auto *Call = dyn_cast<CallInst>(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/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp b/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp
new file mode 100644 (file)
index 0000000..5fea3c8
--- /dev/null
@@ -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/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/unittests/ExecutionEngine/Orc/OrcTestCommon.h
new file mode 100644 (file)
index 0000000..3ae2ed8
--- /dev/null
@@ -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 <memory>
+
+namespace llvm {
+
+  class ModuleBuilder {
+  public:
+    ModuleBuilder(LLVMContext &Context, StringRef Triple,
+                  StringRef Name);
+
+    template <typename FuncType>
+    Function* createFunctionDecl(Module *M, StringRef Name) {
+      return Function::Create(
+               TypeBuilder<FuncType, false>::get(M->getContext()),
+               GlobalValue::ExternalLinkage, Name, M);
+    }
+
+    Module* getModule() { return M.get(); }
+    const Module* getModule() const { return M.get(); }
+    std::unique_ptr<Module> takeModule() { return std::move(M); }
+
+  private:
+    std::unique_ptr<Module> M;
+    IRBuilder<> Builder;
+  };
+
+  // Dummy struct type.
+  struct DummyStruct {
+    int X[256];
+  };
+
+  // TypeBuilder specialization for DummyStruct.
+  template <bool XCompile>
+  class TypeBuilder<DummyStruct, XCompile> {
+  public:
+    static StructType *get(LLVMContext &Context) {
+      return StructType::get(TypeBuilder<types::i<32>[256], XCompile>::get(Context), NULL);
+    }
+  };
+
+
+} // namespace llvm
+
+#endif