Skip to content

Commit 9bea628

Browse files
author
Bryce Wilson
committed
[clang] Allow builtin addc/subc to be constant evaluated
1 parent 79fec2f commit 9bea628

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5241,6 +5241,11 @@ Intrinsics Support within Constant Expressions
52415241
52425242
The following builtin intrinsics can be used in constant expressions:
52435243
5244+
* ``__builtin_addcb``
5245+
* ``__builtin_addcs``
5246+
* ``__builtin_addc``
5247+
* ``__builtin_addcl``
5248+
* ``__builtin_addcll``
52445249
* ``__builtin_bitreverse8``
52455250
* ``__builtin_bitreverse16``
52465251
* ``__builtin_bitreverse32``
@@ -5287,6 +5292,11 @@ The following builtin intrinsics can be used in constant expressions:
52875292
* ``__builtin_rotateright16``
52885293
* ``__builtin_rotateright32``
52895294
* ``__builtin_rotateright64``
5295+
* ``__builtin_subcb``
5296+
* ``__builtin_subcs``
5297+
* ``__builtin_subc``
5298+
* ``__builtin_subcl``
5299+
* ``__builtin_subcll``
52905300
52915301
The following x86-specific intrinsics can be used in constant expressions:
52925302

clang/include/clang/Basic/Builtins.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4061,14 +4061,14 @@ class MPATemplate : Template<
40614061

40624062
def Addc : Builtin, MPATemplate {
40634063
let Spellings = ["__builtin_addc"];
4064-
let Attributes = [NoThrow];
4064+
let Attributes = [NoThrow, Constexpr];
40654065
// FIXME: Why are these argumentes marked const?
40664066
let Prototype = "T(T const, T const, T const, T*)";
40674067
}
40684068

40694069
def Subc : Builtin, MPATemplate {
40704070
let Spellings = ["__builtin_subc"];
4071-
let Attributes = [NoThrow];
4071+
let Attributes = [NoThrow, Constexpr];
40724072
// FIXME: Why are these argumentes marked const?
40734073
let Prototype = "T(T const, T const, T const, T*)";
40744074
}

clang/lib/AST/ExprConstant.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12691,6 +12691,56 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1269112691
return BuiltinOp == Builtin::BI__atomic_always_lock_free ?
1269212692
Success(0, E) : Error(E);
1269312693
}
12694+
case Builtin::BI__builtin_addcb:
12695+
case Builtin::BI__builtin_addcs:
12696+
case Builtin::BI__builtin_addc:
12697+
case Builtin::BI__builtin_addcl:
12698+
case Builtin::BI__builtin_addcll:
12699+
case Builtin::BI__builtin_subcb:
12700+
case Builtin::BI__builtin_subcs:
12701+
case Builtin::BI__builtin_subc:
12702+
case Builtin::BI__builtin_subcl:
12703+
case Builtin::BI__builtin_subcll: {
12704+
LValue CarryOutLValue;
12705+
APSInt LHS, RHS, CarryIn, Result;
12706+
QualType ResultType = E->getArg(0)->getType();
12707+
if (!EvaluateInteger(E->getArg(0), LHS, Info) ||
12708+
!EvaluateInteger(E->getArg(1), RHS, Info) ||
12709+
!EvaluateInteger(E->getArg(2), CarryIn, Info) ||
12710+
!EvaluatePointer(E->getArg(3), CarryOutLValue, Info))
12711+
return false;
12712+
12713+
bool FirstOverflowed = false;
12714+
bool SecondOverflowed = false;
12715+
switch (BuiltinOp) {
12716+
default:
12717+
llvm_unreachable("Invalid value for BuiltinOp");
12718+
case Builtin::BI__builtin_addcb:
12719+
case Builtin::BI__builtin_addcs:
12720+
case Builtin::BI__builtin_addc:
12721+
case Builtin::BI__builtin_addcl:
12722+
case Builtin::BI__builtin_addcll:
12723+
Result =
12724+
LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed);
12725+
break;
12726+
case Builtin::BI__builtin_subcb:
12727+
case Builtin::BI__builtin_subcs:
12728+
case Builtin::BI__builtin_subc:
12729+
case Builtin::BI__builtin_subcl:
12730+
case Builtin::BI__builtin_subcll:
12731+
Result =
12732+
LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed);
12733+
break;
12734+
}
12735+
12736+
// It is possible for both overflows to happen but CGBuiltin uses an OR so
12737+
// this is consistent
12738+
APSInt API{(uint32_t)(FirstOverflowed | SecondOverflowed)};
12739+
APValue APV{API};
12740+
if (!handleAssignment(Info, E, CarryOutLValue, ResultType, APV))
12741+
return false;
12742+
return Success(Result, E);
12743+
}
1269412744
case Builtin::BI__builtin_add_overflow:
1269512745
case Builtin::BI__builtin_sub_overflow:
1269612746
case Builtin::BI__builtin_mul_overflow:

0 commit comments

Comments
 (0)