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