Skip to content

Commit b6c9c76

Browse files
authored
[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 <[email protected]>
1 parent bae8e1f commit b6c9c76

File tree

5 files changed

+63
-13
lines changed

5 files changed

+63
-13
lines changed

llvm/lib/IR/Verifier.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,8 +1987,12 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
19871987
V);
19881988

19891989
if (Attrs.hasAttribute(Attribute::ImmArg)) {
1990-
Check(Attrs.getNumAttributes() == 1,
1991-
"Attribute 'immarg' is incompatible with other attributes", V);
1990+
unsigned AttrCount =
1991+
Attrs.getNumAttributes() - Attrs.hasAttribute(Attribute::Range);
1992+
Check(AttrCount == 1,
1993+
"Attribute 'immarg' is incompatible with other attributes except the "
1994+
"'range' attribute",
1995+
V);
19921996
}
19931997

19941998
// Check for mutually incompatible attributes. Only inreg is compatible with
@@ -3680,6 +3684,20 @@ void Verifier::visitCallBase(CallBase &Call) {
36803684
Value *ArgVal = Call.getArgOperand(i);
36813685
Check(isa<ConstantInt>(ArgVal) || isa<ConstantFP>(ArgVal),
36823686
"immarg operand has non-immediate parameter", ArgVal, Call);
3687+
3688+
// If the imm-arg is an integer and also has a range attached,
3689+
// check if the given value is within the range.
3690+
if (Call.paramHasAttr(i, Attribute::Range)) {
3691+
if (auto *CI = dyn_cast<ConstantInt>(ArgVal)) {
3692+
const ConstantRange &CR =
3693+
Call.getParamAttr(i, Attribute::Range).getValueAsConstantRange();
3694+
Check(CR.contains(CI->getValue()),
3695+
"immarg value " + Twine(CI->getValue().getSExtValue()) +
3696+
" out of range [" + Twine(CR.getLower().getSExtValue()) +
3697+
", " + Twine(CR.getUpper().getSExtValue()) + ")",
3698+
Call);
3699+
}
3700+
}
36833701
}
36843702

36853703
if (Call.paramHasAttr(i, Attribute::Preallocated)) {

llvm/test/Assembler/immarg-param-attribute.ll

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ declare void @llvm.test.immarg.intrinsic.i32(i32 immarg)
66
; CHECK: declare void @llvm.test.immarg.intrinsic.f32(float immarg)
77
declare void @llvm.test.immarg.intrinsic.f32(float immarg)
88

9+
; CHECK: declare void @llvm.test.immarg.range.intrinsic.i32(i32 immarg range(i32 -2, 14))
10+
declare void @llvm.test.immarg.range.intrinsic.i32(i32 immarg range(i32 -2, 14))
11+
912
; CHECK-LABEL: @call_llvm.test.immarg.intrinsic.i32(
1013
define void @call_llvm.test.immarg.intrinsic.i32() {
1114
; CHECK: call void @llvm.test.immarg.intrinsic.i32(i32 0)
@@ -37,3 +40,19 @@ define void @on_callsite_and_declaration() {
3740
call void @llvm.test.immarg.intrinsic.i32(i32 immarg 0)
3841
ret void
3942
}
43+
44+
; CHECK-LABEL: @test_int_immarg_with_range(
45+
define void @test_int_immarg_with_range() {
46+
; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 -2)
47+
call void @llvm.test.immarg.range.intrinsic.i32(i32 -2)
48+
49+
; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 0)
50+
call void @llvm.test.immarg.range.intrinsic.i32(i32 0)
51+
52+
; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 5)
53+
call void @llvm.test.immarg.range.intrinsic.i32(i32 5)
54+
55+
; CHECK: call void @llvm.test.immarg.range.intrinsic.i32(i32 13)
56+
call void @llvm.test.immarg.range.intrinsic.i32(i32 13)
57+
ret void
58+
}

llvm/test/Assembler/invalid-immarg.ll

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
22

3-
; CHECK: Attribute 'immarg' is incompatible with other attributes
3+
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
44
declare void @llvm.immarg.byval(ptr byval(i32) immarg)
55

6-
; CHECK: Attribute 'immarg' is incompatible with other attributes
6+
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
77
declare void @llvm.immarg.inalloca(ptr inalloca(i32) immarg)
88

9-
; CHECK: Attribute 'immarg' is incompatible with other attributes
9+
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
1010
declare void @llvm.immarg.inreg(i32 inreg immarg)
1111

12-
; CHECK: Attribute 'immarg' is incompatible with other attributes
12+
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
1313
declare void @llvm.immarg.nest(ptr nest immarg)
1414

15-
; CHECK: Attribute 'immarg' is incompatible with other attributes
15+
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
1616
declare void @llvm.immarg.sret(ptr sret(i32) immarg)
1717

18-
; CHECK: Attribute 'immarg' is incompatible with other attributes
18+
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
1919
declare void @llvm.immarg.zeroext(i32 zeroext immarg)
2020

21-
; CHECK: Attribute 'immarg' is incompatible with other attributes
21+
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
2222
declare void @llvm.immarg.signext(i32 signext immarg)
2323

24-
; CHECK: Attribute 'immarg' is incompatible with other attributes
24+
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
2525
declare void @llvm.immarg.returned(i32 returned immarg)
2626

27-
; CHECK: Attribute 'immarg' is incompatible with other attributes
27+
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
2828
declare void @llvm.immarg.noalias(ptr noalias immarg)
2929

30-
; CHECK: Attribute 'immarg' is incompatible with other attributes
30+
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
3131
declare void @llvm.immarg.readnone(ptr readnone immarg)
3232

33-
; CHECK: Attribute 'immarg' is incompatible with other attributes
33+
; CHECK: Attribute 'immarg' is incompatible with other attributes except the 'range' attribute
3434
declare void @llvm.immarg.readonly(ptr readonly immarg)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
2+
3+
; CHECK: Attribute 'range(i32 1, 145)' applied to incompatible type!
4+
declare void @llvm.test.immarg.range.intrinsic.f32(float immarg range(i32 1, 145))
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
2+
3+
declare void @llvm.test.immarg.range.intrinsic.i32(i32 immarg range(i32 -3, 4))
4+
5+
define void @test_int_immarg_with_range() {
6+
; CHECK: immarg value -4 out of range [-3, 4)
7+
call void @llvm.test.immarg.range.intrinsic.i32(i32 -4)
8+
ret void
9+
}

0 commit comments

Comments
 (0)