Skip to content

[DFP] Implement parsing of Decimal32 literals and printing of Decimal32 values #49

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: dfp
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1098,11 +1098,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
CanQualType SatShortFractTy, SatFractTy, SatLongFractTy;
CanQualType SatUnsignedShortFractTy, SatUnsignedFractTy,
SatUnsignedLongFractTy;
// ISO/IEC TS 18661-2, ISO/IEC TR 24733, and C23 decimal floating-point.
CanQualType DecimalFloat32Ty, DecimalFloat64Ty, DecimalFloat128Ty;
CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
CanQualType BFloat16Ty;
CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3
// ISO/IEC TS 18661-2:2015, C23 conditionally supported
CanQualType DecimalFloat32Ty, DecimalFloat64Ty, DecimalFloat128Ty;
CanQualType VoidPtrTy, NullPtrTy;
CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
CanQualType BuiltinFnTy;
Expand Down
8 changes: 7 additions & 1 deletion clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1661,9 +1661,10 @@ class CharacterLiteral : public Expr {

class FloatingLiteral : public Expr, private APFloatStorage {
SourceLocation Loc;
bool DFP : 1;

FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact,
QualType Type, SourceLocation L);
QualType Type, SourceLocation L, bool isDFP=false);

/// Construct an empty floating-point literal.
explicit FloatingLiteral(const ASTContext &C, EmptyShell Empty);
Expand All @@ -1673,6 +1674,7 @@ class FloatingLiteral : public Expr, private APFloatStorage {
bool isexact, QualType Type, SourceLocation L);
static FloatingLiteral *Create(const ASTContext &C, EmptyShell Empty);

bool isDFP() const { return DFP; }
llvm::APFloat getValue() const {
return APFloatStorage::getValue(getSemantics());
}
Expand Down Expand Up @@ -1714,6 +1716,10 @@ class FloatingLiteral : public Expr, private APFloatStorage {
/// debugging dumps, etc.
double getValueAsApproximateDouble() const;

void getValueAsString(SmallVectorImpl<char> &Str) const {
getValue().toString(Str,0,0,false);
}

SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }

Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,9 @@ class alignas(void *) Stmt {
unsigned : NumExprBits;

static_assert(
llvm::APFloat::S_MaxSemantics < 16,
"Too many Semantics enum values to fit in bitfield of size 4");
unsigned Semantics : 4; // Provides semantics for APFloat construction
llvm::APFloat::S_MaxSemantics < 32,
"Too many Semantics enum values to fit in bitfield of size 5");
unsigned Semantics : 5; // Provides semantics for APFloat construction
unsigned IsExact : 1;
};

