From c4786d15291cbaa8d29ea1055fc606a1f4981f58 Mon Sep 17 00:00:00 2001 From: Serguei Katkov Date: Tue, 21 Aug 2018 04:27:07 +0000 Subject: [PATCH] [IR Verifier] Do not allow bitcast of pointer to vector of pointers and vice versa. LangRef for BitCast requires that "The bit sizes of value and the destination type, ty2, must be identical". Currently verifier allows BitCast of pointer to vector of pointers so that the sizes are different. This change fixes that. Reviewers: arsenm Reviewed By: arsenm Subscribers: llvm-commits, wdng Differential Revision: https://reviews.llvm.org/D50886 llvm-svn: 340249 --- lib/IR/Instructions.cpp | 14 ++++++++------ test/Verifier/bitcast-pointer-vector-neg.ll | 10 ++++++++++ test/Verifier/bitcast-vector-pointer-as-neg.ll | 15 +++++++++++++++ test/Verifier/bitcast-vector-pointer-neg.ll | 10 ++++++++++ test/Verifier/bitcast-vector-pointer-pos.ll | 14 ++++++++++++++ 5 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 test/Verifier/bitcast-pointer-vector-neg.ll create mode 100644 test/Verifier/bitcast-vector-pointer-as-neg.ll create mode 100644 test/Verifier/bitcast-vector-pointer-neg.ll create mode 100644 test/Verifier/bitcast-vector-pointer-pos.ll diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index 32db918dab9..d8470ac567d 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -2978,12 +2978,14 @@ CastInst::castIsValid(Instruction::CastOps op, Value *S, Type *DstTy) { return false; // A vector of pointers must have the same number of elements. - if (VectorType *SrcVecTy = dyn_cast(SrcTy)) { - if (VectorType *DstVecTy = dyn_cast(DstTy)) - return (SrcVecTy->getNumElements() == DstVecTy->getNumElements()); - - return false; - } + VectorType *SrcVecTy = dyn_cast(SrcTy); + VectorType *DstVecTy = dyn_cast(DstTy); + if (SrcVecTy && DstVecTy) + return (SrcVecTy->getNumElements() == DstVecTy->getNumElements()); + if (SrcVecTy) + return SrcVecTy->getNumElements() == 1; + if (DstVecTy) + return DstVecTy->getNumElements() == 1; return true; } diff --git a/test/Verifier/bitcast-pointer-vector-neg.ll b/test/Verifier/bitcast-pointer-vector-neg.ll new file mode 100644 index 00000000000..68b67725471 --- /dev/null +++ b/test/Verifier/bitcast-pointer-vector-neg.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s + +target datalayout = "e-p:32:32:32-p1:16:16:16-p2:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n8:16:32" + +; CHECK: error: invalid cast opcode for cast from 'i64*' to '<2 x i32*>' + +define <2 x i32*> @illegal_bitcast_pointer_to_vector_of_pointers(i64* %a) { + %b = bitcast i64* %a to <2 x i32*> + ret <2 x i32*> %b +} diff --git a/test/Verifier/bitcast-vector-pointer-as-neg.ll b/test/Verifier/bitcast-vector-pointer-as-neg.ll new file mode 100644 index 00000000000..dbd7356b707 --- /dev/null +++ b/test/Verifier/bitcast-vector-pointer-as-neg.ll @@ -0,0 +1,15 @@ +; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s + +target datalayout = "e-p:32:32:32-p1:16:16:16-p2:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n8:16:32" + +; CHECK: error: invalid cast opcode for cast from '<4 x i32 addrspace(1)*>' to '<2 x i32 addrspace(2)*>' + +; The pointer in addrspace 1 of the size 16 while pointer in addrspace 2 of the size 32. +; Converting 4 element array of pointers from addrspace 2 to 2 element array in addrspace 2 +; has the same total bit length but bitcast still does not allow conversion into +; different addrspace. +define <2 x i32 addrspace(2)*> @vector_illegal_bitcast_as_1_to_2(<4 x i32 addrspace(1)*> %p) { + %cast = bitcast <4 x i32 addrspace(1)*> %p to <2 x i32 addrspace(2)*> + ret <2 x i32 addrspace(2)*> %cast +} + diff --git a/test/Verifier/bitcast-vector-pointer-neg.ll b/test/Verifier/bitcast-vector-pointer-neg.ll new file mode 100644 index 00000000000..ce70a3f77e9 --- /dev/null +++ b/test/Verifier/bitcast-vector-pointer-neg.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s + +target datalayout = "e-p:32:32:32-p1:16:16:16-p2:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n8:16:32" + +; CHECK: error: invalid cast opcode for cast from '<2 x i32*>' to 'i64*' + +define i64* @illegal_bitcast_vector_of_pointers_to_pointer(<2 x i32*> %a) { + %b = bitcast <2 x i32*> %a to i64* + ret i64* %b +} diff --git a/test/Verifier/bitcast-vector-pointer-pos.ll b/test/Verifier/bitcast-vector-pointer-pos.ll new file mode 100644 index 00000000000..6a08f1135c8 --- /dev/null +++ b/test/Verifier/bitcast-vector-pointer-pos.ll @@ -0,0 +1,14 @@ +; RUN: llvm-as -disable-output %s + +target datalayout = "e-p:32:32:32-p1:16:16:16-p2:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n8:16:32" + +define <1 x i32*> @vector_legal_bitcast_pointer_to_vector_of_pointers(i64* %a) { + %b = bitcast i64* %a to <1 x i32*> + ret <1 x i32*> %b +} + +define i64* @vector_legal_bitcast_vector_of_pointers_to_pointer(<1 x i32*> %a) { + %b = bitcast <1 x i32*> %a to i64* + ret i64* %b +} +