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 "Compiler.h" 12 #include "EvalEmitter.h" 13 #include "Interp.h" 14 #include "InterpFrame.h" 15 #include "InterpStack.h" 16 #include "PrimType.h" 17 #include "Program.h" 18 #include "clang/AST/Expr.h" 19 #include "clang/Basic/TargetInfo.h" 20 21 using namespace clang; 22 using namespace clang::interp; 23 24 Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {} 25 26 Context::~Context() {} 27 28 bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) { 29 assert(Stk.empty()); 30 Function *Func = P->getFunction(FD); 31 if (!Func || !Func->hasBody()) 32 Func = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD); 33 34 if (!Func) 35 return false; 36 37 APValue DummyResult; 38 if (!Run(Parent, Func, DummyResult)) 39 return false; 40 41 return Func->isConstexpr(); 42 } 43 44 bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { 45 ++EvalID; 46 bool Recursing = !Stk.empty(); 47 Compiler<EvalEmitter> C(*this, *P, Parent, Stk); 48 49 auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue()); 50 51 if (Res.isInvalid()) { 52 C.cleanup(); 53 Stk.clear(); 54 return false; 55 } 56 57 if (!Recursing) { 58 assert(Stk.empty()); 59 C.cleanup(); 60 #ifndef NDEBUG 61 // Make sure we don't rely on some value being still alive in 62 // InterpStack memory. 63 Stk.clear(); 64 #endif 65 } 66 67 Result = Res.toAPValue(); 68 69 return true; 70 } 71 72 bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) { 73 ++EvalID; 74 bool Recursing = !Stk.empty(); 75 Compiler<EvalEmitter> C(*this, *P, Parent, Stk); 76 77 auto Res = C.interpretExpr(E); 78 if (Res.isInvalid()) { 79 C.cleanup(); 80 Stk.clear(); 81 return false; 82 } 83 84 if (!Recursing) { 85 assert(Stk.empty()); 86 C.cleanup(); 87 #ifndef NDEBUG 88 // Make sure we don't rely on some value being still alive in 89 // InterpStack memory. 90 Stk.clear(); 91 #endif 92 } 93 94 Result = Res.toAPValue(); 95 return true; 96 } 97 98 bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, 99 APValue &Result) { 100 ++EvalID; 101 bool Recursing = !Stk.empty(); 102 Compiler<EvalEmitter> C(*this, *P, Parent, Stk); 103 104 bool CheckGlobalInitialized = 105 shouldBeGloballyIndexed(VD) && 106 (VD->getType()->isRecordType() || VD->getType()->isArrayType()); 107 auto Res = C.interpretDecl(VD, CheckGlobalInitialized); 108 if (Res.isInvalid()) { 109 C.cleanup(); 110 Stk.clear(); 111 return false; 112 } 113 114 if (!Recursing) { 115 assert(Stk.empty()); 116 C.cleanup(); 117 #ifndef NDEBUG 118 // Make sure we don't rely on some value being still alive in 119 // InterpStack memory. 120 Stk.clear(); 121 #endif 122 } 123 124 Result = Res.toAPValue(); 125 return true; 126 } 127 128 const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); } 129 130 std::optional<PrimType> Context::classify(QualType T) const { 131 if (T->isBooleanType()) 132 return PT_Bool; 133 134 // We map these to primitive arrays. 135 if (T->isAnyComplexType() || T->isVectorType()) 136 return std::nullopt; 137 138 if (const auto *ET = T->getAs<EnumType>()) 139 return classify(ET->getDecl()->getIntegerType()); 140 141 if (T->isSignedIntegerOrEnumerationType()) { 142 switch (Ctx.getIntWidth(T)) { 143 case 64: 144 return PT_Sint64; 145 case 32: 146 return PT_Sint32; 147 case 16: 148 return PT_Sint16; 149 case 8: 150 return PT_Sint8; 151 default: 152 return PT_IntAPS; 153 } 154 } 155 156 if (T->isUnsignedIntegerOrEnumerationType()) { 157 switch (Ctx.getIntWidth(T)) { 158 case 64: 159 return PT_Uint64; 160 case 32: 161 return PT_Uint32; 162 case 16: 163 return PT_Uint16; 164 case 8: 165 return PT_Uint8; 166 default: 167 return PT_IntAP; 168 } 169 } 170 171 if (T->isNullPtrType()) 172 return PT_Ptr; 173 174 if (T->isFloatingType()) 175 return PT_Float; 176 177 if (T->isSpecificBuiltinType(BuiltinType::BoundMember) || 178 T->isMemberPointerType()) 179 return PT_MemberPtr; 180 181 if (T->isFunctionPointerType() || T->isFunctionReferenceType() || 182 T->isFunctionType()) 183 return PT_FnPtr; 184 185 if (T->isPointerOrReferenceType() || T->isObjCObjectPointerType()) 186 return PT_Ptr; 187 188 if (const auto *AT = T->getAs<AtomicType>()) 189 return classify(AT->getValueType()); 190 191 if (const auto *DT = dyn_cast<DecltypeType>(T)) 192 return classify(DT->getUnderlyingType()); 193 194 return std::nullopt; 195 } 196 197 unsigned Context::getCharBit() const { 198 return Ctx.getTargetInfo().getCharWidth(); 199 } 200 201 /// Simple wrapper around getFloatTypeSemantics() to make code a 202 /// little shorter. 203 const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const { 204 return Ctx.getFloatTypeSemantics(T); 205 } 206 207 bool Context::Run(State &Parent, const Function *Func, APValue &Result) { 208 209 { 210 InterpState State(Parent, *P, Stk, *this); 211 State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, CodePtr(), 212 Func->getArgSize()); 213 if (Interpret(State, Result)) { 214 assert(Stk.empty()); 215 return true; 216 } 217 218 // State gets destroyed here, so the Stk.clear() below doesn't accidentally 219 // remove values the State's destructor might access. 220 } 221 222 Stk.clear(); 223 return false; 224 } 225 226 // TODO: Virtual bases? 227 const CXXMethodDecl * 228 Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl, 229 const CXXRecordDecl *StaticDecl, 230 const CXXMethodDecl *InitialFunction) const { 231 assert(DynamicDecl); 232 assert(StaticDecl); 233 assert(InitialFunction); 234 235 const CXXRecordDecl *CurRecord = DynamicDecl; 236 const CXXMethodDecl *FoundFunction = InitialFunction; 237 for (;;) { 238 const CXXMethodDecl *Overrider = 239 FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false); 240 if (Overrider) 241 return Overrider; 242 243 // Common case of only one base class. 244 if (CurRecord->getNumBases() == 1) { 245 CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl(); 246 continue; 247 } 248 249 // Otherwise, go to the base class that will lead to the StaticDecl. 250 for (const CXXBaseSpecifier &Spec : CurRecord->bases()) { 251 const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl(); 252 if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) { 253 CurRecord = Base; 254 break; 255 } 256 } 257 } 258 259 llvm_unreachable( 260 "Couldn't find an overriding function in the class hierarchy?"); 261 return nullptr; 262 } 263 264 const Function *Context::getOrCreateFunction(const FunctionDecl *FD) { 265 assert(FD); 266 const Function *Func = P->getFunction(FD); 267 bool IsBeingCompiled = Func && Func->isDefined() && !Func->isFullyCompiled(); 268 bool WasNotDefined = Func && !Func->isConstexpr() && !Func->isDefined(); 269 270 if (IsBeingCompiled) 271 return Func; 272 273 if (!Func || WasNotDefined) { 274 if (auto F = Compiler<ByteCodeEmitter>(*this, *P).compileFunc(FD)) 275 Func = F; 276 } 277 278 return Func; 279 } 280 281 unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl, 282 const RecordDecl *DerivedDecl) const { 283 assert(BaseDecl); 284 assert(DerivedDecl); 285 const auto *FinalDecl = cast<CXXRecordDecl>(BaseDecl); 286 const RecordDecl *CurDecl = DerivedDecl; 287 const Record *CurRecord = P->getOrCreateRecord(CurDecl); 288 assert(CurDecl && FinalDecl); 289 290 unsigned OffsetSum = 0; 291 for (;;) { 292 assert(CurRecord->getNumBases() > 0); 293 // One level up 294 for (const Record::Base &B : CurRecord->bases()) { 295 const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl); 296 297 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) { 298 OffsetSum += B.Offset; 299 CurRecord = B.R; 300 CurDecl = BaseDecl; 301 break; 302 } 303 } 304 if (CurDecl == FinalDecl) 305 break; 306 } 307 308 assert(OffsetSum > 0); 309 return OffsetSum; 310 } 311 312 const Record *Context::getRecord(const RecordDecl *D) const { 313 return P->getOrCreateRecord(D); 314 } 315