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