13#ifndef LLVM_CLANG_AST_INTERP_INTERP_H
14#define LLVM_CLANG_AST_INTERP_INTERP_H
30#include "llvm/ADT/APFloat.h"
31#include "llvm/ADT/APSInt.h"
32#include "llvm/Support/Endian.h"
39using APInt = llvm::APInt;
40using APSInt = llvm::APSInt;
49bool CheckExtern(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
52bool CheckArray(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
55bool CheckLive(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
58bool CheckNull(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
62bool CheckRange(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
66bool CheckRange(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
70bool CheckConst(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
73bool CheckMutable(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
76bool CheckLoad(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
79bool CheckStore(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
82bool CheckInvoke(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
85bool CheckInit(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
88bool CheckCallable(InterpState &S, CodePtr OpPC,
const Function *F);
91bool CheckThis(InterpState &S, CodePtr OpPC,
const Pointer &
This);
100template <
typename RT>
102 if (RHS.isNegative()) {
103 const SourceInfo &Loc = S.Current->getSource(OpPC);
104 S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
110 if (Bits > 1 && RHS >= RT::from(Bits, RHS.bitWidth())) {
111 const Expr *E = S.Current->getExpr(OpPC);
112 const APSInt Val = RHS.toAPSInt();
114 S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
124 const SourceInfo &Loc = S.Current->getSource(OpPC);
125 S.FFDiag(Loc, diag::note_expr_divide_by_zero);
129 if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) {
130 APSInt LHSInt = LHS.toAPSInt();
132 (-LHSInt.extend(LHSInt.getBitWidth() + 1)).
toString(Trunc, 10);
133 const SourceInfo &Loc = S.Current->getSource(OpPC);
134 const Expr *E = S.Current->getExpr(OpPC);
135 S.CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->
getType();
143bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status);
157template <
PrimType Name,
bool Builtin =
false,
158 class T =
typename PrimConv<Name>::T>
161 const T &
Ret = S.Stk.pop<T>();
163 assert(S.Current->getFrameOffset() == S.Stk.size() &&
"Invalid frame");
164 if (Builtin || !S.checkingPotentialConstantExpression())
165 S.Current->popArgs();
168 PC = S.Current->getRetPC();
181template <
bool Builtin = false>
185 assert(S.Current->getFrameOffset() == S.Stk.size() &&
"Invalid frame");
186 if (Builtin || !S.checkingPotentialConstantExpression())
187 S.Current->popArgs();
190 PC = S.Current->getRetPC();
205 template <typename U>
class OpAP>
210 if (!OpFW(LHS, RHS, Bits, &
Result)) {
219 APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));
222 const Expr *E = S.Current->getExpr(OpPC);
224 if (S.checkingForUndefinedBehavior()) {
228 S.report(Loc, diag::warn_integer_constant_overflow) << Trunc <<
Type;
231 S.CCEDiag(E, diag::note_constexpr_overflow) <<
Value <<
Type;
232 return S.noteUndefinedBehavior();
236template <PrimType Name, class T = typename PrimConv<Name>::T>
238 const T &RHS = S.Stk.pop<T>();
239 const T &LHS = S.Stk.pop<T>();
240 const unsigned Bits = RHS.bitWidth() + 1;
241 return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
254template <PrimType Name, class T = typename PrimConv<Name>::T>
256 const T &RHS = S.Stk.pop<T>();
257 const T &LHS = S.Stk.pop<T>();
258 const unsigned Bits = RHS.bitWidth() + 1;
259 return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
272template <PrimType Name, class T = typename PrimConv<Name>::T>
274 const T &RHS = S.Stk.pop<T>();
275 const T &LHS = S.Stk.pop<T>();
276 const unsigned Bits = RHS.bitWidth() * 2;
277 return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
292template <PrimType Name, class T = typename PrimConv<Name>::T>
294 const T &RHS = S.Stk.pop<T>();
295 const T &LHS = S.Stk.pop<T>();
297 unsigned Bits = RHS.bitWidth();
299 if (!T::bitAnd(LHS, RHS, Bits, &
Result)) {
309template <PrimType Name, class T = typename PrimConv<Name>::T>
311 const T &RHS = S.Stk.pop<T>();
312 const T &LHS = S.Stk.pop<T>();
314 unsigned Bits = RHS.bitWidth();
316 if (!T::bitOr(LHS, RHS, Bits, &
Result)) {
326template <PrimType Name, class T = typename PrimConv<Name>::T>
328 const T &RHS = S.Stk.pop<T>();
329 const T &LHS = S.Stk.pop<T>();
331 unsigned Bits = RHS.bitWidth();
333 if (!T::bitXor(LHS, RHS, Bits, &
Result)) {
343template <PrimType Name, class T = typename PrimConv<Name>::T>
345 const T &RHS = S.Stk.pop<T>();
346 const T &LHS = S.Stk.pop<T>();
351 const unsigned Bits = RHS.bitWidth() * 2;
353 if (!T::rem(LHS, RHS, Bits, &
Result)) {
363template <PrimType Name, class T = typename PrimConv<Name>::T>
365 const T &RHS = S.Stk.pop<T>();
366 const T &LHS = S.Stk.pop<T>();
371 const unsigned Bits = RHS.bitWidth() * 2;
373 if (!T::div(LHS, RHS, Bits, &
Result)) {
397template <PrimType Name, class T = typename PrimConv<Name>::T>
400 const T &Val = S.Stk.pop<T>();
401 const unsigned Bits = Val.bitWidth();
405 S.Stk.push<BoolT>(R);
413template <PrimType Name, class T = typename PrimConv<Name>::T>
415 const T &Val = S.Stk.pop<T>();
432template <
typename T, IncDecOp Op, PushVal DoPush>
454 unsigned Bits =
Value.bitWidth() + 1;
457 APResult = ++
Value.toAPSInt(Bits);
459 APResult = --
Value.toAPSInt(Bits);
462 const Expr *E = S.Current->getExpr(OpPC);
464 if (S.checkingForUndefinedBehavior()) {
468 S.report(Loc, diag::warn_integer_constant_overflow) << Trunc <<
Type;
472 S.CCEDiag(E, diag::note_constexpr_overflow) << APResult <<
Type;
473 return S.noteUndefinedBehavior();
480template <PrimType Name, class T = typename PrimConv<Name>::T>
485 return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr);
491template <PrimType Name, class T = typename PrimConv<Name>::T>
496 return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr);
503template <PrimType Name, class T = typename PrimConv<Name>::T>
508 return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr);
514template <PrimType Name, class T = typename PrimConv<Name>::T>
519 return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr);
524template <PrimType Name, class T = typename PrimConv<Name>::T>
526 const T &Val = S.Stk.pop<T>();
528 if (!T::comp(Val, &
Result)) {
545 const T &RHS = S.Stk.pop<T>();
546 const T &LHS = S.Stk.pop<T>();
547 S.Stk.push<BoolT>(BoolT::from(Fn(LHS.compare(RHS))));
553 return CmpHelper<T>(S, OpPC, Fn);
563 const SourceInfo &Loc = S.Current->getSource(OpPC);
564 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
567 unsigned VL = LHS.getByteOffset();
569 S.Stk.push<BoolT>(BoolT::from(Fn(
Compare(VL, VR))));
580 if (LHS.isZero() && RHS.
isZero()) {
589 unsigned VL = LHS.getByteOffset();
596 if (LHS.inArray() && LHS.isRoot())
597 VL = LHS.atIndex(0).getByteOffset();
601 S.Stk.push<BoolT>(BoolT::from(Fn(
Compare(VL, VR))));
606template <PrimType Name, class T = typename PrimConv<Name>::T>
613template <PrimType Name, class T = typename PrimConv<Name>::T>
620template <PrimType Name, class T = typename PrimConv<Name>::T>
627template <PrimType Name, class T = typename PrimConv<Name>::T>
635template <PrimType Name, class T = typename PrimConv<Name>::T>
642template <PrimType Name, class T = typename PrimConv<Name>::T>
654template <PrimType Name, class T = typename PrimConv<Name>::T>
656 const T RHS = S.Stk.pop<T>();
657 const T LHS = S.Stk.pop<T>();
658 const T
Value = S.Stk.pop<T>();
660 S.Stk.push<
bool>(LHS <=
Value &&
Value <= RHS);
668template <PrimType Name, class T = typename PrimConv<Name>::T>
670 S.Stk.push<T>(S.Stk.peek<T>());
674template <PrimType Name, class T = typename PrimConv<Name>::T>
684template <PrimType Name, class T = typename PrimConv<Name>::T>
694template <PrimType Name, class T = typename PrimConv<Name>::T>
696 const Pointer &Ptr = S.Current->getLocalPointer(I);
699 S.Stk.push<T>(Ptr.
deref<T>());
703template <PrimType Name, class T = typename PrimConv<Name>::T>
705 S.Current->setLocal<T>(I, S.Stk.pop<T>());
709template <PrimType Name, class T = typename PrimConv<Name>::T>
711 if (S.checkingPotentialConstantExpression()) {
714 S.Stk.push<T>(S.Current->getParam<T>(I));
718template <PrimType Name, class T = typename PrimConv<Name>::T>
720 S.Current->setParam<T>(I, S.Stk.pop<T>());
726template <PrimType Name, class T = typename PrimConv<Name>::T>
736 S.Stk.push<T>(Field.deref<T>());
740template <PrimType Name, class T = typename PrimConv<Name>::T>
742 const T &
Value = S.Stk.pop<T>();
748 const Pointer &Field = Obj.atField(I);
751 Field.deref<T>() =
Value;
757template <PrimType Name, class T = typename PrimConv<Name>::T>
767 S.Stk.push<T>(Field.deref<T>());
771template <PrimType Name, class T = typename PrimConv<Name>::T>
773 if (S.checkingPotentialConstantExpression())
781 S.Stk.push<T>(Field.deref<T>());
785template <PrimType Name, class T = typename PrimConv<Name>::T>
787 if (S.checkingPotentialConstantExpression())
789 const T &
Value = S.Stk.pop<T>();
796 Field.deref<T>() =
Value;
800template <PrimType Name, class T = typename PrimConv<Name>::T>
802 auto *B = S.P.getGlobal(I);
805 S.Stk.push<T>(B->deref<T>());
809template <PrimType Name, class T = typename PrimConv<Name>::T>
815template <PrimType Name, class T = typename PrimConv<Name>::T>
817 S.P.getGlobal(I)->deref<T>() = S.Stk.pop<T>();
824template <PrimType Name, class T = typename PrimConv<Name>::T>
828 const T
Value = S.Stk.peek<T>();
833 S.P.getGlobal(I)->deref<T>() = S.Stk.pop<T>();
837template <PrimType Name, class T = typename PrimConv<Name>::T>
839 if (S.checkingPotentialConstantExpression())
845 Field.deref<T>() = S.Stk.pop<T>();
850template <PrimType Name, class T = typename PrimConv<Name>::T>
852 if (S.checkingPotentialConstantExpression())
858 const auto &
Value = S.Stk.pop<T>();
864template <PrimType Name, class T = typename PrimConv<Name>::T>
866 if (S.checkingPotentialConstantExpression())
872 Field.deref<T>() = S.Stk.pop<T>();
881template <PrimType Name, class T = typename PrimConv<Name>::T>
883 const T &
Value = S.Stk.pop<T>();
885 Field.deref<T>() =
Value;
891template <PrimType Name, class T = typename PrimConv<Name>::T>
893 const T &
Value = S.Stk.pop<T>();
901template <PrimType Name, class T = typename PrimConv<Name>::T>
903 const T &
Value = S.Stk.pop<T>();
905 const Pointer &Field = Ptr.atField(I);
906 Field.deref<T>() =
Value;
917 S.Stk.push<
Pointer>(S.Current->getLocalPointer(I));
922 if (S.checkingPotentialConstantExpression()) {
925 S.Stk.push<
Pointer>(S.Current->getParamPointer(I));
930 S.Stk.push<
Pointer>(S.P.getPtrGlobal(I));
949 if (S.checkingPotentialConstantExpression())
967 S.Stk.push<
Pointer>(std::move(Field));
972 if (S.checkingPotentialConstantExpression())
980 S.Stk.push<
Pointer>(std::move(Field));
1001 if (S.checkingPotentialConstantExpression())
1013 while (
Base.isBaseClass())
1016 auto *Field =
Base.getRecord()->getVirtualBase(
Decl);
1030 if (S.checkingPotentialConstantExpression())
1042template <PrimType Name, class T = typename PrimConv<Name>::T>
1047 S.Stk.push<T>(Ptr.
deref<T>());
1051template <PrimType Name, class T = typename PrimConv<Name>::T>
1056 S.Stk.push<T>(Ptr.
deref<T>());
1060template <PrimType Name, class T = typename PrimConv<Name>::T>
1062 const T &
Value = S.Stk.pop<T>();
1068 Ptr.deref<T>() =
Value;
1072template <PrimType Name, class T = typename PrimConv<Name>::T>
1074 const T &
Value = S.Stk.pop<T>();
1080 Ptr.deref<T>() =
Value;
1084template <PrimType Name, class T = typename PrimConv<Name>::T>
1086 const T &
Value = S.Stk.pop<T>();
1092 if (
auto *FD = Ptr.getField()) {
1093 Ptr.deref<T>() =
Value.truncate(FD->getBitWidthValue(S.getCtx()));
1095 Ptr.deref<T>() =
Value;
1100template <PrimType Name, class T = typename PrimConv<Name>::T>
1102 const T &
Value = S.Stk.pop<T>();
1108 if (
auto *FD = Ptr.getField()) {
1109 Ptr.deref<T>() =
Value.truncate(FD->getBitWidthValue(S.getCtx()));
1111 Ptr.deref<T>() =
Value;
1116template <PrimType Name, class T = typename PrimConv<Name>::T>
1118 const T &
Value = S.Stk.pop<T>();
1123 new (&Ptr.deref<T>()) T(
Value);
1130template <PrimType Name, class T = typename PrimConv<Name>::T>
1132 const T &
Value = S.Stk.pop<T>();
1137 new (&Ptr.deref<T>()) T(
Value);
1142template <PrimType Name, class T = typename PrimConv<Name>::T>
1144 const T &
Value = S.Stk.pop<T>();
1149 new (&Ptr.deref<T>()) T(
Value);
1157template <
class T, ArithOp Op>
1182 auto InvalidOffset = [&]() {
1183 const unsigned Bits =
Offset.bitWidth();
1184 APSInt APOffset(
Offset.toAPSInt().extend(Bits + 2),
false);
1185 APSInt APIndex(Index.toAPSInt().extend(Bits + 2),
false);
1187 (Op ==
ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
1188 S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
1190 <<
static_cast<int>(!Ptr.
inArray())
1191 <<
static_cast<unsigned>(MaxIndex);
1195 unsigned MaxOffset = MaxIndex - Ptr.
getIndex();
1199 return InvalidOffset();
1203 return InvalidOffset();
1207 return InvalidOffset();
1211 return InvalidOffset();
1215 int64_t WideIndex =
static_cast<int64_t
>(Index);
1216 int64_t WideOffset =
static_cast<int64_t
>(
Offset);
1219 Result = WideIndex + WideOffset;
1221 Result = WideIndex - WideOffset;
1227template <PrimType Name, class T = typename PrimConv<Name>::T>
1229 const T &
Offset = S.Stk.pop<T>();
1231 return OffsetHelper<T, ArithOp::Add>(S, OpPC,
Offset, Ptr);
1234template <PrimType Name, class T = typename PrimConv<Name>::T>
1236 const T &
Offset = S.Stk.pop<T>();
1238 return OffsetHelper<T, ArithOp::Sub>(S, OpPC,
Offset, Ptr);
1241template <ArithOp Op>
1251 OneT One = OneT::from(1);
1252 if (!OffsetHelper<OneT, Op>(S, OpPC, One,
P))
1261 return IncDecPtrHelper<ArithOp::Add>(S, OpPC);
1265 return IncDecPtrHelper<ArithOp::Sub>(S, OpPC);
1271template <PrimType Name, class T = typename PrimConv<Name>::T>
1282 T B = T::from(RHS.getIndex());
1283 return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, A.bitWidth(), A, B);
1291 S.Current->destroy(I);
1302 S.Stk.push<
U>(U::from(S.Stk.pop<T>()));
1309bool CastFP(InterpState &S, CodePtr OpPC,
const llvm::fltSemantics *Sem,
1310 llvm::RoundingMode RM);
1312template <PrimType Name, class T = typename PrimConv<Name>::T>
1314 const llvm::fltSemantics *Sem,
1315 llvm::RoundingMode RM) {
1316 const T &From = S.Stk.pop<T>();
1317 APSInt FromAP = From.toAPSInt();
1326template <PrimType Name, class T = typename PrimConv<Name>::T>
1330 if constexpr (std::is_same_v<T, Boolean>) {
1339 if ((Status & APFloat::opStatus::opInvalidOp) && F.
isFinite()) {
1340 const Expr *E = S.Current->getExpr(OpPC);
1343 S.CCEDiag(E, diag::note_constexpr_overflow) << F.
getAPFloat() <<
Type;
1344 return S.noteUndefinedBehavior();
1347 S.Stk.push<T>(T(
Result));
1356template <PrimType Name, class T = typename PrimConv<Name>::T>
1358 S.Stk.push<T>(T::zero());
1362template <PrimType Name, class T = typename PrimConv<Name>::T>
1374 if (S.checkingPotentialConstantExpression()) {
1387 assert(S.Current->getFunction()->hasRVO());
1388 if (S.checkingPotentialConstantExpression())
1390 S.Stk.push<
Pointer>(S.Current->getRVOPtr());
1398template <PrimType NameL, PrimType NameR>
1402 const auto &RHS = S.Stk.pop<RT>();
1403 const auto &LHS = S.Stk.pop<
LT>();
1404 const unsigned Bits = LHS.bitWidth();
1406 if (!CheckShift<RT>(S, OpPC, RHS, Bits))
1410 Integral<LT::bitWidth(),
false>::shiftRight(LHS.toUnsigned(), RHS, Bits, &R);
1415template <PrimType NameL, PrimType NameR>
1419 const auto &RHS = S.Stk.pop<RT>();
1420 const auto &LHS = S.Stk.pop<
LT>();
1421 const unsigned Bits = LHS.bitWidth();
1423 if (!CheckShift<RT>(S, OpPC, RHS, Bits))
1427 Integral<LT::bitWidth(),
false>::shiftLeft(LHS.toUnsigned(), RHS, Bits, &R);
1438 S.FFDiag(EndLoc, diag::note_constexpr_no_return);
1466template <PrimType Name, class T = typename PrimConv<Name>::T>
1468 const T &
Offset = S.Stk.pop<T>();
1471 if (!OffsetHelper<T, ArithOp::Add>(S, OpPC,
Offset, Ptr))
1477template <PrimType Name, class T = typename PrimConv<Name>::T>
1479 const T &
Offset = S.Stk.pop<T>();
1482 if (!OffsetHelper<T, ArithOp::Add>(S, OpPC,
Offset, Ptr))
1494 auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
1497 ThisPtr = NewFrame->getThis();
1501 if (S.checkingPotentialConstantExpression())
1509 S.Current = NewFrame.get();
1517 assert(S.Current == FrameBefore);
1523 S.Current = FrameBefore;
1528 auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
1531 S.Current = NewFrame.get();
1537 S.Current = FrameBefore;
1546 if constexpr (std::is_pointer<T>::value) {
1547 uint32_t ID = OpPC.
read<uint32_t>();
1548 return reinterpret_cast<T
>(S.P.getNativePointer(ID));
1550 return OpPC.
read<T>();
Defines the clang::ASTContext interface.
ASTImporterLookupTable & LT
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Represents a static or instance method of a struct/union/class.
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
unsigned getBitWidthValue(const ASTContext &Ctx) const
Implicit declaration of a temporary that was materialized by a MaterializeTemporaryExpr and lifetime-...
APValue * getOrCreateValue(bool MayCreate) const
Get the storage for the constant value of a materialized temporary of static storage duration.
A (possibly-)qualified type.
Represents a struct/union/class.
Encodes a location in the source.
The base class of the type hierarchy.
Wrapper around boolean types.
static bool inv(Boolean A, Boolean *R)
Pointer into the code segment.
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
static APFloat::opStatus div(Floating A, Floating B, llvm::RoundingMode RM, Floating *R)
const APFloat & getAPFloat() const
static APFloat::opStatus sub(Floating A, Floating B, llvm::RoundingMode RM, Floating *R)
static APFloat::opStatus fromIntegral(APSInt Val, const llvm::fltSemantics &Sem, llvm::RoundingMode RM, Floating &Result)
APFloat::opStatus convertToInteger(APSInt &Result) const
static APFloat::opStatus add(Floating A, Floating B, llvm::RoundingMode RM, Floating *R)
static APFloat::opStatus mul(Floating A, Floating B, llvm::RoundingMode RM, Floating *R)
bool hasThisPointer() const
unsigned getBuiltinID() const
Wrapper around numeric types.
Frame storing local variables.
A pointer to a memory block, live or dead.
static bool hasSameBase(const Pointer &A, const Pointer &B)
Checks if two pointers are comparable.
Pointer narrow() const
Restricts the scope of an array element pointer.
void deactivate() const
Deactivates an entire strurcutre.
int64_t getIndex() const
Returns the index into an array.
Pointer atIndex(unsigned Idx) const
Offsets a pointer inside an array.
Pointer atField(unsigned Off) const
Creates a pointer to a field.
T & deref() const
Dereferences the pointer, if it's live.
unsigned getNumElems() const
Returns the number of elements.
bool inArray() const
Checks if the innermost field is an array.
bool isZero() const
Checks if the pointer is null.
bool isRoot() const
Pointer points directly to a block.
static bool hasSameArray(const Pointer &A, const Pointer &B)
Checks if two pointers can be subtracted.
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
void initialize() const
Initializes a field.
unsigned getByteOffset() const
Returns the byte offset from the start.
Describes the statement/declaration an opcode was generated from.
bool InitPop(InterpState &S, CodePtr OpPC)
bool Inv(InterpState &S, CodePtr OpPC)
bool Shr(InterpState &S, CodePtr OpPC)
bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I, const LifetimeExtendedTemporaryDecl *Temp)
1) Converts the value on top of the stack to an APValue 2) Sets that APValue on \Temp 3) Initialized ...
bool IncPop(InterpState &S, CodePtr OpPC)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off)
bool Subf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
bool GT(InterpState &S, CodePtr OpPC)
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
bool DecPop(InterpState &S, CodePtr OpPC)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value decreased by ...
bool GetThisField(InterpState &S, CodePtr OpPC, uint32_t I)
bool NarrowPtr(InterpState &S, CodePtr OpPC)
bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I)
bool Interpret(InterpState &S, APValue &Result)
Interpreter entry point.
bool GetParam(InterpState &S, CodePtr OpPC, uint32_t I)
bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx)
The same as InitElem, but pops the pointer as well.
bool StoreBitField(InterpState &S, CodePtr OpPC)
bool LoadPop(InterpState &S, CodePtr OpPC)
static bool IncPtr(InterpState &S, CodePtr OpPC)
bool Dup(InterpState &S, CodePtr OpPC)
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the 'this' pointer.
bool SetField(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks that all fields are initialized after a constructor call.
bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS)
Checks if Div/Rem operation on LHS and RHS is valid.
bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS, const T &RHS)
bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off)
1) Pops a Pointer from the stack 2) Pushes Pointer.atField(Off) on the stack
bool Div(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off)
bool SubPtr(InterpState &S, CodePtr OpPC)
1) Pops a Pointer from the stack.
bool ReturnValue(const T &V, APValue &R)
Convert a value to an APValue.
bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool ArrayElemPtr(InterpState &S, CodePtr OpPC)
bool NE(InterpState &S, CodePtr OpPC)
bool NoRet(InterpState &S, CodePtr OpPC)
bool Addf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
bool Shl(InterpState &S, CodePtr OpPC)
bool RVOPtr(InterpState &S, CodePtr OpPC)
bool SubOffset(InterpState &S, CodePtr OpPC)
bool BitXor(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
bool ExpandPtr(InterpState &S, CodePtr OpPC)
bool InitThisFieldActive(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
bool Store(InterpState &S, CodePtr OpPC)
bool GetField(InterpState &S, CodePtr OpPC, uint32_t I)
1) Peeks a pointer on the stack 2) Pushes the value of the pointer's field on the stack
bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC)
bool This(InterpState &S, CodePtr OpPC)
bool InterpretBuiltin(InterpState &S, CodePtr &PC, unsigned BuiltinID)
Interpret a builtin function.
bool Mulf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
bool InitField(InterpState &S, CodePtr OpPC, uint32_t I)
1) Pops the value from the stack 2) Peeks a pointer from the stack 3) Pushes the value to field I of ...
bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status)
Checks if the result is a floating-point operation is valid in the current context.
bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn)
llvm::function_ref< bool(ComparisonCategoryResult)> CompareFn
T ReadArg(InterpState &S, CodePtr &OpPC)
bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
bool CastFloatingIntegral(InterpState &S, CodePtr OpPC)
bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I)
bool BitAnd(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool CallBI(InterpState &S, CodePtr &PC, const Function *Func)
bool CastIntegralFloating(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, llvm::RoundingMode RM)
bool LE(InterpState &S, CodePtr OpPC)
PrimType
Enumeration of the primitive types of the VM.
bool Zero(InterpState &S, CodePtr OpPC)
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be stored in a block.
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, llvm::RoundingMode RM)
1) Pops a Floating from the stack.
ComparisonCategoryResult Compare(const T &X, const T &Y)
Helper to compare two comparable types.
static bool IncDecPtrHelper(InterpState &S, CodePtr OpPC)
bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I)
bool StoreBitFieldPop(InterpState &S, CodePtr OpPC)
static bool DecPtr(InterpState &S, CodePtr OpPC)
bool RetVoid(InterpState &S, CodePtr &PC, APValue &Result)
bool CheckGlobalCtor(InterpState &S, CodePtr &PC)
bool Null(InterpState &S, CodePtr OpPC)
bool InitFieldActive(InterpState &S, CodePtr OpPC, uint32_t I)
bool Rem(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl, const Pointer &Ptr)
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be loaded from a block.
bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off)
bool GetPtrActiveField(InterpState &S, CodePtr OpPC, uint32_t Off)
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off)
bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I)
bool Comp(InterpState &S, CodePtr OpPC)
1) Pops the value from the stack.
bool StorePop(InterpState &S, CodePtr OpPC)
bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F)
bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I)
bool Mul(InterpState &S, CodePtr OpPC)
bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx)
1) Pops the value from the stack 2) Peeks a pointer and gets its index \Idx 3) Sets the value on the ...
bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I)
bool Pop(InterpState &S, CodePtr OpPC)
bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F)
bool GetPtrVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D)
bool Call(InterpState &S, CodePtr &PC, const Function *Func)
bool InRange(InterpState &S, CodePtr OpPC)
bool Neg(InterpState &S, CodePtr OpPC)
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
bool Divf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM)
bool BitOr(InterpState &S, CodePtr OpPC)
1) Pops the RHS from the stack.
bool Load(InterpState &S, CodePtr OpPC)
bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool Cast(InterpState &S, CodePtr OpPC)
bool EQ(InterpState &S, CodePtr OpPC)
bool GetFieldPop(InterpState &S, CodePtr OpPC, uint32_t I)
1) Pops a pointer from the stack 2) Pushes the value of the pointer's field on the stack
bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Checks if a method can be called.
bool AddOffset(InterpState &S, CodePtr OpPC)
bool Const(InterpState &S, CodePtr OpPC, const T &Arg)
bool GE(InterpState &S, CodePtr OpPC)
bool CmpHelperEQ< Pointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
bool CmpHelper(InterpState &S, CodePtr OpPC, CompareFn Fn)
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t I)
bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D)
bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
bool CheckShift(InterpState &S, CodePtr OpPC, const RT &RHS, unsigned Bits)
Checks if the shift operation is legal.
bool CmpHelper< Pointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a method can be invoked on an object.
bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off)
bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, const Pointer &Ptr)
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
@ Result
The result type of a method or function.
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
Mapping from primitive types to their representation.
Describes a record field.