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