[Verifier] Add checks for range attribute on ImmArg (#140522)
This patch implements verifier checks for range attributes on ImmArg. This enables validation of the range of ImmArg operands in intrinsics, when the intrinsic definition includes the range information. Signed-off-by: Durgadoss R <durgadossr@nvidia.com>
This commit is contained in:
@@ -1987,8 +1987,12 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
|
||||
V);
|
||||
|
||||
if (Attrs.hasAttribute(Attribute::ImmArg)) {
|
||||
Check(Attrs.getNumAttributes() == 1,
|
||||
"Attribute 'immarg' is incompatible with other attributes", V);
|
||||
unsigned AttrCount =
|
||||
Attrs.getNumAttributes() - Attrs.hasAttribute(Attribute::Range);
|
||||
Check(AttrCount == 1,
|
||||
"Attribute 'immarg' is incompatible with other attributes except the "
|
||||
"'range' attribute",
|
||||
V);
|
||||
}
|
||||
|
||||
// Check for mutually incompatible attributes. Only inreg is compatible with
|
||||
@@ -3680,6 +3684,20 @@ void Verifier::visitCallBase(CallBase &Call) {
|
||||
Value *ArgVal = Call.getArgOperand(i);
|
||||
Check(isa<ConstantInt>(ArgVal) || isa<ConstantFP>(ArgVal),
|
||||
"immarg operand has non-immediate parameter", ArgVal, Call);
|
||||
|
||||
// If the imm-arg is an integer and also has a range attached,
|
||||
// check if the given value is within the range.
|
||||
if (Call.paramHasAttr(i, Attribute::Range)) {
|
||||
if (auto *CI = dyn_cast<ConstantInt>(ArgVal)) {
|
||||
const ConstantRange &CR =
|
||||
Call.getParamAttr(i, Attribute::Range).getValueAsConstantRange();
|
||||
Check(CR.contains(CI->getValue()),
|
||||
"immarg value " + Twine(CI->getValue().getSExtValue()) +
|
||||
" out of range [" + Twine(CR.getLower().getSExtValue()) +
|
||||
", " + Twine(CR.getUpper().getSExtValue()) + ")",
|
||||
Call);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Call.paramHasAttr(i, Attribute::Preallocated)) {
|
||||
|
||||
@@ -6,6 +6,9 @@ declare void @llvm.test.immarg.intrinsic.i32(i32 immarg)
|
||||
; CHECK: declare void @llvm.test.immarg.intrinsic.f32(float immarg)
|
||||
declare void @llvm.test.immarg.intrinsic.f32(float immarg)
|
||||
|
||||
; CHECK: declare void @llvm.test.immarg.range.intrinsic.i32(i32 immarg range(i32 -2, 14))
|
||||
declare void @llvm.test.immarg.range.intrinsic.i32(i32 immarg range(i32 -2, 14))
|
||||
|
||||
; CHECK-LABEL: @call_llvm.test.immarg.intrinsic.i32(
|
||||
define void @call_llvm.test.immarg.intrinsic.i32() {
|
||||
; CHECK: call void @llvm.test.immarg.intrinsic.i32(i32 0)
|
||||
@@ -37,3 +40,19 @@ define void @on_callsite_and_declaration() {
|
||||
call void @llvm.test.immarg.intrinsic.i32(i32 immarg 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test_int_immarg_with_range(
|
||||
define void @test_int_immarg_with_range() {
|
||||
; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 -2)
|
||||
call void @llvm.test.immarg.range.intrinsic.i32(i32 -2)
|
||||
|
||||
; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 0)
|
||||
call void @llvm.test.immarg.range.intrinsic.i32(i32 0)
|
||||
|
||||
; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 5)
|
||||
call void @llvm.test.immarg.range.intrinsic.i32(i32 5)
|
||||
|
||||
; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 13)
|
||||
call void @llvm.test.immarg.range.intrinsic.i32(i32 13)
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
|
||||
declare void @llvm.immarg.byval(ptr byval(i32) immarg)
|
||||
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
|
||||
declare void @llvm.immarg.inalloca(ptr inalloca(i32) immarg)
|
||||
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
|
||||
declare void @llvm.immarg.inreg(i32 inreg immarg)
|
||||
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
|
||||
declare void @llvm.immarg.nest(ptr nest immarg)
|
||||
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
|
||||
declare void @llvm.immarg.sret(ptr sret(i32) immarg)
|
||||
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
|
||||
declare void @llvm.immarg.zeroext(i32 zeroext immarg)
|
||||
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
|
||||
declare void @llvm.immarg.signext(i32 signext immarg)
|
||||
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
|
||||
declare void @llvm.immarg.returned(i32 returned immarg)
|
||||
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
|
||||
declare void @llvm.immarg.noalias(ptr noalias immarg)
|
||||
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
|
||||
declare void @llvm.immarg.readnone(ptr readnone immarg)
|
||||
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes
|
||||
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
|
||||
declare void @llvm.immarg.readonly(ptr readonly immarg)
|
||||
|
||||
4
llvm/test/Assembler/invalid-immarg4.ll
Normal file
4
llvm/test/Assembler/invalid-immarg4.ll
Normal file
@@ -0,0 +1,4 @@
|
||||
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK: Attribute 'range(i32 1, 145)' applied to incompatible type!
|
||||
declare void @llvm.test.immarg.range.intrinsic.f32(float immarg range(i32 1, 145))
|
||||
9
llvm/test/Assembler/invalid-immarg5.ll
Normal file
9
llvm/test/Assembler/invalid-immarg5.ll
Normal file
@@ -0,0 +1,9 @@
|
||||
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
declare void @llvm.test.immarg.range.intrinsic.i32(i32 immarg range(i32 -3, 4))
|
||||
|
||||
define void @test_int_immarg_with_range() {
|
||||
; CHECK: immarg value -4 out of range [-3, 4)
|
||||
call void @llvm.test.immarg.range.intrinsic.i32(i32 -4)
|
||||
ret void
|
||||
}
|
||||
Reference in New Issue
Block a user