From 4d188a6524083ef79dae910215d4b34fad595358 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 14 Jul 2021 22:21:06 +0200 Subject: [PATCH] [Verifier] Require same signature for intrinsic calls As suggested on D105733, this adds a verifier rule that calls to intrinsics must match the signature of the intrinsic. Without opaque pointers this is automatically enforced for all calls, because the pointer types need to match. If the signatures don't match, a pointer bitcast has to be inserted. For intrinsics in particular, such bitcasts are not legal, because the address of intrinsics cannot be taken. With opaque pointers, there are no more pointer bitcasts, so it's generally possible for the call and the callee signature to differ. However, for intrinsics we still want to enforce that the signatures must match, the same as was done before through the address taken check. We can't enforce this more generally for non-intrinsics, because calls with mismatched signatures at the very least can legally occur in unreachable code, and might also be valid in some other cases, depending on how exactly the signatures differ. Differential Revision: https://reviews.llvm.org/D106013 --- llvm/lib/IR/Verifier.cpp | 7 ++++--- llvm/test/Verifier/force-opaque-ptr.ll | 9 +++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 llvm/test/Verifier/force-opaque-ptr.ll diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 67ed73f..d23603c 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3064,11 +3064,12 @@ void Verifier::visitCallBase(CallBase &Call) { Assert(verifyAttributeCount(Attrs, Call.arg_size()), "Attribute after last parameter!", Call); - bool IsIntrinsic = Call.getCalledFunction() && - Call.getCalledFunction()->isIntrinsic(); - Function *Callee = dyn_cast(Call.getCalledOperand()->stripPointerCasts()); + bool IsIntrinsic = Callee && Callee->isIntrinsic(); + if (IsIntrinsic) + Assert(Callee->getValueType() == FTy, + "Intrinsic called with incompatible signature", Call); if (Attrs.hasFnAttribute(Attribute::Speculatable)) { // Don't allow speculatable on call sites, unless the underlying function diff --git a/llvm/test/Verifier/force-opaque-ptr.ll b/llvm/test/Verifier/force-opaque-ptr.ll new file mode 100644 index 0000000..913480b --- /dev/null +++ b/llvm/test/Verifier/force-opaque-ptr.ll @@ -0,0 +1,9 @@ +; RUN: not opt -passes=verify -force-opaque-pointers -S < %s 2>&1 | FileCheck %s + +declare i32 @llvm.umax.i32(i32, i32) + +define void @intrinsic_signature_mismatch() { +; CHECK: Intrinsic called with incompatible signature + call i32 @llvm.umax.i32(i32 0) + ret void +} -- 2.7.4