Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3acc848
Adding C23 constexpr math functions fmin and frexp.
zahiraam Apr 16, 2024
d7050b5
Addressed review comments.
zahiraam Apr 22, 2024
625028a
Responded to review comments.
zahiraam May 1, 2024
319fdd0
Added code to store the exponent in Pointer. Edited LIT tests
zahiraam May 8, 2024
da06dba
Added fmax function and function IsinRange function.
zahiraam May 9, 2024
1793cf0
Addressed review comments.
zahiraam May 10, 2024
42d7d4c
Added a fix for failing LIT test.
zahiraam May 15, 2024
9f4d632
Fixed aix-builtin-mapping.c test.
zahiraam May 17, 2024
efeec9b
Merge remote-tracking branch 'origin/main' into C23ConstExpr
zahiraam May 17, 2024
e384a05
Addressed review comments.
zahiraam Jun 11, 2024
5f67645
Put back CodeGen/aix-builtin-mapping.c how it was originally written.
zahiraam Jun 11, 2024
49186b9
Fix build issue in flang.
zahiraam Jul 26, 2024
cf2814d
Merge remote-tracking branch 'origin/main' into C23ConstExpr
zahiraam Jul 26, 2024
1c2912c
Merge remote-tracking branch 'origin/main' into C23ConstExpr
zahiraam Jul 26, 2024
d32737e
Rewrote isInFrexpResultRange according to review comments and fixed
zahiraam Jul 26, 2024
bd536f5
Fix format.
zahiraam Jul 26, 2024
32b788a
Addressed missed review comments.
zahiraam Jul 29, 2024
501e39a
Addressed review comments. Remove StoreExponent function and fixed LIT
zahiraam Aug 5, 2024
0cc61eb
Replaced ConstexpSince by Constexpr for FrexpF16F128.
zahiraam Aug 13, 2024
c615b22
Removed builtin attribute ConstExprSince and replaced it with a member
zahiraam Aug 22, 2024
5eec2db
Fix format.
zahiraam Aug 22, 2024
299df9a
Fix LIT failures.
zahiraam Aug 23, 2024
1507a33
Merge remote-tracking branch 'origin/main' into C23ConstExpr
zahiraam Aug 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2036,6 +2036,10 @@ class FunctionDecl : public DeclaratorDecl,
/// the DeclaratorDecl base class.
DeclarationNameLoc DNLoc;

/// Represents the language version since this function has been declared
/// constexpr.
clang::LangStandard::Kind ConstexprSinceVersion;

/// Specify that this function declaration is actually a function
/// template specialization.
///
Expand Down Expand Up @@ -2151,6 +2155,20 @@ class FunctionDecl : public DeclaratorDecl,

void setDeclarationNameLoc(DeclarationNameLoc L) { DNLoc = L; }

/// Set the language standard version at which this builtin became constexpr.
void setConstexprBuiltinSinceVersion(IdentifierInfo *builtinIdentifier);

/// Get the language standard version at which this builtin became constexpr.
clang::LangStandard::Kind getConstexprBuiltinSinceVersion() const {
return ConstexprSinceVersion;
}

/// Set the version of the language standard at which this declaration became
/// constexpr.
void setConstexprSinceVersion(clang::LangStandard::Kind LangVersion) {
ConstexprSinceVersion = LangVersion;
}

/// Returns the location of the ellipsis of a variadic function.
SourceLocation getEllipsisLoc() const {
const auto *FPT = getType()->getAs<FunctionProtoType>();
Expand Down
11 changes: 10 additions & 1 deletion clang/include/clang/Basic/Builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_BASIC_BUILTINS_H
#define LLVM_CLANG_BASIC_BUILTINS_H

#include "LangStandard.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
Expand Down Expand Up @@ -74,6 +75,7 @@ struct Info {
const char *Features;
HeaderDesc Header;
LanguageID Langs;
LangStandard UnprefixedOnlyConstexprSince;
};

/// Holds information about both target-independent and
Expand Down Expand Up @@ -161,6 +163,12 @@ class Context {
return strchr(getRecord(ID).Attributes, 'f') != nullptr;
}

clang::LangStandard::Kind isBuiltinConstant(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'O') != nullptr
? LangStandard::lang_cxx23
: LangStandard::lang_cxx20; // Not constexpr
}

/// Returns true if this builtin requires appropriate header in other
/// compilers. In Clang it will work even without including it, but we can emit
/// a warning about missing header.
Expand Down Expand Up @@ -277,7 +285,8 @@ class Context {

/// Return true if this function can be constant evaluated by Clang frontend.
bool isConstantEvaluated(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'E') != nullptr;
return (strchr(getRecord(ID).Attributes, 'E') != nullptr ||
strchr(getRecord(ID).Attributes, 'O') != nullptr);
}

