[OpaquePtr] Remove checking pointee type for byval/preallocated type
authorArthur Eubanks <aeubanks@google.com>
Wed, 7 Jul 2021 21:28:41 +0000 (14:28 -0700)
committerArthur Eubanks <aeubanks@google.com>
Wed, 7 Jul 2021 21:28:55 +0000 (14:28 -0700)
These currently always require a type parameter. The bitcode reader
already upgrades old bitcode without the type parameter to use the
pointee type.

In cases where the caller does not have byval but the callee does, we
need to follow CallBase::paramHasAttr() and also look at the callee for
the byval type so that CallBase::isByValArgument() and
CallBase::getParamByValType() are in sync. Do the same for preallocated.

While we're here add a corresponding version for inalloca since we'll
need it soon.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D104663

llvm/include/llvm/IR/InstrTypes.h
llvm/unittests/IR/AttributesTest.cpp

index c690306..0e372d1 100644 (file)
@@ -1728,14 +1728,29 @@ public:
 
   /// Extract the byval type for a call or parameter.
   Type *getParamByValType(unsigned ArgNo) const {
-    Type *Ty = Attrs.getParamByValType(ArgNo);
-    return Ty ? Ty : getArgOperand(ArgNo)->getType()->getPointerElementType();
+    if (auto *Ty = Attrs.getParamByValType(ArgNo))
+      return Ty;
+    if (const Function *F = getCalledFunction())
+      return F->getAttributes().getParamByValType(ArgNo);
+    return nullptr;
   }
 
   /// Extract the preallocated type for a call or parameter.
   Type *getParamPreallocatedType(unsigned ArgNo) const {
-    Type *Ty = Attrs.getParamPreallocatedType(ArgNo);
-    return Ty ? Ty : getArgOperand(ArgNo)->getType()->getPointerElementType();
+    if (auto *Ty = Attrs.getParamPreallocatedType(ArgNo))
+      return Ty;
+    if (const Function *F = getCalledFunction())
+      return F->getAttributes().getParamPreallocatedType(ArgNo);
+    return nullptr;
+  }
+
+  /// Extract the preallocated type for a call or parameter.
+  Type *getParamInAllocaType(unsigned ArgNo) const {
+    if (auto *Ty = Attrs.getParamInAllocaType(ArgNo))
+      return Ty;
+    if (const Function *F = getCalledFunction())
+      return F->getAttributes().getParamInAllocaType(ArgNo);
+    return nullptr;
   }
 
   /// Extract the number of dereferenceable bytes for a call or
index f260f0f..d29df4c 100644 (file)
@@ -7,8 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/IR/Attributes.h"
-#include "llvm/IR/LLVMContext.h"
+#include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 using namespace llvm;
 
@@ -252,4 +256,44 @@ TEST(Attributes, AttributeListPrinting) {
   }
 }
 
+TEST(Attributes, MismatchedABIAttrs) {
+  const char *IRString = R"IR(
+    declare void @f1(i32* byval(i32))
+    define void @g() {
+      call void @f1(i32* null)
+      ret void
+    }
+    declare void @f2(i32* preallocated(i32))
+    define void @h() {
+      call void @f2(i32* null)
+      ret void
+    }
+    declare void @f3(i32* inalloca(i32))
+    define void @i() {
+      call void @f3(i32* null)
+      ret void
+    }
+  )IR";
+
+  SMDiagnostic Err;
+  LLVMContext Context;
+  std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context);
+  ASSERT_TRUE(M);
+
+  {
+    auto *I = cast<CallBase>(&M->getFunction("g")->getEntryBlock().front());
+    ASSERT_TRUE(I->isByValArgument(0));
+    ASSERT_TRUE(I->getParamByValType(0));
+  }
+  {
+    auto *I = cast<CallBase>(&M->getFunction("h")->getEntryBlock().front());
+    ASSERT_TRUE(I->getParamPreallocatedType(0));
+  }
+  {
+    auto *I = cast<CallBase>(&M->getFunction("i")->getEntryBlock().front());
+    ASSERT_TRUE(I->isInAllocaArgument(0));
+    ASSERT_TRUE(I->getParamInAllocaType(0));
+  }
+}
+
 } // end anonymous namespace