18 using namespace clang;
35 return this->addLocal(Local);
50 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
51 OldInitFn(
std::move(Ctx->InitFn)) {
58 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
59 OldInitFn(
std::move(Ctx->InitFn)) {
66 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
67 OldInitFn(
std::move(Ctx->InitFn)) {
68 assert(OldInitFn &&
"missing initializer");
69 Ctx->
InitFn = [
this, NewInitFn] {
return NewInitFn(*OldInitFn); };
73 Ctx->DiscardResult = OldDiscardResult;
74 Ctx->InitFn = std::move(OldInitFn);
81 bool OldDiscardResult;
89 template <
class Emitter>
94 case CK_LValueToRValue: {
103 if (!this->emitLoadPop(T, CE))
105 return DiscardResult ? this->emitPop(T, CE) :
true;
109 case CK_ArrayToPointerDecay:
110 case CK_AtomicToNonAtomic:
111 case CK_ConstructorConversion:
112 case CK_FunctionToPointerDecay:
113 case CK_NonAtomicToAtomic:
115 case CK_UserDefinedConversion:
116 return this->Visit(SubExpr);
119 return discard(SubExpr);
123 return this->bail(CE);
128 template <
class Emitter>
136 return emitConst(*T, getIntWidth(LitTy), LE->
getValue(),
LE);
137 return this->bail(LE);
140 template <
class Emitter>
145 template <
class Emitter>
155 if (!this->Visit(RHS))
166 return this->bail(BO);
175 auto Discard = [
this, T, BO](
bool Result) {
178 return DiscardResult ? this->emitPop(*T, BO) :
true;
183 return Discard(this->emitEQ(*LT, BO));
185 return Discard(this->emitNE(*LT, BO));
187 return Discard(this->emitLT(*LT, BO));
189 return Discard(this->emitLE(*LT, BO));
191 return Discard(this->emitGT(*LT, BO));
193 return Discard(this->emitGE(*LT, BO));
195 return Discard(this->emitSub(*T, BO));
197 return Discard(this->emitAdd(*T, BO));
199 return Discard(this->emitMul(*T, BO));
201 return this->bail(BO);
205 return this->bail(BO);
208 template <
class Emitter>
211 return this->Visit(E);
214 template <
class Emitter>
217 return this->Visit(E);
220 template <
class Emitter>
225 return this->bail(E);
229 template <
class Emitter>
233 return this->emitZeroBool(E);
235 return this->emitZeroSint8(E);
237 return this->emitZeroUint8(E);
239 return this->emitZeroSint16(E);
241 return this->emitZeroUint16(E);
243 return this->emitZeroSint32(E);
245 return this->emitZeroUint32(E);
247 return this->emitZeroSint64(E);
249 return this->emitZeroUint64(E);
251 return this->emitNullPtr(E);
253 llvm_unreachable(
"unknown primitive type");
256 template <
class Emitter>
258 const Expr *LV, DerefKind AK, llvm::function_ref<
bool(
PrimType)> Direct,
259 llvm::function_ref<
bool(
PrimType)> Indirect) {
263 if (
auto *DE = dyn_cast<DeclRefExpr>(LV)) {
264 if (!DE->getDecl()->getType()->isReferenceType()) {
265 if (
auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
266 return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
267 if (
auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
268 return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
281 template <
class Emitter>
284 llvm::function_ref<
bool(
PrimType)> Direct,
285 llvm::function_ref<
bool(
PrimType)> Indirect) {
286 auto It = this->Params.find(PD);
287 if (It != this->Params.end()) {
288 unsigned Idx = It->second;
290 case DerefKind::Read:
291 return DiscardResult ?
true : this->emitGetParam(T, Idx, LV);
293 case DerefKind::Write:
296 if (!this->emitSetParam(T, Idx, LV))
298 return DiscardResult ?
true : this->emitGetPtrParam(Idx, LV);
300 case DerefKind::ReadWrite:
301 if (!this->emitGetParam(T, Idx, LV))
305 if (!this->emitSetParam(T, Idx, LV))
307 return DiscardResult ?
true : this->emitGetPtrParam(Idx, LV);
313 if (!DiscardResult && T ==
PT_Ptr && AK == DerefKind::Read) {
314 if (
auto Idx =
P.getOrCreateDummy(PD))
315 return this->emitGetPtrGlobal(*Idx, PD);
320 return visit(LV) && Indirect(T);
323 template <
class Emitter>
326 llvm::function_ref<
bool(
PrimType)> Direct,
327 llvm::function_ref<
bool(
PrimType)> Indirect) {
328 auto It = Locals.find(VD);
329 if (It != Locals.end()) {
330 const auto &L = It->second;
332 case DerefKind::Read:
333 if (!this->emitGetLocal(T, L.Offset, LV))
335 return DiscardResult ? this->emitPop(T, LV) :
true;
337 case DerefKind::Write:
340 if (!this->emitSetLocal(T, L.Offset, LV))
342 return DiscardResult ?
true : this->emitGetPtrLocal(L.Offset, LV);
344 case DerefKind::ReadWrite:
345 if (!this->emitGetLocal(T, L.Offset, LV))
349 if (!this->emitSetLocal(T, L.Offset, LV))
351 return DiscardResult ?
true : this->emitGetPtrLocal(L.Offset, LV);
353 }
else if (
auto Idx = getGlobalIdx(VD)) {
355 case DerefKind::Read:
356 if (!this->emitGetGlobal(T, *Idx, LV))
358 return DiscardResult ? this->emitPop(T, LV) :
true;
360 case DerefKind::Write:
363 if (!this->emitSetGlobal(T, *Idx, LV))
365 return DiscardResult ?
true : this->emitGetPtrGlobal(*Idx, LV);
367 case DerefKind::ReadWrite:
368 if (!this->emitGetGlobal(T, *Idx, LV))
372 if (!this->emitSetGlobal(T, *Idx, LV))
374 return DiscardResult ?
true : this->emitGetPtrGlobal(*Idx, LV);
381 if (!DiscardResult && AK == DerefKind::Read) {
385 return this->Visit(VD->
getInit());
390 return visit(LV) && Indirect(T);
393 template <
class Emitter>
398 return this->emitConstSint8(
Value.getSExtValue(), E);
400 return this->emitConstUint8(
Value.getZExtValue(), E);
402 return this->emitConstSint16(
Value.getSExtValue(), E);
404 return this->emitConstUint16(
Value.getZExtValue(), E);
406 return this->emitConstSint32(
Value.getSExtValue(), E);
408 return this->emitConstUint32(
Value.getZExtValue(), E);
410 return this->emitConstSint64(
Value.getSExtValue(), E);
412 return this->emitConstUint64(
Value.getZExtValue(), E);
414 return this->emitConstBool(
Value.getBoolValue(), E);
416 llvm_unreachable(
"Invalid integral type");
419 llvm_unreachable(
"unknown primitive type");
422 template <
class Emitter>
427 Descriptor *D =
P.createDescriptor(Src, Ty, IsConst, Src.is<
const Expr *>());
429 if (
auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<
const Decl *>()))
430 Locals.insert({VD, Local});
431 VarScope->add(Local, IsExtended);
435 template <
class Emitter>
441 bool IsTemporary =
false;
442 if (
auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<
const Decl *>())) {
446 if (
auto *E = Src.dyn_cast<
const Expr *>()) {
458 Locals.insert({Key, Local});
459 VarScope->add(Local, IsExtended);
463 template <
class Emitter>
467 return this->Visit(Init);
470 template <
class Emitter>
475 return this->emitGetGlobalPtr(*Idx, E);
477 return this->emitGetPtrGlobal(*Idx, E);
479 return this->bail(VD);
482 template <
class Emitter>
487 return P.getGlobal(VD);
492 return P.getOrCreateGlobal(VD);
497 template <
class Emitter>
499 if (
auto *PT = dyn_cast<PointerType>(Ty))
505 template <
class Emitter>
507 if (
auto *RecordTy = getRecordTy(Ty)) {
508 return getRecord(RecordTy->getDecl());
513 template <
class Emitter>
515 return P.getOrCreateRecord(RD);
518 template <
class Emitter>
525 return this->emitRet(*T, Exp);
527 return this->emitRetValue(Exp);
530 template <
class Emitter>
544 if (!this->emitDup(*T, VD))
546 if (!this->emitInitGlobal(*T, *I, VD))
548 return this->emitRet(*T, VD);
553 if (!visitGlobalInitializer(Init, *I))
558 if (!this->emitGetPtrGlobal(*I, VD))
560 return this->emitRetValue(VD);
564 return this->bail(VD);
567 template <
class Emitter>
570 C->emitDestruction();
unsigned llvm::PointerUnion< const Decl *, const Expr * > DeclTy
Scope chain managing the variable lifetimes.
A (possibly-)qualified type.
std::function< bool(InitFnRef)> ChainedInitFnRef
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Decl - This represents one declaration (or definition), e.g.
ParenExpr - This represents a parethesized expression, e.g.
bool VisitCastExpr(const CastExpr *E)
Represents a variable declaration or definition.
bool visitInitializer(const Expr *E, InitFnRef GenPtr)
Compiles an initializer for a local.
const T * getAs() const
Member-template getAs<specific type>'.
Represents a parameter to a function.
bool VisitIntegerLiteral(const IntegerLiteral *E)
Represents a struct/union/class.
bool visitDecl(const VarDecl *VD) override
bool isReferenceType() const
static llvm::Optional< DereferenceInfo > dereference(ProgramStateRef State, const FieldRegion *FR)
Dereferences FR and returns with the pointee's region, and whether it needs to be casted back to it's...
bool visit(const Expr *E)
Evaluates an expression and places result on stack.
llvm::Optional< InitFnRef > InitFn
Expression being initialized.
Structure/Class descriptor.
typename ByteCodeExprGen< Emitter >::InitFnRef InitFnRef
bool visitBool(const Expr *E)
Visits an expression and converts it to a boolean.
bool refersToBitField() const
Returns true if this expression is a gl-value that potentially refers to a bit-field.
PrimType
Enumeration of the primitive types of the VM.
Context to manage declaration lifetimes.
A builtin binary operation expression such as "x + y" or "x <= y".
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Describes a memory block created by an allocation site.
Expression scope which tracks potentially lifetime extended temporaries which are hoisted to the pare...
bool VisitBinaryOperator(const BinaryOperator *E)
OptionScope(ByteCodeExprGen< Emitter > *Ctx, InitFnRef NewInitFn)
Root constructor, setting up compilation state.
bool discard(const Expr *E)
Evaluates an expression for side effects and discards the result.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
This represents one expression.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Information about a local's storage.
std::function< bool()> InitFnRef
void emitCleanup()
Emits scope cleanup instructions.
unsigned Offset
Offset of the local in frame.
const Expr * getSubExpr() const
OptionScope(ByteCodeExprGen< Emitter > *Ctx, ChainedInitFnRef NewInitFn)
Extends the chain of initialisation pointers.
bool isConstQualified() const
Determine whether this type is const-qualified.
CastKind getCastKind() const
void addExtended(const Scope::Local &Local) override
Record * getRecord(QualType Ty)
Returns a record from a record or pointer type.
Scope used to handle temporaries in toplevel variable declarations.
Scope used to handle initialization methods.
Dataflow Directional Tag Classes.
bool DiscardResult
Flag indicating if return value is to be discarded.
const Expr * getInit() const
DeclScope(ByteCodeExprGen< Emitter > *Ctx, const VarDecl *VD)
const RecordType * getRecordTy(QualType Ty)
Returns a record type from a record or pointer type.
bool visitExpr(const Expr *E) override
llvm::APInt getValue() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Scope for local variables.
bool VisitParenExpr(const ParenExpr *E)
Compilation context for expressions.
bool LE(InterpState &S, CodePtr OpPC)
bool isFundamentalType() const
Tests whether the type is categorized as a fundamental type.
OptionScope(ByteCodeExprGen< Emitter > *Ctx, bool NewDiscardResult)
Root constructor, compiling or discarding primitives.
llvm::Optional< unsigned > allocateLocal(DeclTy &&Decl, bool IsExtended=false)
Allocates a space storing a local given its type.
unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsMutable, bool IsExtended=false)
Creates a local primitive value.
bool LT(InterpState &S, CodePtr OpPC)