diff options
| author | Gauthier Harnisch <tyker1@outlook.com> | 2019-06-15 10:24:47 +0000 |
|---|---|---|
| committer | Gauthier Harnisch <tyker1@outlook.com> | 2019-06-15 10:24:47 +0000 |
| commit | 83c7b61052bd46fac08a69a8f61ac56eba6d7ffc (patch) | |
| tree | dcfdd5c46e692b343f3586784c68eebea4ccfce8 /clang/lib/AST | |
| parent | b6dc09e725bf5782f45917cd92dcac7ab14cfe9c (diff) | |
| download | bcm5719-llvm-83c7b61052bd46fac08a69a8f61ac56eba6d7ffc.tar.gz bcm5719-llvm-83c7b61052bd46fac08a69a8f61ac56eba6d7ffc.zip | |
[clang] Add storage for APValue in ConstantExpr
Summary:
When using ConstantExpr we often need the result of the expression to be kept in the AST. Currently this is done on a by the node that needs the result and has been done multiple times for enumerator, for constexpr variables... . This patch adds to ConstantExpr the ability to store the result of evaluating the expression. no functional changes expected.
Changes:
- Add trailling object to ConstantExpr that can hold an APValue or an uint64_t. the uint64_t is here because most ConstantExpr yield integral values so there is an optimized layout for integral values.
- Add basic* serialization support for the trailing result.
- Move conversion functions from an enum to a fltSemantics from clang::FloatingLiteral to llvm::APFloatBase. this change is to make it usable for serializing APValues.
- Add basic* Import support for the trailing result.
- ConstantExpr created in CheckConvertedConstantExpression now stores the result in the ConstantExpr Node.
- Adapt AST dump to print the result when present.
basic* : None, Indeterminate, Int, Float, FixedPoint, ComplexInt, ComplexFloat,
the result is not yet used anywhere but for -ast-dump.
Reviewers: rsmith, martong, shafik
Reviewed By: rsmith
Subscribers: rnkovacs, hiraditya, dexonsmith, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D62399
llvm-svn: 363493
Diffstat (limited to 'clang/lib/AST')
| -rw-r--r-- | clang/lib/AST/APValue.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 141 | ||||
| -rw-r--r-- | clang/lib/AST/TextNodeDumper.cpp | 9 |
5 files changed, 127 insertions, 38 deletions
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 5d5e67a8902..1993bba9bd1 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -456,7 +456,8 @@ void APValue::dump(raw_ostream &OS) const { llvm_unreachable("Unknown APValue kind!"); } -void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ +void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, + QualType Ty) const { switch (getKind()) { case APValue::None: Out << "<out of lifetime>"; @@ -675,7 +676,7 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ llvm_unreachable("Unknown APValue kind!"); } -std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { +std::string APValue::getAsString(const ASTContext &Ctx, QualType Ty) const { std::string Result; llvm::raw_string_ostream Out(Result); printPretty(Out, Ctx, Ty); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 0657528dc1b..b3c9c20d2b3 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -827,6 +827,9 @@ ASTContext::~ASTContext() { for (const auto &Value : ModuleInitializers) Value.second->~PerModuleInitializers(); + + for (APValue *Value : APValueCleanups) + Value->~APValue(); } class ASTContext::ParentMap { diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index b43491d061a..d3c79eac903 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6376,6 +6376,13 @@ ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) { Expr *ToSubExpr; std::tie(ToSubExpr) = *Imp; + // TODO : Handle APValue::ValueKind that require importing. + APValue::ValueKind Kind = E->getResultAPValueKind(); + if (Kind == APValue::Int || Kind == APValue::Float || + Kind == APValue::FixedPoint || Kind == APValue::ComplexFloat || + Kind == APValue::ComplexInt) + return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, + E->getAPValueResult()); return ConstantExpr::Create(Importer.getToContext(), ToSubExpr); } diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 72e1119851b..f5714d93787 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -229,6 +229,110 @@ SourceLocation Expr::getExprLoc() const { // Primary Expressions. //===----------------------------------------------------------------------===// +static void AssertResultStorageKind(ConstantExpr::ResultStorageKind Kind) { + assert((Kind == ConstantExpr::RSK_APValue || + Kind == ConstantExpr::RSK_Int64 || Kind == ConstantExpr::RSK_None) && + "Invalid StorageKind Value"); +} + +ConstantExpr::ResultStorageKind +ConstantExpr::getStorageKind(const APValue &Value) { + switch (Value.getKind()) { + case APValue::None: + return ConstantExpr::RSK_None; + case APValue::Int: + if (!Value.getInt().needsCleanup()) + return ConstantExpr::RSK_Int64; + LLVM_FALLTHROUGH; + default: + return ConstantExpr::RSK_APValue; + } +} + +void ConstantExpr::DefaultInit(ResultStorageKind StorageKind) { + ConstantExprBits.ResultKind = StorageKind; + if (StorageKind == RSK_APValue) + ::new (getTrailingObjects<APValue>()) APValue(); +} + +ConstantExpr::ConstantExpr(Expr *subexpr, ResultStorageKind StorageKind) + : FullExpr(ConstantExprClass, subexpr) { + DefaultInit(StorageKind); +} + +ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E, + ResultStorageKind StorageKind) { + assert(!isa<ConstantExpr>(E)); + AssertResultStorageKind(StorageKind); + unsigned Size = totalSizeToAlloc<APValue, uint64_t>( + StorageKind == ConstantExpr::RSK_APValue, + StorageKind == ConstantExpr::RSK_Int64); + void *Mem = Context.Allocate(Size, alignof(ConstantExpr)); + ConstantExpr *Self = new (Mem) ConstantExpr(E, StorageKind); + if (StorageKind == ConstantExpr::RSK_APValue) + Context.AddAPValueCleanup(&Self->APValueResult()); + return Self; +} + +ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E, + const APValue &Result) { + ResultStorageKind StorageKind = getStorageKind(Result); + ConstantExpr *Self = Create(Context, E, StorageKind); + Self->SetResult(Result); + return Self; +} + +ConstantExpr::ConstantExpr(ResultStorageKind StorageKind, EmptyShell Empty) + : FullExpr(ConstantExprClass, Empty) { + DefaultInit(StorageKind); +} + +ConstantExpr *ConstantExpr::CreateEmpty(const ASTContext &Context, + ResultStorageKind StorageKind, + EmptyShell Empty) { + AssertResultStorageKind(StorageKind); + unsigned Size = totalSizeToAlloc<APValue, uint64_t>( + StorageKind == ConstantExpr::RSK_APValue, + StorageKind == ConstantExpr::RSK_Int64); + void *Mem = Context.Allocate(Size, alignof(ConstantExpr)); + ConstantExpr *Self = new (Mem) ConstantExpr(StorageKind, Empty); + if (StorageKind == ConstantExpr::RSK_APValue) + Context.AddAPValueCleanup(&Self->APValueResult()); + return Self; +} + +void ConstantExpr::MoveIntoResult(APValue &Value) { + assert(getStorageKind(Value) == ConstantExprBits.ResultKind && + "Invalid storage for this value kind"); + switch (ConstantExprBits.ResultKind) { + case RSK_None: + return; + case RSK_Int64: + Int64Result() = *Value.getInt().getRawData(); + ConstantExprBits.BitWidth = Value.getInt().getBitWidth(); + ConstantExprBits.IsUnsigned = Value.getInt().isUnsigned(); + return; + case RSK_APValue: + APValueResult() = std::move(Value); + return; + } + llvm_unreachable("Invalid ResultKind Bits"); +} + +APValue ConstantExpr::getAPValueResult() const { + switch (ConstantExprBits.ResultKind) { + case ConstantExpr::RSK_APValue: + return APValueResult(); + case ConstantExpr::RSK_Int64: + return APValue( + llvm::APSInt(llvm::APInt(ConstantExprBits.BitWidth, Int64Result()), + ConstantExprBits.IsUnsigned)); + case ConstantExpr::RSK_None: + return APValue(); + } + llvm_unreachable("invalid ResultKind"); +} + /// Compute the type-, value-, and instantiation-dependence of a /// declaration reference /// based on the declaration being referenced. @@ -840,7 +944,7 @@ FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, FloatingLiteral::FloatingLiteral(const ASTContext &C, EmptyShell Empty) : Expr(FloatingLiteralClass, Empty) { - setRawSemantics(IEEEhalf); + setRawSemantics(llvm::APFloatBase::S_IEEEhalf); FloatingLiteralBits.IsExact = false; } @@ -855,41 +959,6 @@ FloatingLiteral::Create(const ASTContext &C, EmptyShell Empty) { return new (C) FloatingLiteral(C, Empty); } -const llvm::fltSemantics &FloatingLiteral::getSemantics() const { - switch(FloatingLiteralBits.Semantics) { - case IEEEhalf: - return llvm::APFloat::IEEEhalf(); - case IEEEsingle: - return llvm::APFloat::IEEEsingle(); - case IEEEdouble: - return llvm::APFloat::IEEEdouble(); - case x87DoubleExtended: - return llvm::APFloat::x87DoubleExtended(); - case IEEEquad: - return llvm::APFloat::IEEEquad(); - case PPCDoubleDouble: - return llvm::APFloat::PPCDoubleDouble(); - } - llvm_unreachable("Unrecognised floating semantics"); -} - -void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) { - if (&Sem == &llvm::APFloat::IEEEhalf()) - FloatingLiteralBits.Semantics = IEEEhalf; - else if (&Sem == &llvm::APFloat::IEEEsingle()) - FloatingLiteralBits.Semantics = IEEEsingle; - else if (&Sem == &llvm::APFloat::IEEEdouble()) - FloatingLiteralBits.Semantics = IEEEdouble; - else if (&Sem == &llvm::APFloat::x87DoubleExtended()) - FloatingLiteralBits.Semantics = x87DoubleExtended; - else if (&Sem == &llvm::APFloat::IEEEquad()) - FloatingLiteralBits.Semantics = IEEEquad; - else if (&Sem == &llvm::APFloat::PPCDoubleDouble()) - FloatingLiteralBits.Semantics = PPCDoubleDouble; - else - llvm_unreachable("Unknown floating semantics"); -} - /// getValueAsApproximateDouble - This returns the value as an inaccurate /// double. Note that this may cause loss of precision, but is useful for /// debugging dumps, etc. diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 1998cfaec04..81b3b74f93a 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -223,6 +223,7 @@ void TextNodeDumper::Visit(const Decl *D) { return; } + Context = &D->getASTContext(); { ColorScope Color(OS, ShowColors, DeclKindNameColor); OS << D->getDeclKindName() << "Decl"; @@ -689,6 +690,14 @@ void TextNodeDumper::VisitCaseStmt(const CaseStmt *Node) { OS << " gnu_range"; } +void TextNodeDumper::VisitConstantExpr(const ConstantExpr *Node) { + if (Node->getResultAPValueKind() != APValue::None) { + ColorScope Color(OS, ShowColors, ValueColor); + OS << " "; + Node->getAPValueResult().printPretty(OS, *Context, Node->getType()); + } +} + void TextNodeDumper::VisitCallExpr(const CallExpr *Node) { if (Node->usesADL()) OS << " adl"; |

