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 return Func->isConstexpr(); 46 } 47 48 bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { 49 assert(Stk.empty()); 50 ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); 51 if (Check(Parent, C.interpretExpr(E))) { 52 assert(Stk.empty()); 53 return true; 54 } 55 56 Stk.clear(); 57 return false; 58 } 59 60 bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, 61 APValue &Result) { 62 assert(Stk.empty()); 63 ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); 64 if (Check(Parent, C.interpretDecl(VD))) { 65 assert(Stk.empty()); 66 return true; 67 } 68 69 Stk.clear(); 70 return false; 71 } 72 73 const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); } 74 75 std::optional<PrimType> Context::classify(QualType T) const { 76 if (T->isReferenceType() || T->isPointerType()) { 77 return PT_Ptr; 78 } 79 80 if (T->isBooleanType()) 81 return PT_Bool; 82 83 if (T->isSignedIntegerOrEnumerationType()) { 84 switch (Ctx.getIntWidth(T)) { 85 case 64: 86 return PT_Sint64; 87 case 32: 88 return PT_Sint32; 89 case 16: 90 return PT_Sint16; 91 case 8: 92 return PT_Sint8; 93 default: 94 return {}; 95 } 96 } 97 98 if (T->isUnsignedIntegerOrEnumerationType()) { 99 switch (Ctx.getIntWidth(T)) { 100 case 64: 101 return PT_Uint64; 102 case 32: 103 return PT_Uint32; 104 case 16: 105 return PT_Uint16; 106 case 8: 107 return PT_Uint8; 108 default: 109 return {}; 110 } 111 } 112 113 if (T->isNullPtrType()) 114 return PT_Ptr; 115 116 if (auto *AT = dyn_cast<AtomicType>(T)) 117 return classify(AT->getValueType()); 118 119 return {}; 120 } 121 122 unsigned Context::getCharBit() const { 123 return Ctx.getTargetInfo().getCharWidth(); 124 } 125 126 bool Context::Run(State &Parent, Function *Func, APValue &Result) { 127 InterpState State(Parent, *P, Stk, *this); 128 State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, {}); 129 if (Interpret(State, Result)) 130 return true; 131 Stk.clear(); 132 return false; 133 } 134 135 bool Context::Check(State &Parent, llvm::Expected<bool> &&Flag) { 136 if (Flag) 137 return *Flag; 138 handleAllErrors(Flag.takeError(), [&Parent](ByteCodeGenError &Err) { 139 Parent.FFDiag(Err.getRange().getBegin(), 140 diag::err_experimental_clang_interp_failed) 141 << Err.getRange(); 142 }); 143 return false; 144 } 145