Expand Down
12 changes: 11 additions & 1 deletion clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ struct TransferrableTargetInfo {
unsigned MaxTLSAlign;

const llvm::fltSemantics *HalfFormat, *BFloat16Format, *FloatFormat,
*DoubleFormat, *LongDoubleFormat, *Float128Format, *Ibm128Format;
*DoubleFormat, *LongDoubleFormat, *Float128Format, *Ibm128Format,
*DecimalFloat32Format, *DecimalFloat64Format, *DecimalFloat128Format;

///===---- Target Data Type Query Methods -------------------------------===//
enum IntType {
Expand Down Expand Up @@ -535,14 +536,23 @@ class TargetInfo : public TransferrableTargetInfo,
/// DecimalFloat32Width/Align - Return the size/align of '_Decimal32'.
unsigned getDecimalFloat32Width() const { return DecimalFloat32Width; }
unsigned getDecimalFloat32Align() const { return DecimalFloat32Align; }
const llvm::fltSemantics &getDecimalFloat32Format() const {
return *DecimalFloat32Format;
}

/// DecimalFloat64Width/Align - Return the size/align of '_Decimal64'.
unsigned getDecimalFloat64Width() const { return DecimalFloat64Width; }
unsigned getDecimalFloat64Align() const { return DecimalFloat64Align; }
const llvm::fltSemantics &getDecimalFloat64Format() const {
return *DecimalFloat64Format;
}

/// DecimalFloat128Width/Align - Return the size/align of '_Decimal128'.
unsigned getDecimalFloat128Width() const { return DecimalFloat128Width; }
unsigned getDecimalFloat128Align() const { return DecimalFloat128Align; }
const llvm::fltSemantics &getDecimalFloat128Format() const {
return *DecimalFloat128Format;
}

/// getShortAccumWidth/Align - Return the size of 'signed short _Accum' and
/// 'unsigned short _Accum' for this target, in bits.
Expand Down
16 changes: 15 additions & 1 deletion clang/include/clang/Lex/LiteralSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class NumericLiteralParser {

unsigned radix;

bool saw_exponent, saw_period, saw_ud_suffix, saw_fixed_point_suffix;
bool saw_exponent, saw_period, saw_ud_suffix, saw_fixed_point_suffix, saw_decimal_float_suffix;

SmallString<32> UDSuffixBuf;

Expand All @@ -78,6 +78,11 @@ class NumericLiteralParser {
bool isImaginary : 1; // 1.0i
bool isFloat16 : 1; // 1.0f16
bool isFloat128 : 1; // 1.0q
bool isDecimalFloat : 1; // df/DF for _Decimal32, dd/DD for _Decimal64
// Dl/DL for _Decimal128
bool isDecimal32 : 1; // 6543.0DF
bool isDecimal64 : 1; // 9.99DD
bool isDecimal128 : 1; // 9.99DL
bool isFract : 1; // 1.0hr/r/lr/uhr/ur/ulr
bool isAccum : 1; // 1.0hk/k/lk/uhk/uk/ulk
bool isBitInt : 1; // 1wb, 1uwb (C23)
Expand All @@ -88,6 +93,10 @@ class NumericLiteralParser {
return (saw_period || saw_exponent) && saw_fixed_point_suffix;
}

bool isDecimalFloatLiteral() const {
return (saw_period || saw_exponent) && saw_decimal_float_suffix;
}

bool isIntegerLiteral() const {
return !saw_period && !saw_exponent && !isFixedPointLiteral();
}
Expand Down Expand Up @@ -124,6 +133,11 @@ class NumericLiteralParser {
/// literal exactly, and false otherwise.
llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result);

/// GetDecimalFloatValue - Convert this numeric literal to a decimal float value, using
/// the specified DFPFloat fltSemantics (specifying _Decimal32, _Decimal64, etc).
llvm::APFloat::opStatus GetDecimalFloatValue(llvm::APFloat &Result);


/// GetFixedPointValue - Convert this numeric literal value into a
/// scaled integer that represents this value. Returns true if an overflow
/// occurred when calculating the integral part of the scaled integer or
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1681,6 +1681,12 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
if (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice)
return AuxTarget->getFloat128Format();
return Target->getFloat128Format();
case BuiltinType::DecimalFloat32:
return Target->getDecimalFloat32Format();
case BuiltinType::DecimalFloat64:
return Target->getDecimalFloat64Format();
case BuiltinType::DecimalFloat128:
return Target->getDecimalFloat128Format();
}
}

Expand Down
6 changes: 3 additions & 3 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1083,8 +1083,8 @@ void CharacterLiteral::print(unsigned Val, CharacterKind Kind,
}

FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L)
: Expr(FloatingLiteralClass, Type, VK_PRValue, OK_Ordinary), Loc(L) {
bool isexact, QualType Type, SourceLocation L, bool isDFP)
: Expr(FloatingLiteralClass, Type, VK_PRValue, OK_Ordinary), Loc(L), DFP(isDFP) {
setSemantics(V.getSemantics());
FloatingLiteralBits.IsExact = isexact;
setValue(C, V);
Expand All @@ -1100,7 +1100,7 @@ FloatingLiteral::FloatingLiteral(const ASTContext &C, EmptyShell Empty)
FloatingLiteral *
FloatingLiteral::Create(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L) {
return new (C) FloatingLiteral(C, V, isexact, Type, L);
return new (C) FloatingLiteral(C, V, isexact, Type, L, V.isDFP());
}

FloatingLiteral *
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,13 @@ void TextNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) {

void TextNodeDumper::VisitFloatingLiteral(const FloatingLiteral *Node) {
ColorScope Color(OS, ShowColors, ValueColor);
OS << " " << Node->getValueAsApproximateDouble();
if (!Node->isDFP())
OS << " " << Node->getValueAsApproximateDouble();
else {
SmallVector<char, 16> Buffer;
Node->getValueAsString(Buffer);
OS << " " << Buffer;
}
}

void TextNodeDumper::VisitStringLiteral(const StringLiteral *Str) {
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Basic/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
Float128Format = &llvm::APFloat::IEEEquad();
Ibm128Format = &llvm::APFloat::PPCDoubleDouble();
DecimalFloat32Format = &llvm::APFloat::DecimalFloat32();
DecimalFloat64Format = &llvm::APFloat::DecimalFloat64();
DecimalFloat128Format = &llvm::APFloat::DecimalFloat128();
MCountName = "mcount";
UserLabelPrefix = "_";
RegParmMax = 0;
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CodeGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,13 +419,13 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
break;

case BuiltinType::DecimalFloat32:
ResultType = llvm::Type::getDecimal32Ty(getLLVMContext());
ResultType = llvm::Type::getDecimalFloat32Ty(getLLVMContext());
break;
case BuiltinType::DecimalFloat64:
ResultType = llvm::Type::getDecimal64Ty(getLLVMContext());
ResultType = llvm::Type::getDecimalFloat64Ty(getLLVMContext());
break;
case BuiltinType::DecimalFloat128:
ResultType = llvm::Type::getDecimal128Ty(getLLVMContext());
ResultType = llvm::Type::getDecimalFloat128Ty(getLLVMContext());
break;

case BuiltinType::NullPtr:
Expand Down
47 changes: 47 additions & 0 deletions clang/lib/Lex/LiteralSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
saw_period = false;
saw_ud_suffix = false;
saw_fixed_point_suffix = false;
saw_decimal_float_suffix = false;
isLong = false;
isUnsigned = false;
isLongLong = false;
Expand All @@ -920,6 +921,10 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
isImaginary = false;
isFloat16 = false;
isFloat128 = false;
isDecimalFloat = false;
isDecimal32 = false;
isDecimal64 = false;
isDecimal128 = false;
MicrosoftInteger = 0;
isFract = false;
isAccum = false;
Expand Down Expand Up @@ -975,6 +980,26 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
// we break out of the loop.
for (; s != ThisTokEnd; ++s) {
switch (*s) {
case 'd':
case 'D':
switch (s[1]) {
case 'f':
case 'F':
isDecimal32 = true;
saw_decimal_float_suffix = true;
break;
case 'd':
case 'D':
isDecimal64 = true;
saw_decimal_float_suffix = true;
break;
case 'l':
case 'L':
isDecimal128 = true;
saw_decimal_float_suffix = true;
break;
}
continue;
case 'R':
case 'r':
if (!LangOpts.FixedPoint)
Expand Down Expand Up @@ -1155,6 +1180,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
isBitInt = false;
MicrosoftInteger = 0;
saw_fixed_point_suffix = false;
saw_decimal_float_suffix = false;
isFract = false;
isAccum = false;
}
Expand Down Expand Up @@ -1503,6 +1529,27 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {
: APFloat::opInvalidOp;
}

llvm::APFloat::opStatus NumericLiteralParser::GetDecimalFloatValue(llvm::APFloat &Result) {
using llvm::APFloat;

unsigned n = std::min(SuffixBegin - ThisTokBegin, ThisTokEnd - ThisTokBegin);

llvm::SmallString<16> Buffer;
StringRef Str(ThisTokBegin, n);
if (Str.contains('\'')) {
Buffer.reserve(n);
std::remove_copy_if(Str.begin(), Str.end(), std::back_inserter(Buffer),
&isDigitSeparator);
Str = Buffer;
}

auto StatusOrErr =
Result.convertFromString(Str, APFloat::rmNearestTiesToEven);
assert(StatusOrErr && "Invalid floating point representation");
return !errorToBool(StatusOrErr.takeError()) ? *StatusOrErr
: APFloat::opInvalidOp;
}

static inline bool IsExponentPart(char c) {
return c == 'p' || c == 'P' || c == 'e' || c == 'E';
}
Expand Down
49 changes: 49 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3880,6 +3880,39 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal,
return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc);
}

static Expr *BuildDecimalFloatLiteral(Sema &S, NumericLiteralParser &Literal,
QualType Ty, SourceLocation Loc) {
const llvm::fltSemantics &Format = S.Context.getFloatTypeSemantics(Ty);

using llvm::APFloat;
APFloat Val(Format);

APFloat::opStatus result = Literal.GetDecimalFloatValue(Val);

// Overflow is always an error, but underflow is only an error if
// we underflowed to zero (APFloat reports denormals as underflow).
// if ((result & APFloat::opOverflow) ||
// ((result & APFloat::opUnderflow) && Val.isZero())) {
// unsigned diagnostic;
// SmallString<20> buffer;
// if (result & APFloat::opOverflow) {
// diagnostic = diag::warn_float_overflow;
// APFloat::getLargest(Format).toString(buffer);
// } else {
// diagnostic = diag::warn_float_underflow;
// APFloat::getSmallest(Format).toString(buffer);
// }

// S.Diag(Loc, diagnostic)
// << Ty
// << StringRef(buffer.data(), buffer.size());
// }

bool isExact = (result == APFloat::opOK);
return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc);
}


bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc) {
assert(E && "Invalid expression");

Expand Down Expand Up @@ -4076,6 +4109,22 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {

Res = FixedPointLiteral::CreateFromRawInt(Context, Val, Ty,
Tok.getLocation(), scale);
} else if (Literal.isDecimalFloatLiteral()) {
QualType Ty;

if (Literal.isDecimal32)
Ty = Context.DecimalFloat32Ty;
else if (Literal.isDecimal64)
Ty = Context.DecimalFloat64Ty;
else if (Literal.isDecimal128)
Ty = Context.DecimalFloat128Ty;
else
assert(false && "unexpected DFP literal");

unsigned bit_width = Context.getTypeInfo(Ty).Width;

Res = BuildDecimalFloatLiteral(*this, Literal, Ty, Tok.getLocation());

} else if (Literal.isFloatingLiteral()) {
QualType Ty;
if (Literal.isHalf){
Expand Down
43 changes: 43 additions & 0 deletions clang/test/AST/dfp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// RUN: %clang_cc1 -x c -ast-dump -fexperimental-decimal-floating-point %s | FileCheck %s --strict-whitespace

_Decimal32 x;
_Decimal64 y;
_Decimal128 z;

//CHECK: |-VarDecl {{.*}} x '_Decimal32'
//CHECK-NEXT: |-VarDecl {{.*}} y '_Decimal64'
//CHECK-NEXT: |-VarDecl {{.*}} z '_Decimal128'

void f(void) {
_Decimal32 x = 0.0DF;
_Decimal32 x2 = 0.00DF;
_Decimal32 x3 = 1234.0DF;
_Decimal32 x4 = 945.75DF;
_Decimal32 x5 = 1E-6DF; // DEC32_EPSILON
_Decimal32 x6 = 9.999999E40DF;
_Decimal32 x7 = 100000.0DF;
_Decimal32 x8 = 9.999999E96DF; // DEC32_MAX
_Decimal32 x9 = 1E-95DF; // DEC32_MIN
_Decimal32 x10 = 0.000001E-95DF; // DEC32_TRUE_MIN
}

//CHECK: | `-VarDecl {{.*}} x '_Decimal32'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Decimal32' 0E-1
//CHECK: | `-VarDecl {{.*}} x2 '_Decimal32'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Decimal32' 0E-2
//CHECK: | `-VarDecl {{.*}} x3 '_Decimal32'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Decimal32' 12340E-1
//CHECK: | `-VarDecl {{.*}} x4 '_Decimal32'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Decimal32' 94575E-2
//CHECK: | `-VarDecl {{.*}} x5 '_Decimal32'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Decimal32' 1E-6
//CHECK: | `-VarDecl {{.*}} x6 '_Decimal32'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Decimal32' 9999999E+34
//CHECK: | `-VarDecl {{.*}} x7 '_Decimal32'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Decimal32' 1000000E-1
//CHECK: | `-VarDecl {{.*}} x8 '_Decimal32'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Decimal32' 9999999E+90
//CHECK: | `-VarDecl {{.*}} x9 '_Decimal32'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Decimal32' 1E-95
//CHECK: `-VarDecl {{.*}} x10 '_Decimal32'
//CHECK-NEXT: `-FloatingLiteral {{.*}} '_Decimal32' 1E-101
Loading