1a7dea167SDimitry Andric //===--- ByteCodeExprGen.cpp - Code generator for expressions ---*- C++ -*-===// 2a7dea167SDimitry Andric // 3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric 9a7dea167SDimitry Andric #include "ByteCodeExprGen.h" 10a7dea167SDimitry Andric #include "ByteCodeEmitter.h" 11a7dea167SDimitry Andric #include "ByteCodeGenError.h" 12a7dea167SDimitry Andric #include "Context.h" 13a7dea167SDimitry Andric #include "Function.h" 14a7dea167SDimitry Andric #include "PrimType.h" 15a7dea167SDimitry Andric #include "Program.h" 16a7dea167SDimitry Andric #include "State.h" 17a7dea167SDimitry Andric 18a7dea167SDimitry Andric using namespace clang; 19a7dea167SDimitry Andric using namespace clang::interp; 20a7dea167SDimitry Andric 21a7dea167SDimitry Andric using APSInt = llvm::APSInt; 22a7dea167SDimitry Andric template <typename T> using Expected = llvm::Expected<T>; 23a7dea167SDimitry Andric template <typename T> using Optional = llvm::Optional<T>; 24a7dea167SDimitry Andric 25a7dea167SDimitry Andric namespace clang { 26a7dea167SDimitry Andric namespace interp { 27a7dea167SDimitry Andric 28a7dea167SDimitry Andric /// Scope used to handle temporaries in toplevel variable declarations. 29a7dea167SDimitry Andric template <class Emitter> class DeclScope final : public LocalScope<Emitter> { 30a7dea167SDimitry Andric public: 31a7dea167SDimitry Andric DeclScope(ByteCodeExprGen<Emitter> *Ctx, const VarDecl *VD) 32a7dea167SDimitry Andric : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {} 33a7dea167SDimitry Andric 34a7dea167SDimitry Andric void addExtended(const Scope::Local &Local) override { 35a7dea167SDimitry Andric return this->addLocal(Local); 36a7dea167SDimitry Andric } 37a7dea167SDimitry Andric 38a7dea167SDimitry Andric private: 39a7dea167SDimitry Andric Program::DeclScope Scope; 40a7dea167SDimitry Andric }; 41a7dea167SDimitry Andric 42a7dea167SDimitry Andric /// Scope used to handle initialization methods. 43a7dea167SDimitry Andric template <class Emitter> class OptionScope { 44a7dea167SDimitry Andric public: 45a7dea167SDimitry Andric using InitFnRef = typename ByteCodeExprGen<Emitter>::InitFnRef; 46a7dea167SDimitry Andric using ChainedInitFnRef = std::function<bool(InitFnRef)>; 47a7dea167SDimitry Andric 48a7dea167SDimitry Andric /// Root constructor, compiling or discarding primitives. 49a7dea167SDimitry Andric OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult) 50a7dea167SDimitry Andric : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult), 51a7dea167SDimitry Andric OldInitFn(std::move(Ctx->InitFn)) { 52a7dea167SDimitry Andric Ctx->DiscardResult = NewDiscardResult; 53a7dea167SDimitry Andric Ctx->InitFn = llvm::Optional<InitFnRef>{}; 54a7dea167SDimitry Andric } 55a7dea167SDimitry Andric 56a7dea167SDimitry Andric /// Root constructor, setting up compilation state. 57a7dea167SDimitry Andric OptionScope(ByteCodeExprGen<Emitter> *Ctx, InitFnRef NewInitFn) 58a7dea167SDimitry Andric : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult), 59a7dea167SDimitry Andric OldInitFn(std::move(Ctx->InitFn)) { 60a7dea167SDimitry Andric Ctx->DiscardResult = true; 61a7dea167SDimitry Andric Ctx->InitFn = NewInitFn; 62a7dea167SDimitry Andric } 63a7dea167SDimitry Andric 64a7dea167SDimitry Andric /// Extends the chain of initialisation pointers. 65a7dea167SDimitry Andric OptionScope(ByteCodeExprGen<Emitter> *Ctx, ChainedInitFnRef NewInitFn) 66a7dea167SDimitry Andric : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult), 67a7dea167SDimitry Andric OldInitFn(std::move(Ctx->InitFn)) { 68a7dea167SDimitry Andric assert(OldInitFn && "missing initializer"); 69a7dea167SDimitry Andric Ctx->InitFn = [this, NewInitFn] { return NewInitFn(*OldInitFn); }; 70a7dea167SDimitry Andric } 71a7dea167SDimitry Andric 72a7dea167SDimitry Andric ~OptionScope() { 73a7dea167SDimitry Andric Ctx->DiscardResult = OldDiscardResult; 74a7dea167SDimitry Andric Ctx->InitFn = std::move(OldInitFn); 75a7dea167SDimitry Andric } 76a7dea167SDimitry Andric 77a7dea167SDimitry Andric private: 78a7dea167SDimitry Andric /// Parent context. 79a7dea167SDimitry Andric ByteCodeExprGen<Emitter> *Ctx; 80a7dea167SDimitry Andric /// Old discard flag to restore. 81a7dea167SDimitry Andric bool OldDiscardResult; 82a7dea167SDimitry Andric /// Old pointer emitter to restore. 83a7dea167SDimitry Andric llvm::Optional<InitFnRef> OldInitFn; 84a7dea167SDimitry Andric }; 85a7dea167SDimitry Andric 86a7dea167SDimitry Andric } // namespace interp 87a7dea167SDimitry Andric } // namespace clang 88a7dea167SDimitry Andric 89a7dea167SDimitry Andric template <class Emitter> 90a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) { 91a7dea167SDimitry Andric auto *SubExpr = CE->getSubExpr(); 92a7dea167SDimitry Andric switch (CE->getCastKind()) { 93a7dea167SDimitry Andric 94a7dea167SDimitry Andric case CK_LValueToRValue: { 95a7dea167SDimitry Andric return dereference( 96a7dea167SDimitry Andric CE->getSubExpr(), DerefKind::Read, 97a7dea167SDimitry Andric [](PrimType) { 98a7dea167SDimitry Andric // Value loaded - nothing to do here. 99a7dea167SDimitry Andric return true; 100a7dea167SDimitry Andric }, 101a7dea167SDimitry Andric [this, CE](PrimType T) { 102a7dea167SDimitry Andric // Pointer on stack - dereference it. 103a7dea167SDimitry Andric if (!this->emitLoadPop(T, CE)) 104a7dea167SDimitry Andric return false; 105a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, CE) : true; 106a7dea167SDimitry Andric }); 107a7dea167SDimitry Andric } 108a7dea167SDimitry Andric 109a7dea167SDimitry Andric case CK_ArrayToPointerDecay: 110a7dea167SDimitry Andric case CK_AtomicToNonAtomic: 111a7dea167SDimitry Andric case CK_ConstructorConversion: 112a7dea167SDimitry Andric case CK_FunctionToPointerDecay: 113a7dea167SDimitry Andric case CK_NonAtomicToAtomic: 114a7dea167SDimitry Andric case CK_NoOp: 115a7dea167SDimitry Andric case CK_UserDefinedConversion: 116a7dea167SDimitry Andric return this->Visit(SubExpr); 117a7dea167SDimitry Andric 118a7dea167SDimitry Andric case CK_ToVoid: 119a7dea167SDimitry Andric return discard(SubExpr); 120a7dea167SDimitry Andric 121a7dea167SDimitry Andric default: { 122a7dea167SDimitry Andric // TODO: implement other casts. 123a7dea167SDimitry Andric return this->bail(CE); 124a7dea167SDimitry Andric } 125a7dea167SDimitry Andric } 126a7dea167SDimitry Andric } 127a7dea167SDimitry Andric 128a7dea167SDimitry Andric template <class Emitter> 129a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) { 130a7dea167SDimitry Andric if (DiscardResult) 131a7dea167SDimitry Andric return true; 132a7dea167SDimitry Andric 133a7dea167SDimitry Andric auto Val = LE->getValue(); 134a7dea167SDimitry Andric QualType LitTy = LE->getType(); 135a7dea167SDimitry Andric if (Optional<PrimType> T = classify(LitTy)) 136a7dea167SDimitry Andric return emitConst(*T, getIntWidth(LitTy), LE->getValue(), LE); 137a7dea167SDimitry Andric return this->bail(LE); 138a7dea167SDimitry Andric } 139a7dea167SDimitry Andric 140a7dea167SDimitry Andric template <class Emitter> 141a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) { 142a7dea167SDimitry Andric return this->Visit(PE->getSubExpr()); 143a7dea167SDimitry Andric } 144a7dea167SDimitry Andric 145a7dea167SDimitry Andric template <class Emitter> 146a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) { 147a7dea167SDimitry Andric const Expr *LHS = BO->getLHS(); 148a7dea167SDimitry Andric const Expr *RHS = BO->getRHS(); 149a7dea167SDimitry Andric 150a7dea167SDimitry Andric // Deal with operations which have composite or void types. 151a7dea167SDimitry Andric switch (BO->getOpcode()) { 152a7dea167SDimitry Andric case BO_Comma: 153a7dea167SDimitry Andric if (!discard(LHS)) 154a7dea167SDimitry Andric return false; 155a7dea167SDimitry Andric if (!this->Visit(RHS)) 156a7dea167SDimitry Andric return false; 157a7dea167SDimitry Andric return true; 158a7dea167SDimitry Andric default: 159a7dea167SDimitry Andric break; 160a7dea167SDimitry Andric } 161a7dea167SDimitry Andric 162a7dea167SDimitry Andric // Typecheck the args. 163a7dea167SDimitry Andric Optional<PrimType> LT = classify(LHS->getType()); 164a7dea167SDimitry Andric Optional<PrimType> RT = classify(RHS->getType()); 165a7dea167SDimitry Andric if (!LT || !RT) { 166a7dea167SDimitry Andric return this->bail(BO); 167a7dea167SDimitry Andric } 168a7dea167SDimitry Andric 169a7dea167SDimitry Andric if (Optional<PrimType> T = classify(BO->getType())) { 170a7dea167SDimitry Andric if (!visit(LHS)) 171a7dea167SDimitry Andric return false; 172a7dea167SDimitry Andric if (!visit(RHS)) 173a7dea167SDimitry Andric return false; 174a7dea167SDimitry Andric 175a7dea167SDimitry Andric auto Discard = [this, T, BO](bool Result) { 176a7dea167SDimitry Andric if (!Result) 177a7dea167SDimitry Andric return false; 178a7dea167SDimitry Andric return DiscardResult ? this->emitPop(*T, BO) : true; 179a7dea167SDimitry Andric }; 180a7dea167SDimitry Andric 181a7dea167SDimitry Andric switch (BO->getOpcode()) { 182a7dea167SDimitry Andric case BO_EQ: 183a7dea167SDimitry Andric return Discard(this->emitEQ(*LT, BO)); 184a7dea167SDimitry Andric case BO_NE: 185a7dea167SDimitry Andric return Discard(this->emitNE(*LT, BO)); 186a7dea167SDimitry Andric case BO_LT: 187a7dea167SDimitry Andric return Discard(this->emitLT(*LT, BO)); 188a7dea167SDimitry Andric case BO_LE: 189a7dea167SDimitry Andric return Discard(this->emitLE(*LT, BO)); 190a7dea167SDimitry Andric case BO_GT: 191a7dea167SDimitry Andric return Discard(this->emitGT(*LT, BO)); 192a7dea167SDimitry Andric case BO_GE: 193a7dea167SDimitry Andric return Discard(this->emitGE(*LT, BO)); 194a7dea167SDimitry Andric case BO_Sub: 195a7dea167SDimitry Andric return Discard(this->emitSub(*T, BO)); 196a7dea167SDimitry Andric case BO_Add: 197a7dea167SDimitry Andric return Discard(this->emitAdd(*T, BO)); 198a7dea167SDimitry Andric case BO_Mul: 199a7dea167SDimitry Andric return Discard(this->emitMul(*T, BO)); 200a7dea167SDimitry Andric default: 201a7dea167SDimitry Andric return this->bail(BO); 202a7dea167SDimitry Andric } 203a7dea167SDimitry Andric } 204a7dea167SDimitry Andric 205a7dea167SDimitry Andric return this->bail(BO); 206a7dea167SDimitry Andric } 207a7dea167SDimitry Andric 208a7dea167SDimitry Andric template <class Emitter> 209a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::discard(const Expr *E) { 21004eeddc0SDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true); 211a7dea167SDimitry Andric return this->Visit(E); 212a7dea167SDimitry Andric } 213a7dea167SDimitry Andric 214a7dea167SDimitry Andric template <class Emitter> 215a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visit(const Expr *E) { 21604eeddc0SDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false); 217a7dea167SDimitry Andric return this->Visit(E); 218a7dea167SDimitry Andric } 219a7dea167SDimitry Andric 220a7dea167SDimitry Andric template <class Emitter> 221a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) { 222a7dea167SDimitry Andric if (Optional<PrimType> T = classify(E->getType())) { 223a7dea167SDimitry Andric return visit(E); 224a7dea167SDimitry Andric } else { 225a7dea167SDimitry Andric return this->bail(E); 226a7dea167SDimitry Andric } 227a7dea167SDimitry Andric } 228a7dea167SDimitry Andric 229a7dea167SDimitry Andric template <class Emitter> 230a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, const Expr *E) { 231a7dea167SDimitry Andric switch (T) { 232a7dea167SDimitry Andric case PT_Bool: 233a7dea167SDimitry Andric return this->emitZeroBool(E); 234a7dea167SDimitry Andric case PT_Sint8: 235a7dea167SDimitry Andric return this->emitZeroSint8(E); 236a7dea167SDimitry Andric case PT_Uint8: 237a7dea167SDimitry Andric return this->emitZeroUint8(E); 238a7dea167SDimitry Andric case PT_Sint16: 239a7dea167SDimitry Andric return this->emitZeroSint16(E); 240a7dea167SDimitry Andric case PT_Uint16: 241a7dea167SDimitry Andric return this->emitZeroUint16(E); 242a7dea167SDimitry Andric case PT_Sint32: 243a7dea167SDimitry Andric return this->emitZeroSint32(E); 244a7dea167SDimitry Andric case PT_Uint32: 245a7dea167SDimitry Andric return this->emitZeroUint32(E); 246a7dea167SDimitry Andric case PT_Sint64: 247a7dea167SDimitry Andric return this->emitZeroSint64(E); 248a7dea167SDimitry Andric case PT_Uint64: 249a7dea167SDimitry Andric return this->emitZeroUint64(E); 250a7dea167SDimitry Andric case PT_Ptr: 251a7dea167SDimitry Andric return this->emitNullPtr(E); 252a7dea167SDimitry Andric } 253a7dea167SDimitry Andric llvm_unreachable("unknown primitive type"); 254a7dea167SDimitry Andric } 255a7dea167SDimitry Andric 256a7dea167SDimitry Andric template <class Emitter> 257a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereference( 258a7dea167SDimitry Andric const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct, 259a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 260a7dea167SDimitry Andric if (Optional<PrimType> T = classify(LV->getType())) { 261a7dea167SDimitry Andric if (!LV->refersToBitField()) { 262a7dea167SDimitry Andric // Only primitive, non bit-field types can be dereferenced directly. 263a7dea167SDimitry Andric if (auto *DE = dyn_cast<DeclRefExpr>(LV)) { 264a7dea167SDimitry Andric if (!DE->getDecl()->getType()->isReferenceType()) { 265a7dea167SDimitry Andric if (auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl())) 266a7dea167SDimitry Andric return dereferenceParam(LV, *T, PD, AK, Direct, Indirect); 267a7dea167SDimitry Andric if (auto *VD = dyn_cast<VarDecl>(DE->getDecl())) 268a7dea167SDimitry Andric return dereferenceVar(LV, *T, VD, AK, Direct, Indirect); 269a7dea167SDimitry Andric } 270a7dea167SDimitry Andric } 271a7dea167SDimitry Andric } 272a7dea167SDimitry Andric 273a7dea167SDimitry Andric if (!visit(LV)) 274a7dea167SDimitry Andric return false; 275a7dea167SDimitry Andric return Indirect(*T); 276a7dea167SDimitry Andric } 277a7dea167SDimitry Andric 278a7dea167SDimitry Andric return false; 279a7dea167SDimitry Andric } 280a7dea167SDimitry Andric 281a7dea167SDimitry Andric template <class Emitter> 282a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceParam( 283a7dea167SDimitry Andric const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK, 284a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Direct, 285a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 286a7dea167SDimitry Andric auto It = this->Params.find(PD); 287a7dea167SDimitry Andric if (It != this->Params.end()) { 288a7dea167SDimitry Andric unsigned Idx = It->second; 289a7dea167SDimitry Andric switch (AK) { 290a7dea167SDimitry Andric case DerefKind::Read: 291a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetParam(T, Idx, LV); 292a7dea167SDimitry Andric 293a7dea167SDimitry Andric case DerefKind::Write: 294a7dea167SDimitry Andric if (!Direct(T)) 295a7dea167SDimitry Andric return false; 296a7dea167SDimitry Andric if (!this->emitSetParam(T, Idx, LV)) 297a7dea167SDimitry Andric return false; 298a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 299a7dea167SDimitry Andric 300a7dea167SDimitry Andric case DerefKind::ReadWrite: 301a7dea167SDimitry Andric if (!this->emitGetParam(T, Idx, LV)) 302a7dea167SDimitry Andric return false; 303a7dea167SDimitry Andric if (!Direct(T)) 304a7dea167SDimitry Andric return false; 305a7dea167SDimitry Andric if (!this->emitSetParam(T, Idx, LV)) 306a7dea167SDimitry Andric return false; 307a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 308a7dea167SDimitry Andric } 309a7dea167SDimitry Andric return true; 310a7dea167SDimitry Andric } 311a7dea167SDimitry Andric 312a7dea167SDimitry Andric // If the param is a pointer, we can dereference a dummy value. 313a7dea167SDimitry Andric if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) { 314a7dea167SDimitry Andric if (auto Idx = P.getOrCreateDummy(PD)) 315a7dea167SDimitry Andric return this->emitGetPtrGlobal(*Idx, PD); 316a7dea167SDimitry Andric return false; 317a7dea167SDimitry Andric } 318a7dea167SDimitry Andric 319a7dea167SDimitry Andric // Value cannot be produced - try to emit pointer and do stuff with it. 320a7dea167SDimitry Andric return visit(LV) && Indirect(T); 321a7dea167SDimitry Andric } 322a7dea167SDimitry Andric 323a7dea167SDimitry Andric template <class Emitter> 324a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceVar( 325a7dea167SDimitry Andric const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK, 326a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Direct, 327a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 328a7dea167SDimitry Andric auto It = Locals.find(VD); 329a7dea167SDimitry Andric if (It != Locals.end()) { 330a7dea167SDimitry Andric const auto &L = It->second; 331a7dea167SDimitry Andric switch (AK) { 332a7dea167SDimitry Andric case DerefKind::Read: 333a7dea167SDimitry Andric if (!this->emitGetLocal(T, L.Offset, LV)) 334a7dea167SDimitry Andric return false; 335a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, LV) : true; 336a7dea167SDimitry Andric 337a7dea167SDimitry Andric case DerefKind::Write: 338a7dea167SDimitry Andric if (!Direct(T)) 339a7dea167SDimitry Andric return false; 340a7dea167SDimitry Andric if (!this->emitSetLocal(T, L.Offset, LV)) 341a7dea167SDimitry Andric return false; 342a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 343a7dea167SDimitry Andric 344a7dea167SDimitry Andric case DerefKind::ReadWrite: 345a7dea167SDimitry Andric if (!this->emitGetLocal(T, L.Offset, LV)) 346a7dea167SDimitry Andric return false; 347a7dea167SDimitry Andric if (!Direct(T)) 348a7dea167SDimitry Andric return false; 349a7dea167SDimitry Andric if (!this->emitSetLocal(T, L.Offset, LV)) 350a7dea167SDimitry Andric return false; 351a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 352a7dea167SDimitry Andric } 353a7dea167SDimitry Andric } else if (auto Idx = getGlobalIdx(VD)) { 354a7dea167SDimitry Andric switch (AK) { 355a7dea167SDimitry Andric case DerefKind::Read: 356a7dea167SDimitry Andric if (!this->emitGetGlobal(T, *Idx, LV)) 357a7dea167SDimitry Andric return false; 358a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, LV) : true; 359a7dea167SDimitry Andric 360a7dea167SDimitry Andric case DerefKind::Write: 361a7dea167SDimitry Andric if (!Direct(T)) 362a7dea167SDimitry Andric return false; 363a7dea167SDimitry Andric if (!this->emitSetGlobal(T, *Idx, LV)) 364a7dea167SDimitry Andric return false; 365a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 366a7dea167SDimitry Andric 367a7dea167SDimitry Andric case DerefKind::ReadWrite: 368a7dea167SDimitry Andric if (!this->emitGetGlobal(T, *Idx, LV)) 369a7dea167SDimitry Andric return false; 370a7dea167SDimitry Andric if (!Direct(T)) 371a7dea167SDimitry Andric return false; 372a7dea167SDimitry Andric if (!this->emitSetGlobal(T, *Idx, LV)) 373a7dea167SDimitry Andric return false; 374a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 375a7dea167SDimitry Andric } 376a7dea167SDimitry Andric } 377a7dea167SDimitry Andric 378a7dea167SDimitry Andric // If the declaration is a constant value, emit it here even 379a7dea167SDimitry Andric // though the declaration was not evaluated in the current scope. 380a7dea167SDimitry Andric // The access mode can only be read in this case. 381a7dea167SDimitry Andric if (!DiscardResult && AK == DerefKind::Read) { 382a7dea167SDimitry Andric if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) { 383a7dea167SDimitry Andric QualType VT = VD->getType(); 384a7dea167SDimitry Andric if (VT.isConstQualified() && VT->isFundamentalType()) 385a7dea167SDimitry Andric return this->Visit(VD->getInit()); 386a7dea167SDimitry Andric } 387a7dea167SDimitry Andric } 388a7dea167SDimitry Andric 389a7dea167SDimitry Andric // Value cannot be produced - try to emit pointer. 390a7dea167SDimitry Andric return visit(LV) && Indirect(T); 391a7dea167SDimitry Andric } 392a7dea167SDimitry Andric 393a7dea167SDimitry Andric template <class Emitter> 394a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(PrimType T, unsigned NumBits, 395a7dea167SDimitry Andric const APInt &Value, const Expr *E) { 396a7dea167SDimitry Andric switch (T) { 397a7dea167SDimitry Andric case PT_Sint8: 398a7dea167SDimitry Andric return this->emitConstSint8(Value.getSExtValue(), E); 399a7dea167SDimitry Andric case PT_Uint8: 400a7dea167SDimitry Andric return this->emitConstUint8(Value.getZExtValue(), E); 401a7dea167SDimitry Andric case PT_Sint16: 402a7dea167SDimitry Andric return this->emitConstSint16(Value.getSExtValue(), E); 403a7dea167SDimitry Andric case PT_Uint16: 404a7dea167SDimitry Andric return this->emitConstUint16(Value.getZExtValue(), E); 405a7dea167SDimitry Andric case PT_Sint32: 406a7dea167SDimitry Andric return this->emitConstSint32(Value.getSExtValue(), E); 407a7dea167SDimitry Andric case PT_Uint32: 408a7dea167SDimitry Andric return this->emitConstUint32(Value.getZExtValue(), E); 409a7dea167SDimitry Andric case PT_Sint64: 410a7dea167SDimitry Andric return this->emitConstSint64(Value.getSExtValue(), E); 411a7dea167SDimitry Andric case PT_Uint64: 412a7dea167SDimitry Andric return this->emitConstUint64(Value.getZExtValue(), E); 413a7dea167SDimitry Andric case PT_Bool: 414a7dea167SDimitry Andric return this->emitConstBool(Value.getBoolValue(), E); 415a7dea167SDimitry Andric case PT_Ptr: 416a7dea167SDimitry Andric llvm_unreachable("Invalid integral type"); 417a7dea167SDimitry Andric break; 418a7dea167SDimitry Andric } 419a7dea167SDimitry Andric llvm_unreachable("unknown primitive type"); 420a7dea167SDimitry Andric } 421a7dea167SDimitry Andric 422a7dea167SDimitry Andric template <class Emitter> 423a7dea167SDimitry Andric unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src, 424a7dea167SDimitry Andric PrimType Ty, 425a7dea167SDimitry Andric bool IsConst, 426a7dea167SDimitry Andric bool IsExtended) { 427a7dea167SDimitry Andric Descriptor *D = P.createDescriptor(Src, Ty, IsConst, Src.is<const Expr *>()); 428a7dea167SDimitry Andric Scope::Local Local = this->createLocal(D); 429a7dea167SDimitry Andric if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>())) 430a7dea167SDimitry Andric Locals.insert({VD, Local}); 431a7dea167SDimitry Andric VarScope->add(Local, IsExtended); 432a7dea167SDimitry Andric return Local.Offset; 433a7dea167SDimitry Andric } 434a7dea167SDimitry Andric 435a7dea167SDimitry Andric template <class Emitter> 436a7dea167SDimitry Andric llvm::Optional<unsigned> 437a7dea167SDimitry Andric ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) { 438a7dea167SDimitry Andric QualType Ty; 439a7dea167SDimitry Andric 440a7dea167SDimitry Andric const ValueDecl *Key = nullptr; 441a7dea167SDimitry Andric bool IsTemporary = false; 442a7dea167SDimitry Andric if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>())) { 443a7dea167SDimitry Andric Key = VD; 444a7dea167SDimitry Andric Ty = VD->getType(); 445a7dea167SDimitry Andric } 446a7dea167SDimitry Andric if (auto *E = Src.dyn_cast<const Expr *>()) { 447a7dea167SDimitry Andric IsTemporary = true; 448a7dea167SDimitry Andric Ty = E->getType(); 449a7dea167SDimitry Andric } 450a7dea167SDimitry Andric 451a7dea167SDimitry Andric Descriptor *D = P.createDescriptor(Src, Ty.getTypePtr(), 452a7dea167SDimitry Andric Ty.isConstQualified(), IsTemporary); 453a7dea167SDimitry Andric if (!D) 454a7dea167SDimitry Andric return {}; 455a7dea167SDimitry Andric 456a7dea167SDimitry Andric Scope::Local Local = this->createLocal(D); 457a7dea167SDimitry Andric if (Key) 458a7dea167SDimitry Andric Locals.insert({Key, Local}); 459a7dea167SDimitry Andric VarScope->add(Local, IsExtended); 460a7dea167SDimitry Andric return Local.Offset; 461a7dea167SDimitry Andric } 462a7dea167SDimitry Andric 463a7dea167SDimitry Andric template <class Emitter> 464a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitInitializer( 465a7dea167SDimitry Andric const Expr *Init, InitFnRef InitFn) { 466a7dea167SDimitry Andric OptionScope<Emitter> Scope(this, InitFn); 467a7dea167SDimitry Andric return this->Visit(Init); 468a7dea167SDimitry Andric } 469a7dea167SDimitry Andric 470a7dea167SDimitry Andric template <class Emitter> 471a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::getPtrVarDecl(const VarDecl *VD, const Expr *E) { 472a7dea167SDimitry Andric // Generate a pointer to the local, loading refs. 473a7dea167SDimitry Andric if (Optional<unsigned> Idx = getGlobalIdx(VD)) { 474a7dea167SDimitry Andric if (VD->getType()->isReferenceType()) 475a7dea167SDimitry Andric return this->emitGetGlobalPtr(*Idx, E); 476a7dea167SDimitry Andric else 477a7dea167SDimitry Andric return this->emitGetPtrGlobal(*Idx, E); 478a7dea167SDimitry Andric } 479a7dea167SDimitry Andric return this->bail(VD); 480a7dea167SDimitry Andric } 481a7dea167SDimitry Andric 482a7dea167SDimitry Andric template <class Emitter> 483a7dea167SDimitry Andric llvm::Optional<unsigned> 484a7dea167SDimitry Andric ByteCodeExprGen<Emitter>::getGlobalIdx(const VarDecl *VD) { 485a7dea167SDimitry Andric if (VD->isConstexpr()) { 486a7dea167SDimitry Andric // Constexpr decl - it must have already been defined. 487a7dea167SDimitry Andric return P.getGlobal(VD); 488a7dea167SDimitry Andric } 489a7dea167SDimitry Andric if (!VD->hasLocalStorage()) { 490a7dea167SDimitry Andric // Not constexpr, but a global var - can have pointer taken. 491a7dea167SDimitry Andric Program::DeclScope Scope(P, VD); 492a7dea167SDimitry Andric return P.getOrCreateGlobal(VD); 493a7dea167SDimitry Andric } 494a7dea167SDimitry Andric return {}; 495a7dea167SDimitry Andric } 496a7dea167SDimitry Andric 497a7dea167SDimitry Andric template <class Emitter> 498a7dea167SDimitry Andric const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) { 499753f127fSDimitry Andric if (const PointerType *PT = dyn_cast<PointerType>(Ty)) 500a7dea167SDimitry Andric return PT->getPointeeType()->getAs<RecordType>(); 501a7dea167SDimitry Andric else 502a7dea167SDimitry Andric return Ty->getAs<RecordType>(); 503a7dea167SDimitry Andric } 504a7dea167SDimitry Andric 505a7dea167SDimitry Andric template <class Emitter> 506a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) { 507a7dea167SDimitry Andric if (auto *RecordTy = getRecordTy(Ty)) { 508a7dea167SDimitry Andric return getRecord(RecordTy->getDecl()); 509a7dea167SDimitry Andric } 510a7dea167SDimitry Andric return nullptr; 511a7dea167SDimitry Andric } 512a7dea167SDimitry Andric 513a7dea167SDimitry Andric template <class Emitter> 514a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) { 515a7dea167SDimitry Andric return P.getOrCreateRecord(RD); 516a7dea167SDimitry Andric } 517a7dea167SDimitry Andric 518a7dea167SDimitry Andric template <class Emitter> 519a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *Exp) { 520a7dea167SDimitry Andric ExprScope<Emitter> RootScope(this); 521a7dea167SDimitry Andric if (!visit(Exp)) 522a7dea167SDimitry Andric return false; 523a7dea167SDimitry Andric 524a7dea167SDimitry Andric if (Optional<PrimType> T = classify(Exp)) 525a7dea167SDimitry Andric return this->emitRet(*T, Exp); 526a7dea167SDimitry Andric else 527a7dea167SDimitry Andric return this->emitRetValue(Exp); 528a7dea167SDimitry Andric } 529a7dea167SDimitry Andric 530a7dea167SDimitry Andric template <class Emitter> 531a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) { 532a7dea167SDimitry Andric const Expr *Init = VD->getInit(); 533a7dea167SDimitry Andric 534a7dea167SDimitry Andric if (Optional<unsigned> I = P.createGlobal(VD)) { 535a7dea167SDimitry Andric if (Optional<PrimType> T = classify(VD->getType())) { 536a7dea167SDimitry Andric { 537a7dea167SDimitry Andric // Primitive declarations - compute the value and set it. 538a7dea167SDimitry Andric DeclScope<Emitter> LocalScope(this, VD); 539a7dea167SDimitry Andric if (!visit(Init)) 540a7dea167SDimitry Andric return false; 541a7dea167SDimitry Andric } 542a7dea167SDimitry Andric 543a7dea167SDimitry Andric // If the declaration is global, save the value for later use. 544a7dea167SDimitry Andric if (!this->emitDup(*T, VD)) 545a7dea167SDimitry Andric return false; 546a7dea167SDimitry Andric if (!this->emitInitGlobal(*T, *I, VD)) 547a7dea167SDimitry Andric return false; 548a7dea167SDimitry Andric return this->emitRet(*T, VD); 549a7dea167SDimitry Andric } else { 550a7dea167SDimitry Andric { 551a7dea167SDimitry Andric // Composite declarations - allocate storage and initialize it. 552a7dea167SDimitry Andric DeclScope<Emitter> LocalScope(this, VD); 553a7dea167SDimitry Andric if (!visitGlobalInitializer(Init, *I)) 554a7dea167SDimitry Andric return false; 555a7dea167SDimitry Andric } 556a7dea167SDimitry Andric 557a7dea167SDimitry Andric // Return a pointer to the global. 558a7dea167SDimitry Andric if (!this->emitGetPtrGlobal(*I, VD)) 559a7dea167SDimitry Andric return false; 560a7dea167SDimitry Andric return this->emitRetValue(VD); 561a7dea167SDimitry Andric } 562a7dea167SDimitry Andric } 563a7dea167SDimitry Andric 564a7dea167SDimitry Andric return this->bail(VD); 565a7dea167SDimitry Andric } 566a7dea167SDimitry Andric 567a7dea167SDimitry Andric template <class Emitter> 568a7dea167SDimitry Andric void ByteCodeExprGen<Emitter>::emitCleanup() { 569a7dea167SDimitry Andric for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent()) 570a7dea167SDimitry Andric C->emitDestruction(); 571a7dea167SDimitry Andric } 572a7dea167SDimitry Andric 573a7dea167SDimitry Andric namespace clang { 574a7dea167SDimitry Andric namespace interp { 575a7dea167SDimitry Andric 576a7dea167SDimitry Andric template class ByteCodeExprGen<ByteCodeEmitter>; 577a7dea167SDimitry Andric template class ByteCodeExprGen<EvalEmitter>; 578a7dea167SDimitry Andric 579a7dea167SDimitry Andric } // namespace interp 580a7dea167SDimitry Andric } // namespace clang 581