1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00
llvm-mirror/test/Verifier/preallocated-invalid.ll
Nikita Popov b227a46d3d [Verifier] Improve incompatible attribute type check
A couple of attributes had explicit checks for incompatibility
with pointer types. However, this is already handled generically
by the typeIncompatible() check. We can drop these after adding
SwiftError to typeIncompatible().

However, the previous implementation of the check prints out all
attributes that are incompatible with a given type, even though
those attributes aren't actually used. This has the annoying
result that the error message changes every time a new attribute
is added to the list. Improve this by explicitly finding which
attribute isn't compatible and printing just that.
2021-07-14 21:02:10 +02:00

151 lines
5.6 KiB
LLVM

; RUN: not opt -S %s -verify 2>&1 | FileCheck %s
declare token @llvm.call.preallocated.setup(i32)
declare i8* @llvm.call.preallocated.arg(token, i32)
declare void @llvm.call.preallocated.teardown(token)
; Fake LLVM intrinsic to return a token
declare token @llvm.what()
declare void @foo0()
declare void @foo1(i32* preallocated(i32))
declare void @foo2(i32* preallocated(i32), i32*, i32* preallocated(i32))
declare i32 @blackbox()
; CHECK: llvm.call.preallocated.arg must be called with a "preallocated" call site attribute
define void @preallocated_arg_missing_preallocated_attribute() {
%cs = call token @llvm.call.preallocated.setup(i32 1)
%x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0)
%y = bitcast i8* %x to i32*
call void @foo1(i32* preallocated(i32) %y) ["preallocated"(token %cs)]
ret void
}
; CHECK: preallocated as a call site attribute can only be on llvm.call.preallocated.arg
define void @preallocated_call_site_attribute_not_on_arg() {
call void @foo0() preallocated(i32)
ret void
}
; CHECK: "preallocated" argument must be a token from llvm.call.preallocated.setup
define void @preallocated_bundle_token() {
%i = call i32 @blackbox()
call void @foo0() ["preallocated"(i32 %i)]
ret void
}
; CHECK: "preallocated" argument must be a token from llvm.call.preallocated.setup
define void @preallocated_bundle_token_from_setup() {
%cs = call token @llvm.what()
call void @foo0() ["preallocated"(token %cs)]
ret void
}
; CHECK: Expected exactly one preallocated bundle operand
define void @preallocated_bundle_one_token() {
%cs0 = call token @llvm.call.preallocated.setup(i32 0)
%cs1 = call token @llvm.call.preallocated.setup(i32 0)
call void @foo0() ["preallocated"(token %cs0, token %cs1)]
ret void
}
; CHECK: Multiple preallocated operand bundles
define void @preallocated_multiple_bundles() {
%cs0 = call token @llvm.call.preallocated.setup(i32 0)
%cs1 = call token @llvm.call.preallocated.setup(i32 0)
call void @foo0() ["preallocated"(token %cs0), "preallocated"(token %cs1)]
ret void
}
; CHECK: Can have at most one call
define void @preallocated_one_call() {
%cs = call token @llvm.call.preallocated.setup(i32 1)
%x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
%y = bitcast i8* %x to i32*
call void @foo1(i32* preallocated(i32) %y) ["preallocated"(token %cs)]
call void @foo1(i32* preallocated(i32) %y) ["preallocated"(token %cs)]
ret void
}
; CHECK: must be a constant
define void @preallocated_setup_constant() {
%ac = call i32 @blackbox()
%cs = call token @llvm.call.preallocated.setup(i32 %ac)
ret void
}
; CHECK: must be between 0 and corresponding
define void @preallocated_setup_arg_index_in_bounds() {
%cs = call token @llvm.call.preallocated.setup(i32 2)
%a0 = call i8* @llvm.call.preallocated.arg(token %cs, i32 2) preallocated(i32)
ret void
}
; CHECK: Attribute 'preallocated' type does not match parameter
define void @preallocated_attribute_type_mismatch() {
%cs = call token @llvm.call.preallocated.setup(i32 1)
%x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
%y = bitcast i8* %x to i32*
call void @foo1(i32* preallocated(i8) %y) ["preallocated"(token %cs)]
ret void
}
; CHECK: preallocated operand either requires a preallocated bundle or the call to be musttail
define void @preallocated_require_bundle() {
%cs = call token @llvm.call.preallocated.setup(i32 1)
%x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
%y = bitcast i8* %x to i32*
call void @foo1(i32* preallocated(i32) %y)
ret void
}
; CHECK: arg size must be equal to number of preallocated arguments
define void @preallocated_num_args() {
%cs = call token @llvm.call.preallocated.setup(i32 3)
%x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
%x1 = bitcast i8* %x to i32*
%y = call i8* @llvm.call.preallocated.arg(token %cs, i32 1) preallocated(i32)
%y1 = bitcast i8* %y to i32*
%a = inttoptr i32 0 to i32*
call void @foo2(i32* preallocated(i32) %x1, i32* %a, i32* preallocated(i32) %y1) ["preallocated"(token %cs)]
ret void
}
; CHECK: token argument must be a llvm.call.preallocated.setup
define void @preallocated_arg_token() {
%t = call token @llvm.what()
%x = call i8* @llvm.call.preallocated.arg(token %t, i32 1) preallocated(i32)
ret void
}
; CHECK: cannot use preallocated intrinsics on a call without preallocated arguments
define void @preallocated_no_preallocated_args() {
%cs = call token @llvm.call.preallocated.setup(i32 0)
call void @foo0() ["preallocated"(token %cs)]
ret void
}
; CHECK: preallocated operand either requires a preallocated bundle or the call to be musttail
define void @musttail_and_bundle(i32* preallocated(i32) %a) {
%cs = call token @llvm.call.preallocated.setup(i32 0)
musttail call void @musttail_and_bundle(i32* preallocated(i32) %a) ["preallocated"(token %cs)]
ret void
}
; CHECK: cannot guarantee tail call due to mismatched ABI impacting function attributes
define void @musttail_attr_no_match(i32* preallocated(i32) %a) {
musttail call void @musttail_and_bundle(i32* %a)
ret void
}
; CHECK: token argument must be a llvm.call.preallocated.setup
define void @teardown_token_not_from_setup() {
%cs = call token @llvm.what()
call void @llvm.call.preallocated.teardown(token %cs)
ret void
}
; CHECK: Attribute 'preallocated(i32)' applied to incompatible type!
; CHECK-NEXT: void (i32)* @not_pointer
declare void @not_pointer(i32 preallocated(i32))