blob: e7f9ba0f010aebabe03c87fe7e532c3001300269 [file] [log] [blame]
Nandor Licker950b70d2019-09-13 09:46:16 +00001//===--- 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
21using namespace clang;
22using namespace clang::interp;
23
Nandor Lickerf584f042019-11-11 11:13:34 +000024Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {}
Nandor Licker950b70d2019-09-13 09:46:16 +000025
26Context::~Context() {}
27
Nandor Lickerf584f042019-11-11 11:13:34 +000028bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
Nandor Licker950b70d2019-09-13 09:46:16 +000029 Function *Func = P->getFunction(FD);
30 if (!Func) {
31 if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD)) {
32 Func = *R;
Nandor Lickerf584f042019-11-11 11:13:34 +000033 } else {
Nandor Licker950b70d2019-09-13 09:46:16 +000034 handleAllErrors(R.takeError(), [&Parent](ByteCodeGenError &Err) {
35 Parent.FFDiag(Err.getLoc(), diag::err_experimental_clang_interp_failed);
36 });
Nandor Lickerf584f042019-11-11 11:13:34 +000037 return false;
Nandor Licker950b70d2019-09-13 09:46:16 +000038 }
39 }
40
41 if (!Func->isConstexpr())
Nandor Lickerf584f042019-11-11 11:13:34 +000042 return false;
Nandor Licker950b70d2019-09-13 09:46:16 +000043
44 APValue Dummy;
45 return Run(Parent, Func, Dummy);
46}
47
Nandor Lickerf584f042019-11-11 11:13:34 +000048bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
Nandor Licker950b70d2019-09-13 09:46:16 +000049 ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
50 return Check(Parent, C.interpretExpr(E));
51}
52
Nandor Lickerf584f042019-11-11 11:13:34 +000053bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
54 APValue &Result) {
Nandor Licker950b70d2019-09-13 09:46:16 +000055 ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
56 return Check(Parent, C.interpretDecl(VD));
57}
58
59const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
60
61llvm::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
108unsigned Context::getCharBit() const {
109 return Ctx.getTargetInfo().getCharWidth();
110}
111
Nandor Lickerf584f042019-11-11 11:13:34 +0000112bool 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;
Nandor Licker950b70d2019-09-13 09:46:16 +0000119}
120
Nandor Lickerf584f042019-11-11 11:13:34 +0000121bool 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;
Nandor Licker950b70d2019-09-13 09:46:16 +0000128}