jtmott-intel updated this revision to Diff 269727.
jtmott-intel added a comment.
Limited diagnostic to *signed* _ExtInt, and added test to verify unsigned works.
Reused existing diagnostic message rather than make a new one.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D81420/new/
https://reviews.llvm.org/D81420
Files:
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/Sema/SemaChecking.cpp
clang/test/CodeGen/builtins-overflow.c
clang/test/Sema/builtins-overflow.c
Index: clang/test/Sema/builtins-overflow.c
===================================================================
--- clang/test/Sema/builtins-overflow.c
+++ clang/test/Sema/builtins-overflow.c
@@ -19,4 +19,23 @@
__builtin_add_overflow(1, 1, 3); // expected-error {{result argument to overflow builtin must be a pointer to a non-const integer ('int' invalid)}}
__builtin_add_overflow(1, 1, &f); // expected-error {{result argument to overflow builtin must be a pointer to a non-const integer ('float *' invalid)}}
__builtin_add_overflow(1, 1, &q); // expected-error {{result argument to overflow builtin must be a pointer to a non-const integer ('const unsigned int *' invalid)}}
+
+ {
+ _ExtInt(128) x = 1;
+ _ExtInt(128) y = 1;
+ _ExtInt(128) result;
+ _Bool status = __builtin_mul_overflow(x, y, &result); // expect ok
+ }
+ {
+ unsigned _ExtInt(129) x = 1;
+ unsigned _ExtInt(129) y = 1;
+ unsigned _ExtInt(129) result;
+ _Bool status = __builtin_mul_overflow(x, y, &result); // expect ok
+ }
+ {
+ _ExtInt(129) x = 1;
+ _ExtInt(129) y = 1;
+ _ExtInt(129) result;
+ _Bool status = __builtin_mul_overflow(x, y, &result); // expected-error {{signed _ExtInt of bit sizes greater than 128 not supported}}
+ }
}
Index: clang/test/CodeGen/builtins-overflow.c
===================================================================
--- clang/test/CodeGen/builtins-overflow.c
+++ clang/test/CodeGen/builtins-overflow.c
@@ -41,6 +41,20 @@
return r;
}
+int test_add_overflow_xint31_xint31_xint31(_ExtInt(31) x, _ExtInt(31) y) {
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_xint31_xint31_xint31({{.+}})
+ // CHECK-NOT: ext
+ // CHECK: [[S:%.+]] = call { i31, i1 } @llvm.sadd.with.overflow.i31(i31 %{{.+}}, i31 %{{.+}})
+ // CHECK-DAG: [[C:%.+]] = extractvalue { i31, i1 } [[S]], 1
+ // CHECK-DAG: [[Q:%.+]] = extractvalue { i31, i1 } [[S]], 0
+ // CHECK: store i31 [[Q]], i31*
+ // CHECK: br i1 [[C]]
+ _ExtInt(31) r;
+ if (__builtin_add_overflow(x, y, &r))
+ overflowed();
+ return r;
+}
+
unsigned test_sub_overflow_uint_uint_uint(unsigned x, unsigned y) {
// CHECK-LABEL: define {{(dso_local )?}}i32 @test_sub_overflow_uint_uint_uint
// CHECK-NOT: ext
@@ -69,6 +83,20 @@
return r;
}
+int test_sub_overflow_xint31_xint31_xint31(_ExtInt(31) x, _ExtInt(31) y) {
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_sub_overflow_xint31_xint31_xint31({{.+}})
+ // CHECK-NOT: ext
+ // CHECK: [[S:%.+]] = call { i31, i1 } @llvm.ssub.with.overflow.i31(i31 %{{.+}}, i31 %{{.+}})
+ // CHECK-DAG: [[C:%.+]] = extractvalue { i31, i1 } [[S]], 1
+ // CHECK-DAG: [[Q:%.+]] = extractvalue { i31, i1 } [[S]], 0
+ // CHECK: store i31 [[Q]], i31*
+ // CHECK: br i1 [[C]]
+ _ExtInt(31) r;
+ if (__builtin_sub_overflow(x, y, &r))
+ overflowed();
+ return r;
+}
+
unsigned test_mul_overflow_uint_uint_uint(unsigned x, unsigned y) {
// CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_uint_uint_uint
// CHECK-NOT: ext
@@ -97,6 +125,48 @@
return r;
}
+int test_mul_overflow_xint31_xint31_xint31(_ExtInt(31) x, _ExtInt(31) y) {
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_xint31_xint31_xint31({{.+}})
+ // CHECK-NOT: ext
+ // CHECK: [[S:%.+]] = call { i31, i1 } @llvm.smul.with.overflow.i31(i31 %{{.+}}, i31 %{{.+}})
+ // CHECK-DAG: [[C:%.+]] = extractvalue { i31, i1 } [[S]], 1
+ // CHECK-DAG: [[Q:%.+]] = extractvalue { i31, i1 } [[S]], 0
+ // CHECK: store i31 [[Q]], i31*
+ // CHECK: br i1 [[C]]
+ _ExtInt(31) r;
+ if (__builtin_mul_overflow(x, y, &r))
+ overflowed();
+ return r;
+}
+
+int test_mul_overflow_xint127_xint127_xint127(_ExtInt(127) x, _ExtInt(127) y) {
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_xint127_xint127_xint127({{.+}})
+ // CHECK-NOT: ext
+ // CHECK: [[S:%.+]] = call { i127, i1 } @llvm.smul.with.overflow.i127(i127 %{{.+}}, i127 %{{.+}})
+ // CHECK-DAG: [[C:%.+]] = extractvalue { i127, i1 } [[S]], 1
+ // CHECK-DAG: [[Q:%.+]] = extractvalue { i127, i1 } [[S]], 0
+ // CHECK: store i127 [[Q]], i127*
+ // CHECK: br i1 [[C]]
+ _ExtInt(127) r;
+ if (__builtin_mul_overflow(x, y, &r))
+ overflowed();
+ return r;
+}
+
+int test_mul_overflow_xint128_xint128_xint128(_ExtInt(128) x, _ExtInt(128) y) {
+ // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_xint128_xint128_xint128({{.+}})
+ // CHECK-NOT: ext
+ // CHECK: [[S:%.+]] = call { i128, i1 } @llvm.smul.with.overflow.i128(i128 %{{.+}}, i128 %{{.+}})
+ // CHECK-DAG: [[C:%.+]] = extractvalue { i128, i1 } [[S]], 1
+ // CHECK-DAG: [[Q:%.+]] = extractvalue { i128, i1 } [[S]], 0
+ // CHECK: store i128 [[Q]], i128*
+ // CHECK: br i1 [[C]]
+ _ExtInt(128) r;
+ if (__builtin_mul_overflow(x, y, &r))
+ overflowed();
+ return r;
+}
+
int test_add_overflow_uint_int_int(unsigned x, int y) {
// CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_uint_int_int
// CHECK: [[XE:%.+]] = zext i32 %{{.+}} to i33
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -283,7 +283,8 @@
return false;
}
-static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
+static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall,
+ unsigned BuiltinID) {
if (checkArgCount(S, TheCall, 3))
return true;
@@ -325,6 +326,25 @@
return true;
TheCall->setArg(2, Arg.get());
}
+
+ // Disallow ExtIntType args larger than 128 bits to mul function until we
+ // improve backend support.
+ if (BuiltinID == Builtin::BI__builtin_mul_overflow) {
+ for (unsigned I = 0; I < 3; ++I) {
+ ExprResult Arg = TheCall->getArg(I);
+ // Third argument will be a pointer
+ QualType Ty =
+ I < 2 ? Arg.get()->getType()
+ : Arg.get()->getType()->getAs<PointerType>()->getPointeeType();
+ if (Ty->isExtIntType() && Ty->isSignedIntegerType() &&
+ S.getASTContext().getIntWidth(Ty) > 128) {
+ S.Diag(Arg.get()->getBeginLoc(), diag::err_ext_int_max_size)
+ << /*signed*/ 0 << 128;
+ return true;
+ }
+ }
+ }
+
return false;
}
@@ -1728,7 +1748,7 @@
case Builtin::BI__builtin_add_overflow:
case Builtin::BI__builtin_sub_overflow:
case Builtin::BI__builtin_mul_overflow:
- if (SemaBuiltinOverflow(*this, TheCall))
+ if (SemaBuiltinOverflow(*this, TheCall, BuiltinID))
return ExprError();
break;
case Builtin::BI__builtin_operator_new:
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -586,7 +586,9 @@
getIntegerWidthAndSignedness(const clang::ASTContext &context,
const clang::QualType Type) {
assert(Type->isIntegerType() && "Given type is not an integer.");
- unsigned Width = Type->isBooleanType() ? 1 : context.getTypeInfo(Type).Width;
+ unsigned Width = Type->isBooleanType() ? 1
+ : Type->isExtIntType() ? context.getIntWidth(Type)
+ : context.getTypeInfo(Type).Width;
bool Signed = Type->isSignedIntegerType();
return {Width, Signed};
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits