1 //===--- ByteCodeExprGen.h - Code generator for expressions -----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Defines the constexpr bytecode compiler. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H 14 #define LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H 15 16 #include "ByteCodeEmitter.h" 17 #include "EvalEmitter.h" 18 #include "Pointer.h" 19 #include "PrimType.h" 20 #include "Record.h" 21 #include "clang/AST/Decl.h" 22 #include "clang/AST/Expr.h" 23 #include "clang/AST/StmtVisitor.h" 24 #include "clang/Basic/TargetInfo.h" 25 26 namespace clang { 27 class QualType; 28 29 namespace interp { 30 31 template <class Emitter> class LocalScope; 32 template <class Emitter> class DestructorScope; 33 template <class Emitter> class RecordScope; 34 template <class Emitter> class VariableScope; 35 template <class Emitter> class DeclScope; 36 template <class Emitter> class OptionScope; 37 template <class Emitter> class ArrayIndexScope; 38 template <class Emitter> class SourceLocScope; 39 40 /// Compilation context for expressions. 41 template <class Emitter> 42 class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, 43 public Emitter { 44 protected: 45 // Aliases for types defined in the emitter. 46 using LabelTy = typename Emitter::LabelTy; 47 using AddrTy = typename Emitter::AddrTy; 48 49 /// Current compilation context. 50 Context &Ctx; 51 /// Program to link to. 52 Program &P; 53 54 public: 55 /// Initializes the compiler and the backend emitter. 56 template <typename... Tys> ByteCodeExprGen(Context & Ctx,Program & P,Tys &&...Args)57 ByteCodeExprGen(Context &Ctx, Program &P, Tys &&... Args) 58 : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {} 59 60 // Expression visitors - result returned on interp stack. 61 bool VisitCastExpr(const CastExpr *E); 62 bool VisitIntegerLiteral(const IntegerLiteral *E); 63 bool VisitFloatingLiteral(const FloatingLiteral *E); 64 bool VisitParenExpr(const ParenExpr *E); 65 bool VisitBinaryOperator(const BinaryOperator *E); 66 bool VisitLogicalBinOp(const BinaryOperator *E); 67 bool VisitPointerArithBinOp(const BinaryOperator *E); 68 bool VisitComplexBinOp(const BinaryOperator *E); 69 bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E); 70 bool VisitCallExpr(const CallExpr *E); 71 bool VisitBuiltinCallExpr(const CallExpr *E); 72 bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E); 73 bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E); 74 bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E); 75 bool VisitGNUNullExpr(const GNUNullExpr *E); 76 bool VisitCXXThisExpr(const CXXThisExpr *E); 77 bool VisitUnaryOperator(const UnaryOperator *E); 78 bool VisitDeclRefExpr(const DeclRefExpr *E); 79 bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E); 80 bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E); 81 bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); 82 bool VisitInitListExpr(const InitListExpr *E); 83 bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E); 84 bool VisitConstantExpr(const ConstantExpr *E); 85 bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E); 86 bool VisitMemberExpr(const MemberExpr *E); 87 bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E); 88 bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E); 89 bool VisitOpaqueValueExpr(const OpaqueValueExpr *E); 90 bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E); 91 bool VisitStringLiteral(const StringLiteral *E); 92 bool VisitCharacterLiteral(const CharacterLiteral *E); 93 bool VisitCompoundAssignOperator(const CompoundAssignOperator *E); 94 bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E); 95 bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E); 96 bool VisitExprWithCleanups(const ExprWithCleanups *E); 97 bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); 98 bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E); 99 bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); 100 bool VisitTypeTraitExpr(const TypeTraitExpr *E); 101 bool VisitLambdaExpr(const LambdaExpr *E); 102 bool VisitPredefinedExpr(const PredefinedExpr *E); 103 bool VisitCXXThrowExpr(const CXXThrowExpr *E); 104 bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E); 105 bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); 106 bool VisitCXXConstructExpr(const CXXConstructExpr *E); 107 bool VisitSourceLocExpr(const SourceLocExpr *E); 108 bool VisitOffsetOfExpr(const OffsetOfExpr *E); 109 bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E); 110 bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); 111 112 protected: 113 bool visitExpr(const Expr *E) override; 114 bool visitDecl(const VarDecl *VD) override; 115 116 protected: 117 /// Emits scope cleanup instructions. 118 void emitCleanup(); 119 120 /// Returns a record type from a record or pointer type. 121 const RecordType *getRecordTy(QualType Ty); 122 123 /// Returns a record from a record or pointer type. 124 Record *getRecord(QualType Ty); 125 Record *getRecord(const RecordDecl *RD); 126 127 // Returns a function for the given FunctionDecl. 128 // If the function does not exist yet, it is compiled. 129 const Function *getFunction(const FunctionDecl *FD); 130 131 /// Classifies a type. classify(const Expr * E)132 std::optional<PrimType> classify(const Expr *E) const { 133 if (E->isGLValue()) { 134 if (E->getType()->isFunctionType()) 135 return PT_FnPtr; 136 return PT_Ptr; 137 } 138 139 return classify(E->getType()); 140 } classify(QualType Ty)141 std::optional<PrimType> classify(QualType Ty) const { 142 return Ctx.classify(Ty); 143 } 144 145 /// Classifies a known primitive type classifyPrim(QualType Ty)146 PrimType classifyPrim(QualType Ty) const { 147 if (auto T = classify(Ty)) { 148 return *T; 149 } 150 llvm_unreachable("not a primitive type"); 151 } 152 /// Evaluates an expression and places the result on the stack. If the 153 /// expression is of composite type, a local variable will be created 154 /// and a pointer to said variable will be placed on the stack. 155 bool visit(const Expr *E); 156 /// Compiles an initializer. This is like visit() but it will never 157 /// create a variable and instead rely on a variable already having 158 /// been created. visitInitializer() then relies on a pointer to this 159 /// variable being on top of the stack. 160 bool visitInitializer(const Expr *E); 161 /// Evaluates an expression for side effects and discards the result. 162 bool discard(const Expr *E); 163 /// Just pass evaluation on to \p E. This leaves all the parsing flags 164 /// intact. 165 bool delegate(const Expr *E); 166 167 /// Creates and initializes a variable from the given decl. 168 bool visitVarDecl(const VarDecl *VD); 169 /// Visit an APValue. 170 bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E); 171 172 /// Visits an expression and converts it to a boolean. 173 bool visitBool(const Expr *E); 174 175 /// Visits an initializer for a local. visitLocalInitializer(const Expr * Init,unsigned I)176 bool visitLocalInitializer(const Expr *Init, unsigned I) { 177 if (!this->emitGetPtrLocal(I, Init)) 178 return false; 179 180 if (!visitInitializer(Init)) 181 return false; 182 183 return this->emitPopPtr(Init); 184 } 185 186 /// Visits an initializer for a global. visitGlobalInitializer(const Expr * Init,unsigned I)187 bool visitGlobalInitializer(const Expr *Init, unsigned I) { 188 if (!this->emitGetPtrGlobal(I, Init)) 189 return false; 190 191 if (!visitInitializer(Init)) 192 return false; 193 194 return this->emitPopPtr(Init); 195 } 196 197 /// Visits a delegated initializer. visitThisInitializer(const Expr * I)198 bool visitThisInitializer(const Expr *I) { 199 if (!this->emitThis(I)) 200 return false; 201 202 if (!visitInitializer(I)) 203 return false; 204 205 return this->emitPopPtr(I); 206 } 207 208 bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *E); 209 bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init); 210 211 /// Creates a local primitive value. 212 unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst, 213 bool IsExtended = false); 214 215 /// Allocates a space storing a local given its type. 216 std::optional<unsigned> allocateLocal(DeclTy &&Decl, bool IsExtended = false); 217 218 private: 219 friend class VariableScope<Emitter>; 220 friend class LocalScope<Emitter>; 221 friend class DestructorScope<Emitter>; 222 friend class RecordScope<Emitter>; 223 friend class DeclScope<Emitter>; 224 friend class OptionScope<Emitter>; 225 friend class ArrayIndexScope<Emitter>; 226 friend class SourceLocScope<Emitter>; 227 228 /// Emits a zero initializer. 229 bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E); 230 bool visitZeroRecordInitializer(const Record *R, const Expr *E); 231 232 enum class DerefKind { 233 /// Value is read and pushed to stack. 234 Read, 235 /// Direct method generates a value which is written. Returns pointer. 236 Write, 237 /// Direct method receives the value, pushes mutated value. Returns pointer. 238 ReadWrite, 239 }; 240 241 /// Method to directly load a value. If the value can be fetched directly, 242 /// the direct handler is called. Otherwise, a pointer is left on the stack 243 /// and the indirect handler is expected to operate on that. 244 bool dereference(const Expr *LV, DerefKind AK, 245 llvm::function_ref<bool(PrimType)> Direct, 246 llvm::function_ref<bool(PrimType)> Indirect); 247 bool dereferenceParam(const Expr *LV, PrimType T, const ParmVarDecl *PD, 248 DerefKind AK, 249 llvm::function_ref<bool(PrimType)> Direct, 250 llvm::function_ref<bool(PrimType)> Indirect); 251 bool dereferenceVar(const Expr *LV, PrimType T, const VarDecl *PD, 252 DerefKind AK, llvm::function_ref<bool(PrimType)> Direct, 253 llvm::function_ref<bool(PrimType)> Indirect); 254 255 /// Emits an APSInt constant. 256 bool emitConst(const llvm::APSInt &Value, PrimType Ty, const Expr *E); 257 bool emitConst(const llvm::APSInt &Value, const Expr *E); emitConst(const llvm::APInt & Value,const Expr * E)258 bool emitConst(const llvm::APInt &Value, const Expr *E) { 259 return emitConst(static_cast<llvm::APSInt>(Value), E); 260 } 261 262 /// Emits an integer constant. 263 template <typename T> bool emitConst(T Value, PrimType Ty, const Expr *E); 264 template <typename T> bool emitConst(T Value, const Expr *E); 265 266 /// Returns the CXXRecordDecl for the type of the given expression, 267 /// or nullptr if no such decl exists. getRecordDecl(const Expr * E)268 const CXXRecordDecl *getRecordDecl(const Expr *E) const { 269 QualType T = E->getType(); 270 if (const auto *RD = T->getPointeeCXXRecordDecl()) 271 return RD; 272 return T->getAsCXXRecordDecl(); 273 } 274 getRoundingMode(const Expr * E)275 llvm::RoundingMode getRoundingMode(const Expr *E) const { 276 FPOptions FPO = E->getFPFeaturesInEffect(Ctx.getLangOpts()); 277 278 if (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) 279 return llvm::RoundingMode::NearestTiesToEven; 280 281 return FPO.getRoundingMode(); 282 } 283 284 bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E); classifyComplexElementType(QualType T)285 std::optional<PrimType> classifyComplexElementType(QualType T) const { 286 assert(T->isAnyComplexType()); 287 288 QualType ElemType = T->getAs<ComplexType>()->getElementType(); 289 290 return this->classify(ElemType); 291 } 292 293 bool emitComplexReal(const Expr *SubExpr); 294 295 bool emitRecordDestruction(const Descriptor *Desc); 296 unsigned collectBaseOffset(const RecordType *BaseType, 297 const RecordType *DerivedType); 298 299 protected: 300 /// Variable to storage mapping. 301 llvm::DenseMap<const ValueDecl *, Scope::Local> Locals; 302 303 /// OpaqueValueExpr to location mapping. 304 llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs; 305 306 /// Current scope. 307 VariableScope<Emitter> *VarScope = nullptr; 308 309 /// Current argument index. Needed to emit ArrayInitIndexExpr. 310 std::optional<uint64_t> ArrayIndex; 311 312 /// DefaultInit- or DefaultArgExpr, needed for SourceLocExpr. 313 const Expr *SourceLocDefaultExpr = nullptr; 314 315 /// Flag indicating if return value is to be discarded. 316 bool DiscardResult = false; 317 318 /// Flag inidicating if we're initializing an already created 319 /// variable. This is set in visitInitializer(). 320 bool Initializing = false; 321 322 /// Flag indicating if we're initializing a global variable. 323 bool GlobalDecl = false; 324 }; 325 326 extern template class ByteCodeExprGen<ByteCodeEmitter>; 327 extern template class ByteCodeExprGen<EvalEmitter>; 328 329 /// Scope chain managing the variable lifetimes. 330 template <class Emitter> class VariableScope { 331 public: VariableScope(ByteCodeExprGen<Emitter> * Ctx)332 VariableScope(ByteCodeExprGen<Emitter> *Ctx) 333 : Ctx(Ctx), Parent(Ctx->VarScope) { 334 Ctx->VarScope = this; 335 } 336 ~VariableScope()337 virtual ~VariableScope() { Ctx->VarScope = this->Parent; } 338 add(const Scope::Local & Local,bool IsExtended)339 void add(const Scope::Local &Local, bool IsExtended) { 340 if (IsExtended) 341 this->addExtended(Local); 342 else 343 this->addLocal(Local); 344 } 345 addLocal(const Scope::Local & Local)346 virtual void addLocal(const Scope::Local &Local) { 347 if (this->Parent) 348 this->Parent->addLocal(Local); 349 } 350 addExtended(const Scope::Local & Local)351 virtual void addExtended(const Scope::Local &Local) { 352 if (this->Parent) 353 this->Parent->addExtended(Local); 354 } 355 emitDestruction()356 virtual void emitDestruction() {} emitDestructors()357 virtual void emitDestructors() {} getParent()358 VariableScope *getParent() const { return Parent; } 359 360 protected: 361 /// ByteCodeExprGen instance. 362 ByteCodeExprGen<Emitter> *Ctx; 363 /// Link to the parent scope. 364 VariableScope *Parent; 365 }; 366 367 /// Generic scope for local variables. 368 template <class Emitter> class LocalScope : public VariableScope<Emitter> { 369 public: LocalScope(ByteCodeExprGen<Emitter> * Ctx)370 LocalScope(ByteCodeExprGen<Emitter> *Ctx) : VariableScope<Emitter>(Ctx) {} 371 372 /// Emit a Destroy op for this scope. ~LocalScope()373 ~LocalScope() override { 374 if (!Idx) 375 return; 376 this->Ctx->emitDestroy(*Idx, SourceInfo{}); 377 } 378 379 /// Overriden to support explicit destruction. emitDestruction()380 void emitDestruction() override { 381 if (!Idx) 382 return; 383 this->emitDestructors(); 384 this->Ctx->emitDestroy(*Idx, SourceInfo{}); 385 this->Idx = std::nullopt; 386 } 387 addLocal(const Scope::Local & Local)388 void addLocal(const Scope::Local &Local) override { 389 if (!Idx) { 390 Idx = this->Ctx->Descriptors.size(); 391 this->Ctx->Descriptors.emplace_back(); 392 } 393 394 this->Ctx->Descriptors[*Idx].emplace_back(Local); 395 } 396 emitDestructors()397 void emitDestructors() override { 398 if (!Idx) 399 return; 400 // Emit destructor calls for local variables of record 401 // type with a destructor. 402 for (Scope::Local &Local : this->Ctx->Descriptors[*Idx]) { 403 if (!Local.Desc->isPrimitive() && !Local.Desc->isPrimitiveArray()) { 404 this->Ctx->emitGetPtrLocal(Local.Offset, SourceInfo{}); 405 this->Ctx->emitRecordDestruction(Local.Desc); 406 } 407 } 408 } 409 410 /// Index of the scope in the chain. 411 std::optional<unsigned> Idx; 412 }; 413 414 /// Emits the destructors of the variables of \param OtherScope 415 /// when this scope is destroyed. Does not create a Scope in the bytecode at 416 /// all, this is just a RAII object to emit destructors. 417 template <class Emitter> class DestructorScope final { 418 public: DestructorScope(LocalScope<Emitter> & OtherScope)419 DestructorScope(LocalScope<Emitter> &OtherScope) : OtherScope(OtherScope) {} 420 ~DestructorScope()421 ~DestructorScope() { OtherScope.emitDestructors(); } 422 423 private: 424 LocalScope<Emitter> &OtherScope; 425 }; 426 427 /// Like a regular LocalScope, except that the destructors of all local 428 /// variables are automatically emitted when the AutoScope is destroyed. 429 template <class Emitter> class AutoScope : public LocalScope<Emitter> { 430 public: AutoScope(ByteCodeExprGen<Emitter> * Ctx)431 AutoScope(ByteCodeExprGen<Emitter> *Ctx) 432 : LocalScope<Emitter>(Ctx), DS(*this) {} 433 434 private: 435 DestructorScope<Emitter> DS; 436 }; 437 438 /// Scope for storage declared in a compound statement. 439 template <class Emitter> class BlockScope final : public AutoScope<Emitter> { 440 public: BlockScope(ByteCodeExprGen<Emitter> * Ctx)441 BlockScope(ByteCodeExprGen<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {} 442 addExtended(const Scope::Local & Local)443 void addExtended(const Scope::Local &Local) override { 444 // If we to this point, just add the variable as a normal local 445 // variable. It will be destroyed at the end of the block just 446 // like all others. 447 this->addLocal(Local); 448 } 449 }; 450 451 /// Expression scope which tracks potentially lifetime extended 452 /// temporaries which are hoisted to the parent scope on exit. 453 template <class Emitter> class ExprScope final : public AutoScope<Emitter> { 454 public: ExprScope(ByteCodeExprGen<Emitter> * Ctx)455 ExprScope(ByteCodeExprGen<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {} 456 addExtended(const Scope::Local & Local)457 void addExtended(const Scope::Local &Local) override { 458 if (this->Parent) 459 this->Parent->addLocal(Local); 460 } 461 }; 462 463 template <class Emitter> class ArrayIndexScope final { 464 public: ArrayIndexScope(ByteCodeExprGen<Emitter> * Ctx,uint64_t Index)465 ArrayIndexScope(ByteCodeExprGen<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) { 466 OldArrayIndex = Ctx->ArrayIndex; 467 Ctx->ArrayIndex = Index; 468 } 469 ~ArrayIndexScope()470 ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; } 471 472 private: 473 ByteCodeExprGen<Emitter> *Ctx; 474 std::optional<uint64_t> OldArrayIndex; 475 }; 476 477 template <class Emitter> class SourceLocScope final { 478 public: SourceLocScope(ByteCodeExprGen<Emitter> * Ctx,const Expr * DefaultExpr)479 SourceLocScope(ByteCodeExprGen<Emitter> *Ctx, const Expr *DefaultExpr) 480 : Ctx(Ctx) { 481 assert(DefaultExpr); 482 // We only switch if the current SourceLocDefaultExpr is null. 483 if (!Ctx->SourceLocDefaultExpr) { 484 Enabled = true; 485 Ctx->SourceLocDefaultExpr = DefaultExpr; 486 } 487 } 488 ~SourceLocScope()489 ~SourceLocScope() { 490 if (Enabled) 491 Ctx->SourceLocDefaultExpr = nullptr; 492 } 493 494 private: 495 ByteCodeExprGen<Emitter> *Ctx; 496 bool Enabled = false; 497 }; 498 499 } // namespace interp 500 } // namespace clang 501 502 #endif 503