/// Returns true if this is an immediate (consteval) function
Expand Down
20 changes: 11 additions & 9 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,9 @@ def FmodF16F128 : F16F128MathTemplate, Builtin {

def FrexpF16F128 : F16F128MathTemplate, Builtin {
let Spellings = ["__builtin_frexp"];
let Attributes = [FunctionWithBuiltinPrefix, NoThrow];
let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Constexpr];
let Prototype = "T(T, int*)";
let BuiltinPrefixedAliasIsConstexpr = 1;
}

def HugeVal : Builtin, FPMathWithF128Template {
Expand Down Expand Up @@ -3463,15 +3464,15 @@ def Copysign : FPMathTemplate, LibBuiltin<"math.h"> {
let Attributes = [NoThrow, Const];
let Prototype = "T(T, T)";
let AddBuiltinPrefixedAlias = 1;
let OnlyBuiltinPrefixedAliasIsConstexpr = 1;
let BuiltinPrefixedAliasIsConstexpr = 1;
}

def Fabs : FPMathTemplate, LibBuiltin<"math.h"> {
let Spellings = ["fabs"];
let Attributes = [NoThrow, Const];
let Prototype = "T(T)";
let AddBuiltinPrefixedAlias = 1;
let OnlyBuiltinPrefixedAliasIsConstexpr = 1;
let BuiltinPrefixedAliasIsConstexpr = 1;
}

def Finite : FPMathTemplate, GNULibBuiltin<"math.h"> {
Expand All @@ -3496,9 +3497,10 @@ def Fmod : FPMathTemplate, LibBuiltin<"math.h"> {

def Frexp : FPMathTemplate, LibBuiltin<"math.h"> {
let Spellings = ["frexp"];
let Attributes = [NoThrow];
let Attributes = [NoThrow, Constexpr];
let Prototype = "T(T, int*)";
let AddBuiltinPrefixedAlias = 1;
let BuiltinPrefixedAliasIsConstexpr = 1;
}

def Ldexp : FPMathTemplate, LibBuiltin<"math.h"> {
Expand All @@ -3520,7 +3522,7 @@ def Nan : FPMathTemplate, LibBuiltin<"math.h"> {
let Attributes = [Pure, NoThrow];
let Prototype = "T(char const*)";
let AddBuiltinPrefixedAlias = 1;
let OnlyBuiltinPrefixedAliasIsConstexpr = 1;
let BuiltinPrefixedAliasIsConstexpr = 1;
}

def Pow : FPMathTemplate, LibBuiltin<"math.h"> {
Expand Down Expand Up @@ -3666,18 +3668,18 @@ def Fma : FPMathTemplate, LibBuiltin<"math.h"> {

def Fmax : FPMathTemplate, LibBuiltin<"math.h"> {
let Spellings = ["fmax"];
let Attributes = [NoThrow, Const];
let Attributes = [NoThrow, Const, Constexpr];
let Prototype = "T(T, T)";
let AddBuiltinPrefixedAlias = 1;
let OnlyBuiltinPrefixedAliasIsConstexpr = 1;
let BuiltinPrefixedAliasIsConstexpr = 1;
}

def Fmin : FPMathTemplate, LibBuiltin<"math.h"> {
let Spellings = ["fmin"];
let Attributes = [NoThrow, Const];
let Attributes = [NoThrow, Const, Constexpr];
let Prototype = "T(T, T)";
let AddBuiltinPrefixedAlias = 1;
let OnlyBuiltinPrefixedAliasIsConstexpr = 1;
let BuiltinPrefixedAliasIsConstexpr = 1;
}

def Hypot : FPMathTemplate, LibBuiltin<"math.h"> {
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/BuiltinsBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class Builtin {
// On some platforms, some functions are actually macros. In that case we need
// to #undef them.
bit RequiresUndef = 0;
bit BuiltinPrefixedAliasIsConstexpr = 0;
}

class CustomEntry {
Expand All @@ -99,7 +100,7 @@ class LibBuiltin<string header, string languages = "ALL_LANGUAGES"> : Builtin {
string Header = header;
string Languages = languages;
bit AddBuiltinPrefixedAlias = 0;
bit OnlyBuiltinPrefixedAliasIsConstexpr = 0;
bit BuiltinPrefixedAliasIsConstexpr = 0;
}

class MSLibBuiltin<string header> : LibBuiltin<header, "ALL_MS_LANGUAGES">;
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_set>

using namespace clang;

Expand Down Expand Up @@ -3066,6 +3067,25 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
setTrailingRequiresClause(TrailingRequiresClause);
}

void FunctionDecl::setConstexprBuiltinSinceVersion(IdentifierInfo *I) {
const std::unordered_set<std::string> ConstexprFunctions = {
"__builtin_fmax", "__builtin_fmaxf", "__builtin_fmaxl",
"__builtin_fmin", "__builtin_fminf", "__builtin_fminl"};
const std::unordered_set<std::string> ConstexprFunctionsFrexp = {
"__builtin_frexp", "__builtin_frexpf", "__builtin_frexpl",
"__builtin_frexpf16", "__builtin_frexpf128"};
std::string BuiltinName = I->getName().str();
if (ConstexprFunctions.count(BuiltinName)) {
setConstexprSinceVersion(getLangOpts().CPlusPlus23
? LangStandard::lang_cxx23
: getLangOpts().LangStd);
} else if (ConstexprFunctionsFrexp.count(BuiltinName)) {
setConstexprSinceVersion(LangStandard::lang_cxx23);
} else {
setConstexprSinceVersion(getLangOpts().LangStd);
}
}

void FunctionDecl::getNameForDiagnostic(
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
Expand Down
56 changes: 56 additions & 0 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14942,6 +14942,16 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context,

return true;
}
// Checks that the value x is in the range (-1;-0.5], [0.5; 1)
static bool isInFrexpResultRange(const llvm::APFloat &x) {
llvm::APFloat AbsX = abs(x);

llvm::APFloat half(x.getSemantics(), "0.5");
llvm::APFloat one(x.getSemantics(), "1.0");

return (AbsX.compare(half) != llvm::APFloat::cmpLessThan &&
AbsX.compare(one) == llvm::APFloat::cmpLessThan);
}

bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (!IsConstantEvaluatedBuiltinCall(E))
Expand All @@ -14951,6 +14961,36 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
default:
return false;

case Builtin::BIfrexp:
case Builtin::BIfrexpf:
case Builtin::BIfrexpl:
case Builtin::BI__builtin_frexp:
case Builtin::BI__builtin_frexpf:
case Builtin::BI__builtin_frexpl:
case Builtin::BI__builtin_frexpf16:
case Builtin::BI__builtin_frexpf128: {
const auto *FDecl = E->getDirectCallee();
clang::LangStandard::Kind ConstExprSinceVersion =
FDecl->getConstexprBuiltinSinceVersion();
if (ConstExprSinceVersion > Info.Ctx.getLangOpts().LangStd)
return false;
LValue Pointer;
if (!EvaluateFloat(E->getArg(0), Result, Info) ||
!EvaluatePointer(E->getArg(1), Pointer, Info))
return false;
int FrexpExp;
llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
Result = llvm::frexp(Result, FrexpExp, RM);
assert((Result.isZero() || Result.isNaN() || Result.isInfinity() ||
isInFrexpResultRange(Result)) &&
"The value is not in the expected range for frexp.");
APValue ExpVal{Result};
if (!handleAssignment(Info, E, Pointer,
E->getArg(1)->getType()->getPointeeType(), ExpVal))
return false;
return true;
}

case Builtin::BI__builtin_huge_val:
case Builtin::BI__builtin_huge_valf:
case Builtin::BI__builtin_huge_vall:
Expand Down Expand Up @@ -15024,12 +15064,20 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
return true;
}

case Builtin::BIfmax:
case Builtin::BIfmaxf:
case Builtin::BIfmaxl:
case Builtin::BI__builtin_fmax:
case Builtin::BI__builtin_fmaxf:
case Builtin::BI__builtin_fmaxl:
case Builtin::BI__builtin_fmaxf16:
case Builtin::BI__builtin_fmaxf128: {
// TODO: Handle sNaN.
const auto *FDecl = E->getDirectCallee();
clang::LangStandard::Kind ConstExprSinceVersion =
FDecl->getConstexprBuiltinSinceVersion();
if (ConstExprSinceVersion > Info.Ctx.getLangOpts().LangStd)
return false;
APFloat RHS(0.);
if (!EvaluateFloat(E->getArg(0), Result, Info) ||
!EvaluateFloat(E->getArg(1), RHS, Info))
Expand All @@ -15042,12 +15090,20 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
return true;
}

case Builtin::BIfmin:
case Builtin::BIfminf:
case Builtin::BIfminl:
case Builtin::BI__builtin_fmin:
case Builtin::BI__builtin_fminf:
case Builtin::BI__builtin_fminl:
case Builtin::BI__builtin_fminf16:
case Builtin::BI__builtin_fminf128: {
// TODO: Handle sNaN.
const auto *FDecl = E->getDirectCallee();
clang::LangStandard::Kind ConstExprSinceVersion =
FDecl->getConstexprBuiltinSinceVersion();
if (ConstExprSinceVersion > Info.Ctx.getLangOpts().LangStd)
return false;
APFloat RHS(0.);
if (!EvaluateFloat(E->getArg(0), Result, Info) ||
!EvaluateFloat(E->getArg(1), RHS, Info))
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2308,6 +2308,7 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type,
Type->isFunctionProtoType(), ConstexprKind);
New->setImplicit();
New->addAttr(BuiltinAttr::CreateImplicit(Context, ID));
New->setConstexprBuiltinSinceVersion(II);

// Create Decl objects for each parameter, adding them to the
// FunctionDecl.
Expand Down
Loading