1 //===--- Context.cpp - Context for the constexpr VM -------------*- 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 #include "Context.h" 10 #include "ByteCodeEmitter.h" 11 #include "ByteCodeExprGen.h" 12 #include "ByteCodeStmtGen.h" 13 #include "EvalEmitter.h" 14 #include "Interp.h" 15 #include "InterpFrame.h" 16 #include "InterpStack.h" 17 #include "PrimType.h" 18 #include "Program.h" 19 #include "clang/AST/Expr.h" 20 #include "clang/Basic/TargetInfo.h" 21 22 using namespace clang; 23 using namespace clang::interp; 24 25 Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {} 26 27 Context::~Context() {} 28 29 bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) { 30 assert(Stk.empty()); 31 Function *Func = P->getFunction(FD); 32 if (!Func || !Func->hasBody()) { 33 if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD)) { 34 Func = *R; 35 } else { 36 handleAllErrors(R.takeError(), [&Parent](ByteCodeGenError &Err) { 37 Parent.FFDiag(Err.getRange().getBegin(), 38 diag::err_experimental_clang_interp_failed) 39 << Err.getRange(); 40 }); 41 return false; 42 } 43 } 44 45 APValue DummyResult; 46 if (!Run(Parent, Func, DummyResult)) { 47 return false; 48 } 49 50 return Func->isConstexpr(); 51 } 52 53 bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { 54 assert(Stk.empty()); 55 ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); 56 if (Check(Parent, C.interpretExpr(E))) { 57 assert(Stk.empty()); 58 #ifndef NDEBUG 59 // Make sure we don't rely on some value being still alive in 60 // InterpStack memory. 61 Stk.clear(); 62 #endif 63 return true; 64 } 65 66 Stk.clear(); 67 return false; 68 } 69 70 bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, 71 APValue &Result) { 72 assert(Stk.empty()); 73 ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); 74 if (Check(Parent, C.interpretDecl(VD))) { 75 assert(Stk.empty()); 76 #ifndef NDEBUG 77 // Make sure we don't rely on some value being still alive in 78 // InterpStack memory. 79 Stk.clear(); 80 #endif 81 return true; 82 } 83 84 Stk.clear(); 85 return false; 86 } 87 88 const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); } 89 90 std::optional<PrimType> Context::classify(QualType T) const { 91 if (T->isFunctionPointerType() || T->isFunctionReferenceType()) 92 return PT_FnPtr; 93 94 if (T->isReferenceType() || T->isPointerType()) 95 return PT_Ptr; 96 97 if (T->isBooleanType()) 98 return PT_Bool; 99 100 if (T->isSignedIntegerOrEnumerationType()) { 101 switch (Ctx.getIntWidth(T)) { 102 case 64: 103 return PT_Sint64; 104 case 32: 105 return PT_Sint32; 106 case 16: 107 return PT_Sint16; 108 case 8: 109 return PT_Sint8; 110 default: 111 return {}; 112 } 113 } 114 115 if (T->isUnsignedIntegerOrEnumerationType()) { 116 switch (Ctx.getIntWidth(T)) { 117 case 64: 118 return PT_Uint64; 119 case 32: 120 return PT_Uint32; 121 case 16: 122 return PT_Uint16; 123 case 8: 124 return PT_Uint8; 125 default: 126 return {}; 127 } 128 } 129 130 if (T->isNullPtrType()) 131 return PT_Ptr; 132 133 if (T->isFloatingType()) 134 return PT_Float; 135 136 if (auto *AT = dyn_cast<AtomicType>(T)) 137 return classify(AT->getValueType()); 138 139 return {}; 140 } 141 142 unsigned Context::getCharBit() const { 143 return Ctx.getTargetInfo().getCharWidth(); 144 } 145 146 /// Simple wrapper around getFloatTypeSemantics() to make code a 147 /// little shorter. 148 const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const { 149 return Ctx.getFloatTypeSemantics(T); 150 } 151 152 bool Context::Run(State &Parent, const Function *Func, APValue &Result) { 153 InterpState State(Parent, *P, Stk, *this); 154 State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, {}); 155 if (Interpret(State, Result)) 156 return true; 157 Stk.clear(); 158 return false; 159 } 160 161 bool Context::Check(State &Parent, llvm::Expected<bool> &&Flag) { 162 if (Flag) 163 return *Flag; 164 handleAllErrors(Flag.takeError(), [&Parent](ByteCodeGenError &Err) { 165 Parent.FFDiag(Err.getRange().getBegin(), 166 diag::err_experimental_clang_interp_failed) 167 << Err.getRange(); 168 }); 169 return false; 170 } 171 172 // TODO: Virtual bases? 173 const CXXMethodDecl * 174 Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl, 175 const CXXRecordDecl *StaticDecl, 176 const CXXMethodDecl *InitialFunction) const { 177 178 const CXXRecordDecl *CurRecord = DynamicDecl; 179 const CXXMethodDecl *FoundFunction = InitialFunction; 180 for (;;) { 181 const CXXMethodDecl *Overrider = 182 FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false); 183 if (Overrider) 184 return Overrider; 185 186 // Common case of only one base class. 187 if (CurRecord->getNumBases() == 1) { 188 CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl(); 189 continue; 190 } 191 192 // Otherwise, go to the base class that will lead to the StaticDecl. 193 for (const CXXBaseSpecifier &Spec : CurRecord->bases()) { 194 const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl(); 195 if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) { 196 CurRecord = Base; 197 break; 198 } 199 } 200 } 201 202 llvm_unreachable( 203 "Couldn't find an overriding function in the class hierarchy?"); 204 return nullptr; 205 } 206