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 "Compiler.h"
12#include "EvalEmitter.h"
13#include "Interp.h"
14#include "InterpFrame.h"
15#include "InterpStack.h"
16#include "PrimType.h"
17#include "Program.h"
18#include "clang/AST/Expr.h"
19#include "clang/Basic/TargetInfo.h"
20
21using namespace clang;
22using namespace clang::interp;
23
24Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {
25 this->ShortWidth = Ctx.getTargetInfo().getShortWidth();
26 this->IntWidth = Ctx.getTargetInfo().getIntWidth();
27 this->LongWidth = Ctx.getTargetInfo().getLongWidth();
28 this->LongLongWidth = Ctx.getTargetInfo().getLongLongWidth();
29 assert(Ctx.getTargetInfo().getCharWidth() == 8 &&
30 "We're assuming 8 bit chars");
31}
32
33Context::~Context() {}
34
35bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
36 assert(Stk.empty());
37
38 // Get a function handle.
39 const Function *Func = getOrCreateFunction(FuncDecl: FD);
40 if (!Func)
41 return false;
42
43 // Compile the function.
44 Compiler<ByteCodeEmitter>(*this, *P).compileFunc(
45 FuncDecl: FD, Func: const_cast<Function *>(Func));
46
47 ++EvalID;
48 // And run it.
49 if (!Run(Parent, Func))
50 return false;
51
52 return Func->isValid();
53}
54
55bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
56 ++EvalID;
57 bool Recursing = !Stk.empty();
58 size_t StackSizeBefore = Stk.size();
59 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
60
61 auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue());
62
63 if (Res.isInvalid()) {
64 C.cleanup();
65 Stk.clearTo(NewSize: StackSizeBefore);
66 return false;
67 }
68
69 if (!Recursing) {
70 // We *can* actually get here with a non-empty stack, since
71 // things like InterpState::noteSideEffect() exist.
72 C.cleanup();
73#ifndef NDEBUG
74 // Make sure we don't rely on some value being still alive in
75 // InterpStack memory.
76 Stk.clearTo(StackSizeBefore);
77#endif
78 }
79
80 Result = Res.toAPValue();
81
82 return true;
83}
84
85bool Context::evaluate(State &Parent, const Expr *E, APValue &Result,
86 ConstantExprKind Kind) {
87 ++EvalID;
88 bool Recursing = !Stk.empty();
89 size_t StackSizeBefore = Stk.size();
90 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
91
92 auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/false,
93 /*DestroyToplevelScope=*/true);
94 if (Res.isInvalid()) {
95 C.cleanup();
96 Stk.clearTo(NewSize: StackSizeBefore);
97 return false;
98 }
99
100 if (!Recursing) {
101 assert(Stk.empty());
102 C.cleanup();
103#ifndef NDEBUG
104 // Make sure we don't rely on some value being still alive in
105 // InterpStack memory.
106 Stk.clearTo(StackSizeBefore);
107#endif
108 }
109
110 Result = Res.toAPValue();
111 return true;
112}
113
114bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
115 APValue &Result) {
116 ++EvalID;
117 bool Recursing = !Stk.empty();
118 size_t StackSizeBefore = Stk.size();
119 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
120
121 bool CheckGlobalInitialized =
122 shouldBeGloballyIndexed(VD) &&
123 (VD->getType()->isRecordType() || VD->getType()->isArrayType());
124 auto Res = C.interpretDecl(VD, CheckFullyInitialized: CheckGlobalInitialized);
125 if (Res.isInvalid()) {
126 C.cleanup();
127 Stk.clearTo(NewSize: StackSizeBefore);
128
129 return false;
130 }
131
132 if (!Recursing) {
133 assert(Stk.empty());
134 C.cleanup();
135#ifndef NDEBUG
136 // Make sure we don't rely on some value being still alive in
137 // InterpStack memory.
138 Stk.clearTo(StackSizeBefore);
139#endif
140 }
141
142 Result = Res.toAPValue();
143 return true;
144}
145
146template <typename ResultT>
147bool Context::evaluateStringRepr(State &Parent, const Expr *SizeExpr,
148 const Expr *PtrExpr, ResultT &Result) {
149 assert(Stk.empty());
150 Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
151
152 // Evaluate size value.
153 APValue SizeValue;
154 if (!evaluateAsRValue(Parent, E: SizeExpr, Result&: SizeValue))
155 return false;
156
157 if (!SizeValue.isInt())
158 return false;
159 uint64_t Size = SizeValue.getInt().getZExtValue();
160
161 auto PtrRes = C.interpretAsPointer(E: PtrExpr, PtrCB: [&](const Pointer &Ptr) {
162 if (Size == 0) {
163 if constexpr (std::is_same_v<ResultT, APValue>)
164 Result = APValue(APValue::UninitArray{}, 0, 0);
165 return true;
166 }
167
168 if (!Ptr.isLive() || !Ptr.getFieldDesc()->isPrimitiveArray())
169 return false;
170
171 // Must be char.
172 if (Ptr.getFieldDesc()->getElemSize() != 1 /*bytes*/)
173 return false;
174
175 if (Size > Ptr.getNumElems()) {
176 Parent.FFDiag(E: SizeExpr, DiagId: diag::note_constexpr_access_past_end) << AK_Read;
177 Size = Ptr.getNumElems();
178 }
179
180 if constexpr (std::is_same_v<ResultT, APValue>) {
181 QualType CharTy = PtrExpr->getType()->getPointeeType();
182 Result = APValue(APValue::UninitArray{}, Size, Size);
183 for (uint64_t I = 0; I != Size; ++I) {
184 if (std::optional<APValue> ElemVal =
185 Ptr.atIndex(Idx: I).toRValue(Ctx: *this, ResultType: CharTy))
186 Result.getArrayInitializedElt(I) = *ElemVal;
187 else
188 return false;
189 }
190 } else {
191 assert((std::is_same_v<ResultT, std::string>));
192 if (Size < Result.max_size())
193 Result.resize(Size);
194 Result.assign(reinterpret_cast<const char *>(Ptr.getRawAddress()), Size);
195 }
196
197 return true;
198 });
199
200 if (PtrRes.isInvalid()) {
201 C.cleanup();
202 Stk.clear();
203 return false;
204 }
205
206 return true;
207}
208
209bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
210 const Expr *PtrExpr, APValue &Result) {
211 assert(SizeExpr);
212 assert(PtrExpr);
213
214 return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
215}
216
217bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
218 const Expr *PtrExpr, std::string &Result) {
219 assert(SizeExpr);
220 assert(PtrExpr);
221
222 return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
223}
224
225const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
226
227static PrimType integralTypeToPrimTypeS(unsigned BitWidth) {
228 switch (BitWidth) {
229 case 64:
230 return PT_Sint64;
231 case 32:
232 return PT_Sint32;
233 case 16:
234 return PT_Sint16;
235 case 8:
236 return PT_Sint8;
237 default:
238 return PT_IntAPS;
239 }
240 llvm_unreachable("Unhandled BitWidth");
241}
242
243static PrimType integralTypeToPrimTypeU(unsigned BitWidth) {
244 switch (BitWidth) {
245 case 64:
246 return PT_Uint64;
247 case 32:
248 return PT_Uint32;
249 case 16:
250 return PT_Uint16;
251 case 8:
252 return PT_Uint8;
253 default:
254 return PT_IntAP;
255 }
256 llvm_unreachable("Unhandled BitWidth");
257}
258
259std::optional<PrimType> Context::classify(QualType T) const {
260
261 if (const auto *BT = dyn_cast<BuiltinType>(Val: T.getCanonicalType())) {
262 auto Kind = BT->getKind();
263 if (Kind == BuiltinType::Bool)
264 return PT_Bool;
265 if (Kind == BuiltinType::NullPtr)
266 return PT_Ptr;
267 if (Kind == BuiltinType::BoundMember)
268 return PT_MemberPtr;
269
270 // Just trying to avoid the ASTContext::getIntWidth call below.
271 if (Kind == BuiltinType::Short)
272 return integralTypeToPrimTypeS(BitWidth: this->ShortWidth);
273 if (Kind == BuiltinType::UShort)
274 return integralTypeToPrimTypeU(BitWidth: this->ShortWidth);
275
276 if (Kind == BuiltinType::Int)
277 return integralTypeToPrimTypeS(BitWidth: this->IntWidth);
278 if (Kind == BuiltinType::UInt)
279 return integralTypeToPrimTypeU(BitWidth: this->IntWidth);
280 if (Kind == BuiltinType::Long)
281 return integralTypeToPrimTypeS(BitWidth: this->LongWidth);
282 if (Kind == BuiltinType::ULong)
283 return integralTypeToPrimTypeU(BitWidth: this->LongWidth);
284 if (Kind == BuiltinType::LongLong)
285 return integralTypeToPrimTypeS(BitWidth: this->LongLongWidth);
286 if (Kind == BuiltinType::ULongLong)
287 return integralTypeToPrimTypeU(BitWidth: this->LongLongWidth);
288
289 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
290 return integralTypeToPrimTypeS(BitWidth: 8);
291 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
292 Kind == BuiltinType::Char8)
293 return integralTypeToPrimTypeU(BitWidth: 8);
294
295 if (BT->isSignedInteger())
296 return integralTypeToPrimTypeS(BitWidth: Ctx.getIntWidth(T));
297 if (BT->isUnsignedInteger())
298 return integralTypeToPrimTypeU(BitWidth: Ctx.getIntWidth(T));
299
300 if (BT->isFloatingPoint())
301 return PT_Float;
302 }
303
304 if (T->isPointerOrReferenceType())
305 return PT_Ptr;
306
307 if (T->isMemberPointerType())
308 return PT_MemberPtr;
309
310 if (const auto *BT = T->getAs<BitIntType>()) {
311 if (BT->isSigned())
312 return integralTypeToPrimTypeS(BitWidth: BT->getNumBits());
313 return integralTypeToPrimTypeU(BitWidth: BT->getNumBits());
314 }
315
316 if (const auto *ET = T->getAs<EnumType>()) {
317 const auto *D = ET->getDecl();
318 if (!D->isComplete())
319 return std::nullopt;
320 return classify(T: D->getIntegerType());
321 }
322
323 if (const auto *AT = T->getAs<AtomicType>())
324 return classify(T: AT->getValueType());
325
326 if (const auto *DT = dyn_cast<DecltypeType>(Val&: T))
327 return classify(T: DT->getUnderlyingType());
328
329 if (T->isObjCObjectPointerType() || T->isBlockPointerType())
330 return PT_Ptr;
331
332 if (T->isFixedPointType())
333 return PT_FixedPoint;
334
335 // Vector and complex types get here.
336 return std::nullopt;
337}
338
339unsigned Context::getCharBit() const {
340 return Ctx.getTargetInfo().getCharWidth();
341}
342
343/// Simple wrapper around getFloatTypeSemantics() to make code a
344/// little shorter.
345const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const {
346 return Ctx.getFloatTypeSemantics(T);
347}
348
349bool Context::Run(State &Parent, const Function *Func) {
350
351 {
352 InterpState State(Parent, *P, Stk, *this, Func);
353 if (Interpret(S&: State)) {
354 assert(Stk.empty());
355 return true;
356 }
357 // State gets destroyed here, so the Stk.clear() below doesn't accidentally
358 // remove values the State's destructor might access.
359 }
360
361 Stk.clear();
362 return false;
363}
364
365// TODO: Virtual bases?
366const CXXMethodDecl *
367Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl,
368 const CXXRecordDecl *StaticDecl,
369 const CXXMethodDecl *InitialFunction) const {
370 assert(DynamicDecl);
371 assert(StaticDecl);
372 assert(InitialFunction);
373
374 const CXXRecordDecl *CurRecord = DynamicDecl;
375 const CXXMethodDecl *FoundFunction = InitialFunction;
376 for (;;) {
377 const CXXMethodDecl *Overrider =
378 FoundFunction->getCorrespondingMethodDeclaredInClass(RD: CurRecord, MayBeBase: false);
379 if (Overrider)
380 return Overrider;
381
382 // Common case of only one base class.
383 if (CurRecord->getNumBases() == 1) {
384 CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl();
385 continue;
386 }
387
388 // Otherwise, go to the base class that will lead to the StaticDecl.
389 for (const CXXBaseSpecifier &Spec : CurRecord->bases()) {
390 const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl();
391 if (Base == StaticDecl || Base->isDerivedFrom(Base: StaticDecl)) {
392 CurRecord = Base;
393 break;
394 }
395 }
396 }
397
398 llvm_unreachable(
399 "Couldn't find an overriding function in the class hierarchy?");
400 return nullptr;
401}
402
403const Function *Context::getOrCreateFunction(const FunctionDecl *FuncDecl) {
404 assert(FuncDecl);
405 FuncDecl = FuncDecl->getMostRecentDecl();
406
407 if (const Function *Func = P->getFunction(F: FuncDecl))
408 return Func;
409
410 // Manually created functions that haven't been assigned proper
411 // parameters yet.
412 if (!FuncDecl->param_empty() && !FuncDecl->param_begin())
413 return nullptr;
414
415 bool IsLambdaStaticInvoker = false;
416 if (const auto *MD = dyn_cast<CXXMethodDecl>(Val: FuncDecl);
417 MD && MD->isLambdaStaticInvoker()) {
418 // For a lambda static invoker, we might have to pick a specialized
419 // version if the lambda is generic. In that case, the picked function
420 // will *NOT* be a static invoker anymore. However, it will still
421 // be a non-static member function, this (usually) requiring an
422 // instance pointer. We suppress that later in this function.
423 IsLambdaStaticInvoker = true;
424
425 const CXXRecordDecl *ClosureClass = MD->getParent();
426 assert(ClosureClass->captures_begin() == ClosureClass->captures_end());
427 if (ClosureClass->isGenericLambda()) {
428 const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator();
429 assert(MD->isFunctionTemplateSpecialization() &&
430 "A generic lambda's static-invoker function must be a "
431 "template specialization");
432 const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs();
433 FunctionTemplateDecl *CallOpTemplate =
434 LambdaCallOp->getDescribedFunctionTemplate();
435 void *InsertPos = nullptr;
436 const FunctionDecl *CorrespondingCallOpSpecialization =
437 CallOpTemplate->findSpecialization(Args: TAL->asArray(), InsertPos);
438 assert(CorrespondingCallOpSpecialization);
439 FuncDecl = CorrespondingCallOpSpecialization;
440 }
441 }
442 // Set up argument indices.
443 unsigned ParamOffset = 0;
444 SmallVector<PrimType, 8> ParamTypes;
445 SmallVector<unsigned, 8> ParamOffsets;
446 llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;
447
448 // If the return is not a primitive, a pointer to the storage where the
449 // value is initialized in is passed as the first argument. See 'RVO'
450 // elsewhere in the code.
451 QualType Ty = FuncDecl->getReturnType();
452 bool HasRVO = false;
453 if (!Ty->isVoidType() && !classify(T: Ty)) {
454 HasRVO = true;
455 ParamTypes.push_back(Elt: PT_Ptr);
456 ParamOffsets.push_back(Elt: ParamOffset);
457 ParamOffset += align(Size: primSize(Type: PT_Ptr));
458 }
459
460 // If the function decl is a member decl, the next parameter is
461 // the 'this' pointer. This parameter is pop()ed from the
462 // InterpStack when calling the function.
463 bool HasThisPointer = false;
464 if (const auto *MD = dyn_cast<CXXMethodDecl>(Val: FuncDecl)) {
465 if (!IsLambdaStaticInvoker) {
466 HasThisPointer = MD->isInstance();
467 if (MD->isImplicitObjectMemberFunction()) {
468 ParamTypes.push_back(Elt: PT_Ptr);
469 ParamOffsets.push_back(Elt: ParamOffset);
470 ParamOffset += align(Size: primSize(Type: PT_Ptr));
471 }
472 }
473
474 if (isLambdaCallOperator(MD)) {
475 // The parent record needs to be complete, we need to know about all
476 // the lambda captures.
477 if (!MD->getParent()->isCompleteDefinition())
478 return nullptr;
479 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
480 FieldDecl *LTC;
481
482 MD->getParent()->getCaptureFields(Captures&: LC, ThisCapture&: LTC);
483
484 if (MD->isStatic() && !LC.empty()) {
485 // Static lambdas cannot have any captures. If this one does,
486 // it has already been diagnosed and we can only ignore it.
487 return nullptr;
488 }
489 }
490 }
491
492 // Assign descriptors to all parameters.
493 // Composite objects are lowered to pointers.
494 for (const ParmVarDecl *PD : FuncDecl->parameters()) {
495 std::optional<PrimType> T = classify(T: PD->getType());
496 PrimType PT = T.value_or(u: PT_Ptr);
497 Descriptor *Desc = P->createDescriptor(D: PD, T: PT);
498 ParamDescriptors.insert(KV: {ParamOffset, {PT, Desc}});
499 ParamOffsets.push_back(Elt: ParamOffset);
500 ParamOffset += align(Size: primSize(Type: PT));
501 ParamTypes.push_back(Elt: PT);
502 }
503
504 // Create a handle over the emitted code.
505 assert(!P->getFunction(FuncDecl));
506 const Function *Func = P->createFunction(
507 Def: FuncDecl, Args&: ParamOffset, Args: std::move(ParamTypes), Args: std::move(ParamDescriptors),
508 Args: std::move(ParamOffsets), Args&: HasThisPointer, Args&: HasRVO, Args&: IsLambdaStaticInvoker);
509 return Func;
510}
511
512const Function *Context::getOrCreateObjCBlock(const BlockExpr *E) {
513 const BlockDecl *BD = E->getBlockDecl();
514 // Set up argument indices.
515 unsigned ParamOffset = 0;
516 SmallVector<PrimType, 8> ParamTypes;
517 SmallVector<unsigned, 8> ParamOffsets;
518 llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;
519
520 // Assign descriptors to all parameters.
521 // Composite objects are lowered to pointers.
522 for (const ParmVarDecl *PD : BD->parameters()) {
523 std::optional<PrimType> T = classify(T: PD->getType());
524 PrimType PT = T.value_or(u: PT_Ptr);
525 Descriptor *Desc = P->createDescriptor(D: PD, T: PT);
526 ParamDescriptors.insert(KV: {ParamOffset, {PT, Desc}});
527 ParamOffsets.push_back(Elt: ParamOffset);
528 ParamOffset += align(Size: primSize(Type: PT));
529 ParamTypes.push_back(Elt: PT);
530 }
531
532 if (BD->hasCaptures())
533 return nullptr;
534
535 // Create a handle over the emitted code.
536 Function *Func =
537 P->createFunction(Args&: E, Args&: ParamOffset, Args: std::move(ParamTypes),
538 Args: std::move(ParamDescriptors), Args: std::move(ParamOffsets),
539 /*HasThisPointer=*/Args: false, /*HasRVO=*/Args: false,
540 /*IsLambdaStaticInvoker=*/Args: false);
541
542 assert(Func);
543 Func->setDefined(true);
544 // We don't compile the BlockDecl code at all right now.
545 Func->setIsFullyCompiled(true);
546 return Func;
547}
548
549unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
550 const RecordDecl *DerivedDecl) const {
551 assert(BaseDecl);
552 assert(DerivedDecl);
553 const auto *FinalDecl = cast<CXXRecordDecl>(Val: BaseDecl);
554 const RecordDecl *CurDecl = DerivedDecl;
555 const Record *CurRecord = P->getOrCreateRecord(RD: CurDecl);
556 assert(CurDecl && FinalDecl);
557
558 unsigned OffsetSum = 0;
559 for (;;) {
560 assert(CurRecord->getNumBases() > 0);
561 // One level up
562 for (const Record::Base &B : CurRecord->bases()) {
563 const auto *BaseDecl = cast<CXXRecordDecl>(Val: B.Decl);
564
565 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(Base: FinalDecl)) {
566 OffsetSum += B.Offset;
567 CurRecord = B.R;
568 CurDecl = BaseDecl;
569 break;
570 }
571 }
572 if (CurDecl == FinalDecl)
573 break;
574 }
575
576 assert(OffsetSum > 0);
577 return OffsetSum;
578}
579
580const Record *Context::getRecord(const RecordDecl *D) const {
581 return P->getOrCreateRecord(RD: D);
582}
583
584bool Context::isUnevaluatedBuiltin(unsigned ID) {
585 return ID == Builtin::BI__builtin_classify_type ||
586 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
587 ID == Builtin::BI__builtin_constant_p || ID == Builtin::BI__noop;
588}
589

source code of clang/lib/AST/ByteCode/Context.cpp