[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
//===--- Pointer.cpp - Types for the constexpr VM ---------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Pointer.h"
|
2023-02-21 09:36:37 +01:00
|
|
|
#include "Boolean.h"
|
|
|
|
#include "Context.h"
|
|
|
|
#include "Floating.h"
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
#include "Function.h"
|
2023-02-21 09:36:37 +01:00
|
|
|
#include "Integral.h"
|
2020-02-20 14:54:22 -08:00
|
|
|
#include "InterpBlock.h"
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
#include "PrimType.h"
|
2023-02-21 09:36:37 +01:00
|
|
|
#include "Record.h"
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
using namespace clang::interp;
|
|
|
|
|
2024-01-31 08:03:37 +01:00
|
|
|
Pointer::Pointer(Block *Pointee)
|
|
|
|
: Pointer(Pointee, Pointee->getDescriptor()->getMetadataSize(),
|
|
|
|
Pointee->getDescriptor()->getMetadataSize()) {}
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
|
2022-12-26 09:29:04 +01:00
|
|
|
Pointer::Pointer(Block *Pointee, unsigned BaseAndOffset)
|
|
|
|
: Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
Pointer::Pointer(const Pointer &P) : Pointer(P.Pointee, P.Base, P.Offset) {}
|
|
|
|
|
|
|
|
Pointer::Pointer(Pointer &&P)
|
|
|
|
: Pointee(P.Pointee), Base(P.Base), Offset(P.Offset) {
|
|
|
|
if (Pointee)
|
2023-07-09 14:08:35 +02:00
|
|
|
Pointee->replacePointer(&P, this);
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset)
|
|
|
|
: Pointee(Pointee), Base(Base), Offset(Offset) {
|
|
|
|
assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");
|
|
|
|
if (Pointee)
|
|
|
|
Pointee->addPointer(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
Pointer::~Pointer() {
|
|
|
|
if (Pointee) {
|
|
|
|
Pointee->removePointer(this);
|
|
|
|
Pointee->cleanup();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Pointer::operator=(const Pointer &P) {
|
|
|
|
Block *Old = Pointee;
|
|
|
|
|
|
|
|
if (Pointee)
|
|
|
|
Pointee->removePointer(this);
|
|
|
|
|
|
|
|
Offset = P.Offset;
|
|
|
|
Base = P.Base;
|
|
|
|
|
|
|
|
Pointee = P.Pointee;
|
|
|
|
if (Pointee)
|
|
|
|
Pointee->addPointer(this);
|
|
|
|
|
|
|
|
if (Old)
|
|
|
|
Old->cleanup();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Pointer::operator=(Pointer &&P) {
|
|
|
|
Block *Old = Pointee;
|
|
|
|
|
|
|
|
if (Pointee)
|
|
|
|
Pointee->removePointer(this);
|
|
|
|
|
|
|
|
Offset = P.Offset;
|
|
|
|
Base = P.Base;
|
|
|
|
|
|
|
|
Pointee = P.Pointee;
|
|
|
|
if (Pointee)
|
2023-07-09 14:08:35 +02:00
|
|
|
Pointee->replacePointer(&P, this);
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
|
|
|
|
if (Old)
|
|
|
|
Old->cleanup();
|
|
|
|
}
|
|
|
|
|
|
|
|
APValue Pointer::toAPValue() const {
|
|
|
|
llvm::SmallVector<APValue::LValuePathEntry, 5> Path;
|
2024-02-12 13:11:11 +01:00
|
|
|
|
|
|
|
if (isZero())
|
|
|
|
return APValue(static_cast<const Expr *>(nullptr), CharUnits::Zero(), Path,
|
|
|
|
false, /*IsNullPtr=*/false);
|
|
|
|
|
|
|
|
// Build the lvalue base from the block.
|
|
|
|
const Descriptor *Desc = getDeclDesc();
|
|
|
|
APValue::LValueBase Base;
|
2024-02-12 15:20:24 +01:00
|
|
|
if (const auto *VD = Desc->asValueDecl())
|
2024-02-12 13:11:11 +01:00
|
|
|
Base = VD;
|
2024-02-12 15:20:24 +01:00
|
|
|
else if (const auto *E = Desc->asExpr())
|
2024-02-12 13:11:11 +01:00
|
|
|
Base = E;
|
|
|
|
else
|
|
|
|
llvm_unreachable("Invalid allocation type");
|
|
|
|
|
2024-02-12 13:00:36 +01:00
|
|
|
if (isDummy() || isUnknownSizeArray() || Desc->asExpr())
|
2024-02-12 13:11:11 +01:00
|
|
|
return APValue(Base, CharUnits::Zero(), Path, false, false);
|
|
|
|
|
|
|
|
// TODO: compute the offset into the object.
|
|
|
|
CharUnits Offset = CharUnits::Zero();
|
|
|
|
bool IsOnePastEnd = isOnePastEnd();
|
|
|
|
|
|
|
|
// Build the path into the object.
|
|
|
|
Pointer Ptr = *this;
|
|
|
|
while (Ptr.isField() || Ptr.isArrayElement()) {
|
|
|
|
if (Ptr.isArrayElement()) {
|
|
|
|
Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getIndex()));
|
|
|
|
Ptr = Ptr.getArray();
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
} else {
|
2024-02-12 13:11:11 +01:00
|
|
|
// TODO: figure out if base is virtual
|
|
|
|
bool IsVirtual = false;
|
|
|
|
|
|
|
|
// Create a path entry for the field.
|
|
|
|
const Descriptor *Desc = Ptr.getFieldDesc();
|
|
|
|
if (const auto *BaseOrMember = Desc->asDecl()) {
|
|
|
|
Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual}));
|
|
|
|
Ptr = Ptr.getBase();
|
|
|
|
continue;
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
2024-02-12 13:11:11 +01:00
|
|
|
llvm_unreachable("Invalid field type");
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-26 08:44:09 +02:00
|
|
|
// We assemble the LValuePath starting from the innermost pointer to the
|
|
|
|
// outermost one. SO in a.b.c, the first element in Path will refer to
|
|
|
|
// the field 'c', while later code expects it to refer to 'a'.
|
|
|
|
// Just invert the order of the elements.
|
|
|
|
std::reverse(Path.begin(), Path.end());
|
|
|
|
|
2024-02-12 13:11:11 +01:00
|
|
|
return APValue(Base, Offset, Path, IsOnePastEnd, /*IsNullPtr=*/false);
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
|
|
|
|
2023-04-25 19:53:40 +02:00
|
|
|
std::string Pointer::toDiagnosticString(const ASTContext &Ctx) const {
|
|
|
|
if (!Pointee)
|
|
|
|
return "nullptr";
|
|
|
|
|
|
|
|
return toAPValue().getAsString(Ctx, getType());
|
|
|
|
}
|
|
|
|
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
bool Pointer::isInitialized() const {
|
|
|
|
assert(Pointee && "Cannot check if null pointer was initialized");
|
2023-04-26 10:52:01 +02:00
|
|
|
const Descriptor *Desc = getFieldDesc();
|
2022-09-23 11:29:33 +02:00
|
|
|
assert(Desc);
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
if (Desc->isPrimitiveArray()) {
|
2022-10-27 11:32:31 +02:00
|
|
|
if (isStatic() && Base == 0)
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
return true;
|
2023-10-24 06:49:11 +02:00
|
|
|
|
|
|
|
InitMapPtr &IM = getInitMap();
|
|
|
|
|
|
|
|
if (!IM)
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
return false;
|
2023-10-24 06:49:11 +02:00
|
|
|
|
|
|
|
if (IM->first)
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
return true;
|
2023-10-24 06:49:11 +02:00
|
|
|
|
|
|
|
return IM->second->isElementInitialized(getIndex());
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
2023-07-05 05:37:34 +02:00
|
|
|
|
|
|
|
// Field has its bit in an inline descriptor.
|
|
|
|
return Base == 0 || getInlineDesc()->IsInitialized;
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Pointer::initialize() const {
|
|
|
|
assert(Pointee && "Cannot initialize null pointer");
|
2023-04-26 10:52:01 +02:00
|
|
|
const Descriptor *Desc = getFieldDesc();
|
2022-08-31 16:09:40 +02:00
|
|
|
|
2022-09-23 11:29:33 +02:00
|
|
|
assert(Desc);
|
2023-01-24 19:58:09 +01:00
|
|
|
if (Desc->isPrimitiveArray()) {
|
|
|
|
// Primitive global arrays don't have an initmap.
|
|
|
|
if (isStatic() && Base == 0)
|
|
|
|
return;
|
|
|
|
|
2023-10-24 06:49:11 +02:00
|
|
|
InitMapPtr &IM = getInitMap();
|
|
|
|
if (!IM)
|
|
|
|
IM =
|
|
|
|
std::make_pair(false, std::make_shared<InitMap>(Desc->getNumElems()));
|
|
|
|
|
|
|
|
assert(IM);
|
|
|
|
|
|
|
|
// All initialized.
|
|
|
|
if (IM->first)
|
2023-01-24 19:58:09 +01:00
|
|
|
return;
|
2023-10-24 06:49:11 +02:00
|
|
|
|
|
|
|
if (IM->second->initializeElement(getIndex())) {
|
|
|
|
IM->first = true;
|
|
|
|
IM->second.reset();
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
2023-07-09 06:24:51 +02:00
|
|
|
return;
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
2023-07-05 05:37:34 +02:00
|
|
|
|
|
|
|
// Field has its bit in an inline descriptor.
|
|
|
|
assert(Base != 0 && "Only composite fields can be initialised");
|
|
|
|
getInlineDesc()->IsInitialized = true;
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Pointer::activate() const {
|
|
|
|
// Field has its bit in an inline descriptor.
|
|
|
|
assert(Base != 0 && "Only composite fields can be initialised");
|
|
|
|
getInlineDesc()->IsActive = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Pointer::deactivate() const {
|
|
|
|
// TODO: this only appears in constructors, so nothing to deactivate.
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Pointer::hasSameBase(const Pointer &A, const Pointer &B) {
|
|
|
|
return A.Pointee == B.Pointee;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) {
|
2022-10-13 10:09:36 +02:00
|
|
|
return hasSameBase(A, B) && A.Base == B.Base && A.getFieldDesc()->IsArray;
|
[Clang Interpreter] Initial patch for the constexpr interpreter
Summary:
This patch introduces the skeleton of the constexpr interpreter,
capable of evaluating a simple constexpr functions consisting of
if statements. The interpreter is described in more detail in the
RFC. Further patches will add more features.
Reviewers: Bigcheese, jfb, rsmith
Subscribers: bruno, uenoku, ldionne, Tyker, thegameg, tschuett, dexonsmith, mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64146
llvm-svn: 371834
2019-09-13 09:46:16 +00:00
|
|
|
}
|
2023-02-21 09:36:37 +01:00
|
|
|
|
2024-01-19 10:08:03 +01:00
|
|
|
std::optional<APValue> Pointer::toRValue(const Context &Ctx) const {
|
|
|
|
// Method to recursively traverse composites.
|
|
|
|
std::function<bool(QualType, const Pointer &, APValue &)> Composite;
|
|
|
|
Composite = [&Composite, &Ctx](QualType Ty, const Pointer &Ptr, APValue &R) {
|
|
|
|
if (const auto *AT = Ty->getAs<AtomicType>())
|
|
|
|
Ty = AT->getValueType();
|
|
|
|
|
|
|
|
// Invalid pointers.
|
|
|
|
if (Ptr.isDummy() || !Ptr.isLive() ||
|
|
|
|
(!Ptr.isUnknownSizeArray() && Ptr.isOnePastEnd()))
|
|
|
|
return false;
|
2023-02-21 09:36:37 +01:00
|
|
|
|
2024-01-19 10:08:03 +01:00
|
|
|
// Primitive values.
|
|
|
|
if (std::optional<PrimType> T = Ctx.classify(Ty)) {
|
|
|
|
if (T == PT_Ptr || T == PT_FnPtr) {
|
|
|
|
R = Ptr.toAPValue();
|
|
|
|
} else {
|
|
|
|
TYPE_SWITCH(*T, R = Ptr.deref<T>().toAPValue());
|
|
|
|
}
|
|
|
|
return true;
|
2023-02-21 09:36:37 +01:00
|
|
|
}
|
|
|
|
|
2024-01-19 10:08:03 +01:00
|
|
|
if (const auto *RT = Ty->getAs<RecordType>()) {
|
|
|
|
const auto *Record = Ptr.getRecord();
|
|
|
|
assert(Record && "Missing record descriptor");
|
|
|
|
|
|
|
|
bool Ok = true;
|
|
|
|
if (RT->getDecl()->isUnion()) {
|
|
|
|
const FieldDecl *ActiveField = nullptr;
|
|
|
|
APValue Value;
|
|
|
|
for (const auto &F : Record->fields()) {
|
|
|
|
const Pointer &FP = Ptr.atField(F.Offset);
|
|
|
|
QualType FieldTy = F.Decl->getType();
|
|
|
|
if (FP.isActive()) {
|
|
|
|
if (std::optional<PrimType> T = Ctx.classify(FieldTy)) {
|
|
|
|
TYPE_SWITCH(*T, Value = FP.deref<T>().toAPValue());
|
|
|
|
} else {
|
|
|
|
Ok &= Composite(FieldTy, FP, Value);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
R = APValue(ActiveField, Value);
|
|
|
|
} else {
|
|
|
|
unsigned NF = Record->getNumFields();
|
|
|
|
unsigned NB = Record->getNumBases();
|
|
|
|
unsigned NV = Ptr.isBaseClass() ? 0 : Record->getNumVirtualBases();
|
|
|
|
|
|
|
|
R = APValue(APValue::UninitStruct(), NB, NF);
|
|
|
|
|
|
|
|
for (unsigned I = 0; I < NF; ++I) {
|
|
|
|
const Record::Field *FD = Record->getField(I);
|
|
|
|
QualType FieldTy = FD->Decl->getType();
|
|
|
|
const Pointer &FP = Ptr.atField(FD->Offset);
|
|
|
|
APValue &Value = R.getStructField(I);
|
|
|
|
|
|
|
|
if (std::optional<PrimType> T = Ctx.classify(FieldTy)) {
|
|
|
|
TYPE_SWITCH(*T, Value = FP.deref<T>().toAPValue());
|
|
|
|
} else {
|
|
|
|
Ok &= Composite(FieldTy, FP, Value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned I = 0; I < NB; ++I) {
|
|
|
|
const Record::Base *BD = Record->getBase(I);
|
|
|
|
QualType BaseTy = Ctx.getASTContext().getRecordType(BD->Decl);
|
|
|
|
const Pointer &BP = Ptr.atField(BD->Offset);
|
|
|
|
Ok &= Composite(BaseTy, BP, R.getStructBase(I));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned I = 0; I < NV; ++I) {
|
|
|
|
const Record::Base *VD = Record->getVirtualBase(I);
|
|
|
|
QualType VirtBaseTy = Ctx.getASTContext().getRecordType(VD->Decl);
|
|
|
|
const Pointer &VP = Ptr.atField(VD->Offset);
|
|
|
|
Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Ok;
|
2023-02-21 09:36:37 +01:00
|
|
|
}
|
|
|
|
|
2024-01-19 10:08:03 +01:00
|
|
|
if (Ty->isIncompleteArrayType()) {
|
|
|
|
R = APValue(APValue::UninitArray(), 0, 0);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const auto *AT = Ty->getAsArrayTypeUnsafe()) {
|
|
|
|
const size_t NumElems = Ptr.getNumElems();
|
|
|
|
QualType ElemTy = AT->getElementType();
|
|
|
|
R = APValue(APValue::UninitArray{}, NumElems, NumElems);
|
|
|
|
|
|
|
|
bool Ok = true;
|
|
|
|
for (unsigned I = 0; I < NumElems; ++I) {
|
|
|
|
APValue &Slot = R.getArrayInitializedElt(I);
|
|
|
|
const Pointer &EP = Ptr.atIndex(I);
|
|
|
|
if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
|
|
|
|
TYPE_SWITCH(*T, Slot = EP.deref<T>().toAPValue());
|
|
|
|
} else {
|
|
|
|
Ok &= Composite(ElemTy, EP.narrow(), Slot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Ok;
|
|
|
|
}
|
2023-02-21 09:36:37 +01:00
|
|
|
|
2024-01-19 10:08:03 +01:00
|
|
|
// Complex types.
|
|
|
|
if (const auto *CT = Ty->getAs<ComplexType>()) {
|
|
|
|
QualType ElemTy = CT->getElementType();
|
|
|
|
std::optional<PrimType> ElemT = Ctx.classify(ElemTy);
|
|
|
|
assert(ElemT);
|
|
|
|
|
|
|
|
if (ElemTy->isIntegerType()) {
|
|
|
|
INT_TYPE_SWITCH(*ElemT, {
|
|
|
|
auto V1 = Ptr.atIndex(0).deref<T>();
|
|
|
|
auto V2 = Ptr.atIndex(1).deref<T>();
|
|
|
|
R = APValue(V1.toAPSInt(), V2.toAPSInt());
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
} else if (ElemTy->isFloatingType()) {
|
|
|
|
R = APValue(Ptr.atIndex(0).deref<Floating>().getAPFloat(),
|
|
|
|
Ptr.atIndex(1).deref<Floating>().getAPFloat());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("invalid value to return");
|
|
|
|
};
|
|
|
|
|
|
|
|
if (isZero())
|
|
|
|
return APValue(static_cast<Expr *>(nullptr), CharUnits::Zero(), {}, false,
|
|
|
|
true);
|
|
|
|
|
|
|
|
if (isDummy() || !isLive())
|
|
|
|
return std::nullopt;
|
|
|
|
|
|
|
|
// Return the composite type.
|
|
|
|
APValue Result;
|
|
|
|
if (!Composite(getType(), *this, Result))
|
|
|
|
return std::nullopt;
|
2023-02-21 09:36:37 +01:00
|
|
|
return Result;
|
|
|
|
}
|