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 "Boolean.h"
11#include "ByteCodeEmitter.h"
12#include "Char.h"
13#include "Compiler.h"
14#include "EvalEmitter.h"
15#include "EvalSettings.h"
16#include "Integral.h"
17#include "InterpFrame.h"
18#include "InterpHelpers.h"
19#include "InterpStack.h"
20#include "Pointer.h"
21#include "PrimType.h"
22#include "Program.h"
23#include "clang/AST/ASTLambda.h"
24#include "clang/AST/Expr.h"
25#include "clang/Basic/TargetInfo.h"
26
27using namespace clang;
28using namespace clang::interp;
29
30Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {
31 this->ShortWidth = Ctx.getTargetInfo().getShortWidth();
32 this->IntWidth = Ctx.getTargetInfo().getIntWidth();
33 this->LongWidth = Ctx.getTargetInfo().getLongWidth();
34 this->LongLongWidth = Ctx.getTargetInfo().getLongLongWidth();
35 assert(Ctx.getTargetInfo().getCharWidth() == 8 &&
36 "We're assuming 8 bit chars");
37}
38
39Context::~Context() = default;
40
41bool Context::isPotentialConstantExpr(const EvalSettings &Settings,
42 const FunctionDecl *FD) {
43 assert(Stk.empty());
44
45 // Get a function handle.
46 const Function *Func = getOrCreateFunction(FuncDecl: FD);
47 if (!Func)
48 return false;
49
50 // Compile the function.
51 Compiler<ByteCodeEmitter>(*this, *P).compileFunc(
52 FuncDecl: FD, Func: const_cast<Function *>(Func));
53
54 if (!Func->isValid())
55 return false;
56
57 ++EvalID;
58 // And run it.
59 return Run(Settings, Func);
60}
61
62void Context::isPotentialConstantExprUnevaluated(const EvalSettings &Settings,
63 const Expr *E,
64 const FunctionDecl *FD) {
65 assert(Stk.empty());
66 ++EvalID;
67 size_t StackSizeBefore = Stk.size();
68 Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
69
70 if (!C.interpretCall(FD, E)) {
71 C.cleanup();
72 Stk.clearTo(NewSize: StackSizeBefore);
73 }
74}
75
76bool Context::evaluateAsRValue(const EvalSettings &Settings, const Expr *E,
77 APValue &Result) {
78 ++EvalID;
79 bool Recursing = !Stk.empty();
80 size_t StackSizeBefore = Stk.size();
81 Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
82
83 auto Res = C.interpretExpr(E);
84
85 if (Res.isInvalid()) {
86 C.cleanup();
87 Stk.clearTo(NewSize: StackSizeBefore);
88 return false;
89 }
90
91 if (!Recursing) {
92 // We *can* actually get here with a non-empty stack, since
93 // things like InterpState::noteSideEffect() exist.
94 C.cleanup();
95#ifndef NDEBUG
96 // Make sure we don't rely on some value being still alive in
97 // InterpStack memory.
98 Stk.clearTo(StackSizeBefore);
99#endif
100 }
101
102 Result = Res.stealAPValue();
103 return true;
104}
105
106bool Context::evaluate(const EvalSettings &Settings, const Expr *E,
107 APValue &Result) {
108 ++EvalID;
109 bool Recursing = !Stk.empty();
110 size_t StackSizeBefore = Stk.size();
111 Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
112
113 // The object of an initializer outlives the evaluation.
114 auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/false,
115 /*DestroyToplevelScope=*/Settings.ConstexprKind !=
116 ConstantExprKind::Initializer);
117 if (Res.isInvalid()) {
118 C.cleanup();
119 Stk.clearTo(NewSize: StackSizeBefore);
120 return false;
121 }
122
123 if (!Recursing) {
124 assert(Stk.empty());
125 C.cleanup();
126#ifndef NDEBUG
127 // Make sure we don't rely on some value being still alive in
128 // InterpStack memory.
129 Stk.clearTo(StackSizeBefore);
130#endif
131 }
132
133 Result = Res.stealAPValue();
134 return true;
135}
136
137bool Context::evaluateAsInitializer(const EvalSettings &Settings,
138 const VarDecl *VD, const Expr *Init,
139 APValue &Result) {
140 ++EvalID;
141 bool Recursing = !Stk.empty();
142 size_t StackSizeBefore = Stk.size();
143 Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
144
145 bool CheckGlobalInitialized =
146 (VD->getType()->isRecordType() || VD->getType()->isArrayType());
147
148 auto Res = C.interpretDecl(VD, Init, CheckFullyInitialized: CheckGlobalInitialized);
149 if (Res.isInvalid()) {
150 C.cleanup();
151 Stk.clearTo(NewSize: StackSizeBefore);
152
153 return false;
154 }
155
156 if (!Recursing) {
157 assert(Stk.empty());
158 C.cleanup();
159#ifndef NDEBUG
160 // Make sure we don't rely on some value being still alive in
161 // InterpStack memory.
162 Stk.clearTo(StackSizeBefore);
163#endif
164 }
165
166 Result = Res.stealAPValue();
167 return true;
168}
169
170bool Context::evaluateDestruction(const EvalSettings &Settings,
171 const VarDecl *VD, APValue Value) {
172 assert(Stk.empty());
173 Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
174
175 auto Res = C.interpretDestructor(VD, Value);
176
177 if (Res.isInvalid()) {
178 C.cleanup();
179 Stk.clear();
180 return false;
181 }
182
183 assert(Stk.empty());
184
185 return true;
186}
187
188void Context::registerRedecl(const VarDecl *VD, const APValue &V) {
189 Expr::EvalStatus Status;
190 Compiler<EvalEmitter> C(*this, *P, Status, Stk, FrameAlloc);
191
192 C.registerRedecl(VD, V);
193}
194
195template <typename ResultT>
196bool Context::evaluateStringRepr(const EvalSettings &Settings,
197 const Expr *SizeExpr, const Expr *PtrExpr,
198 ResultT &Result) {
199 assert(Stk.empty());
200 Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
201
202 // Evaluate size value.
203 APValue SizeValue;
204 if (!evaluateAsRValue(Settings, E: SizeExpr, Result&: SizeValue))
205 return false;
206
207 if (!SizeValue.isInt())
208 return false;
209 uint64_t Size = SizeValue.getInt().getZExtValue();
210
211 auto PtrRes = C.interpretAsPointer(E: PtrExpr, PtrCB: [&](InterpState &S, CodePtr OpPC,
212 const Pointer &Ptr) {
213 if (Size == 0) {
214 if constexpr (std::is_same_v<ResultT, APValue>)
215 Result = APValue(APValue::UninitArray{}, 0, 0);
216 return true;
217 }
218
219 if (Ptr.isZero()) {
220 S.FFDiag(SI: S.Current->getSource(PC: OpPC), DiagId: diag::note_constexpr_access_null)
221 << AK_Read;
222 return false;
223 }
224
225 if (!Ptr.isLive() || !Ptr.isInitialized() || Ptr.isUnknownSizeArray() ||
226 !Ptr.inArray())
227 return false;
228
229 // Must be char.
230 if (Ptr.isBlockPointer() &&
231 Ptr.getFieldDesc()->getElemDataSize() != 1 /*bytes*/)
232 return false;
233 if (Ptr.isStringPointer() &&
234 !Ptr.asStringPointer().getLiteral()->isOrdinary())
235 return false;
236
237 bool Limited = false;
238 if (Size > Ptr.getNumElems()) {
239 S.FFDiag(SI: S.Current->getSource(PC: OpPC), DiagId: diag::note_constexpr_access_past_end)
240 << AK_Read;
241 Size = Ptr.getNumElems();
242 Limited = true;
243 }
244
245 if constexpr (std::is_same_v<ResultT, APValue>) {
246 QualType CharTy = PtrExpr->getType()->getPointeeType();
247 Result = APValue(APValue::UninitArray{}, Size, Size);
248 for (uint64_t I = 0; I != Size; ++I) {
249 if (std::optional<APValue> ElemVal =
250 Ptr.atIndex(Idx: I).toRValue(Ctx: *this, ResultType: CharTy))
251 Result.getArrayInitializedElt(I) = *ElemVal;
252 else
253 return false;
254 }
255 } else {
256 assert((std::is_same_v<ResultT, std::string>));
257 if (Size < Result.max_size())
258 Result.resize(Size);
259
260 const char *Addr = reinterpret_cast<const char *>(Ptr.getRawAddress());
261
262 if (Ptr.isStringPointer())
263 Result.assign(Addr, Size - static_cast<unsigned>(Limited));
264 else
265 Result.assign(Addr, Size);
266 }
267
268 return true;
269 });
270
271 if (PtrRes.isInvalid()) {
272 C.cleanup();
273 Stk.clear();
274 return false;
275 }
276
277 return true;
278}
279
280bool Context::evaluateCharRange(const EvalSettings &Settings,
281 const Expr *SizeExpr, const Expr *PtrExpr,
282 APValue &Result) {
283 assert(SizeExpr);
284 assert(PtrExpr);
285
286 return evaluateStringRepr(Settings, SizeExpr, PtrExpr, Result);
287}
288
289bool Context::evaluateCharRange(const EvalSettings &Settings,
290 const Expr *SizeExpr, const Expr *PtrExpr,
291 std::string &Result) {
292 assert(SizeExpr);
293 assert(PtrExpr);
294
295 return evaluateStringRepr(Settings, SizeExpr, PtrExpr, Result);
296}
297
298bool Context::evaluateString(const EvalSettings &Settings, const Expr *E,
299 std::string &Result) {
300 assert(Stk.empty());
301 Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
302
303 auto PtrRes = C.interpretAsPointer(E, PtrCB: [&](InterpState &S, CodePtr OpPC,
304 const Pointer &Ptr) {
305 if (!Ptr.isReadablePointerType())
306 return false;
307
308 if (!Ptr.isConst())
309 return false;
310
311 if (Ptr.isDummy() || Ptr.isUnknownSizeArray() || Ptr.isPastEnd())
312 return false;
313
314 unsigned N = Ptr.getNumElems();
315
316 if (Ptr.elemSize() == 1 /* bytes */) {
317 const char *Chars = reinterpret_cast<const char *>(Ptr.getRawAddress());
318 if (Ptr.isStringPointer()) {
319 Result.assign(s: Chars, n: N - 1);
320 return true;
321 }
322 unsigned Length = strnlen(string: Chars, maxlen: N);
323 // Wasn't null terminated.
324 if (N == Length)
325 return false;
326 Result.assign(s: Chars, n: Length);
327 return true;
328 }
329
330 PrimType ElemT;
331 if (Ptr.isBlockPointer()) {
332 ElemT = Ptr.getFieldDesc()->getPrimType();
333 } else {
334 // It may happen here that the string literal has not been decayed or
335 // indexed, so check the element type in that case.
336 assert(Ptr.isStringPointer());
337 if (!Ptr.asStringPointer().Decayed)
338 ElemT =
339 *classify(T: Ptr.getType()->getAsArrayTypeUnsafe()->getElementType());
340 else
341 ElemT = *classify(T: Ptr.getType());
342 }
343 for (unsigned I = Ptr.getIndex(); I != N; ++I) {
344 INT_TYPE_SWITCH(ElemT, {
345 auto Elem = Ptr.loadElem<T>(I);
346 if (Elem.isZero())
347 return true;
348 Result.push_back(static_cast<char>(Elem));
349 });
350 }
351 // We didn't find a 0 byte.
352 return false;
353 });
354
355 if (PtrRes.isInvalid()) {
356 C.cleanup();
357 Stk.clear();
358 return false;
359 }
360 return true;
361}
362
363std::optional<uint64_t> Context::evaluateStrlen(const EvalSettings &Settings,
364 const Expr *E) {
365 assert(Stk.empty());
366 Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
367
368 std::optional<uint64_t> Result;
369 auto PtrRes = C.interpretAsPointer(E, PtrCB: [&](InterpState &S, CodePtr OpPC,
370 const Pointer &Ptr) {
371 if (!Ptr.isReadablePointerType())
372 return false;
373
374 if (Ptr.isPastEnd())
375 return false;
376
377 if (Ptr.isStringPointer()) {
378 const auto *Lit = Ptr.asStringPointer().getLiteral();
379 int64_t Off = Ptr.getByteOffset();
380 if (Off < 0)
381 return false;
382
383 UnsignedOrNone ZeroIndex = Lit->findZeroCodeUnit(StartIndex: Off);
384 if (!ZeroIndex)
385 return false;
386 Result = *ZeroIndex;
387 return true;
388 }
389
390 const Descriptor *FieldDesc = Ptr.getFieldDesc();
391 if (!FieldDesc->isPrimitiveArray())
392 return false;
393
394 if (Ptr.isDummy() || Ptr.isUnknownSizeArray())
395 return false;
396
397 PrimType ElemT = FieldDesc->getPrimType();
398 if (!isIntegerType(T: ElemT))
399 return false;
400
401 unsigned N = Ptr.getNumElems();
402 if (Ptr.elemSize() == 1) {
403 unsigned Size = N - Ptr.getIndex();
404 Result =
405 strnlen(string: reinterpret_cast<const char *>(Ptr.getRawAddress()), maxlen: Size);
406 return Result != Size;
407 }
408
409 Result = 0;
410 for (unsigned I = Ptr.getIndex(); I != N; ++I) {
411 INT_TYPE_SWITCH(ElemT, {
412 auto Elem = Ptr.elem<T>(I);
413 if (Elem.isZero())
414 return true;
415 ++(*Result);
416 });
417 }
418 // We didn't find a 0 byte.
419 return false;
420 });
421
422 if (PtrRes.isInvalid()) {
423 C.cleanup();
424 Stk.clear();
425 return std::nullopt;
426 }
427 return Result;
428}
429
430std::optional<uint64_t>
431Context::tryEvaluateObjectSize(const EvalSettings &Settings, const Expr *E,
432 unsigned Kind, bool IsDynamic) {
433 assert(Stk.empty());
434 Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
435
436 std::optional<uint64_t> Result;
437 auto PtrRes = C.interpretAsLValuePointer(E, PtrCB: [&](InterpState &S, CodePtr OpPC,
438 const Pointer &Ptr) {
439 QualType T = Ptr.getType().getNonReferenceType();
440 if (T->isIncompleteType() || T->isFunctionType() ||
441 !T->isConstantSizeType())
442 return false;
443
444 Pointer P = Ptr;
445 if (auto ObjectSize =
446 evaluateBuiltinObjectSize(ASTCtx: getASTContext(), Kind, Ptr&: P, E, IsDynamic)) {
447 Result = *ObjectSize;
448 return true;
449 }
450 return false;
451 });
452
453 if (PtrRes.isInvalid()) {
454 C.cleanup();
455 Stk.clear();
456 return std::nullopt;
457 }
458 return Result;
459}
460
461std::optional<bool> Context::evaluateWithSubstitution(
462 const EvalSettings &Settings, const FunctionDecl *Callee,
463 ArrayRef<const Expr *> Args, const Expr *This, const Expr *Condition) {
464 if (OptPrimType ConditionT = classify(E: Condition);
465 !ConditionT || ConditionT != PT_Bool) {
466 return std::nullopt;
467 }
468
469 assert(Stk.empty());
470 Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
471 std::optional<bool> Result =
472 C.interpretWithSubstitutions(Callee, Args, This, Condition);
473
474 // This is somewhat of a special case here. We don't allow
475 // evaluateWithSubstitution to recurse (see the Stk.empty() assertion above),
476 // BUT we allow the args to fail evaluation, which means they can leave some
477 // garbage on the stack. So we always clear() here, not only if the evaluation
478 // failed.
479 Stk.clear();
480 if (!Result) {
481 C.cleanup();
482 return std::nullopt;
483 }
484 return Result;
485}
486
487const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
488
489static PrimType integralTypeToPrimTypeS(unsigned BitWidth) {
490 switch (BitWidth) {
491 case 64:
492 return PT_Sint64;
493 case 32:
494 return PT_Sint32;
495 case 16:
496 return PT_Sint16;
497 case 8:
498 return PT_Sint8;
499 default:
500 return PT_IntAPS;
501 }
502 llvm_unreachable("Unhandled BitWidth");
503}
504
505static PrimType integralTypeToPrimTypeU(unsigned BitWidth) {
506 switch (BitWidth) {
507 case 64:
508 return PT_Uint64;
509 case 32:
510 return PT_Uint32;
511 case 16:
512 return PT_Uint16;
513 case 8:
514 return PT_Uint8;
515 default:
516 return PT_IntAP;
517 }
518 llvm_unreachable("Unhandled BitWidth");
519}
520
521OptPrimType Context::classify(QualType T) const {
522 T = T.getCanonicalType();
523
524 if (const auto *BT = dyn_cast<BuiltinType>(Val&: T)) {
525 auto Kind = BT->getKind();
526 if (Kind == BuiltinType::Bool)
527 return PT_Bool;
528 if (Kind == BuiltinType::NullPtr)
529 return PT_Ptr;
530 if (Kind == BuiltinType::BoundMember)
531 return PT_MemberPtr;
532
533 // Just trying to avoid the ASTContext::getIntWidth call below.
534 if (Kind == BuiltinType::Short)
535 return integralTypeToPrimTypeS(BitWidth: this->ShortWidth);
536 if (Kind == BuiltinType::UShort)
537 return integralTypeToPrimTypeU(BitWidth: this->ShortWidth);
538
539 if (Kind == BuiltinType::Int)
540 return integralTypeToPrimTypeS(BitWidth: this->IntWidth);
541 if (Kind == BuiltinType::UInt)
542 return integralTypeToPrimTypeU(BitWidth: this->IntWidth);
543 if (Kind == BuiltinType::Long)
544 return integralTypeToPrimTypeS(BitWidth: this->LongWidth);
545 if (Kind == BuiltinType::ULong)
546 return integralTypeToPrimTypeU(BitWidth: this->LongWidth);
547 if (Kind == BuiltinType::LongLong)
548 return integralTypeToPrimTypeS(BitWidth: this->LongLongWidth);
549 if (Kind == BuiltinType::ULongLong)
550 return integralTypeToPrimTypeU(BitWidth: this->LongLongWidth);
551
552 if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S)
553 return integralTypeToPrimTypeS(BitWidth: 8);
554 if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U ||
555 Kind == BuiltinType::Char8)
556 return integralTypeToPrimTypeU(BitWidth: 8);
557
558 if (BT->isSignedInteger())
559 return integralTypeToPrimTypeS(BitWidth: Ctx.getIntWidth(T));
560 if (BT->isUnsignedInteger())
561 return integralTypeToPrimTypeU(BitWidth: Ctx.getIntWidth(T));
562
563 if (BT->isFloatingPoint())
564 return PT_Float;
565 }
566
567 if (T->isPointerOrReferenceType())
568 return PT_Ptr;
569
570 if (T->isMemberPointerType())
571 return PT_MemberPtr;
572
573 if (const auto *BT = T->getAs<BitIntType>()) {
574 if (BT->isSigned())
575 return integralTypeToPrimTypeS(BitWidth: BT->getNumBits());
576 return integralTypeToPrimTypeU(BitWidth: BT->getNumBits());
577 }
578
579 if (const auto *D = T->getAsEnumDecl()) {
580 if (!D->isComplete())
581 return std::nullopt;
582 return classify(T: D->getIntegerType());
583 }
584
585 if (const auto *AT = T->getAs<AtomicType>())
586 return classify(T: AT->getValueType());
587
588 if (const auto *OBT = T->getAs<OverflowBehaviorType>())
589 return classify(T: OBT->getUnderlyingType());
590
591 if (T->isObjCObjectPointerType() || T->isBlockPointerType())
592 return PT_Ptr;
593
594 if (T->isFixedPointType())
595 return PT_FixedPoint;
596
597 if (T->isMetaInfoType())
598 return PT_Reflect;
599
600 // Vector and complex types get here.
601 return std::nullopt;
602}
603
604unsigned Context::getCharBit() const {
605 return Ctx.getTargetInfo().getCharWidth();
606}
607
608/// Simple wrapper around getFloatTypeSemantics() to make code a
609/// little shorter.
610const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const {
611 return Ctx.getFloatTypeSemantics(T);
612}
613
614bool Context::Run(const EvalSettings &Settings, const Function *Func) {
615 auto Memory = std::make_unique<char[]>(num: InterpFrame::allocSize(F: Func));
616 InterpState State(Settings, *P, Stk, FrameAlloc, *this, Func);
617 InterpFrame *Frame = new (Memory.get()) InterpFrame(
618 State, Func, /*Caller=*/nullptr, CodePtr(), Func->getArgSize());
619 State.Current = Frame;
620
621 if (Interpret(S&: State)) {
622 assert(Stk.empty());
623 return true;
624 }
625
626 Stk.clear();
627 Frame->~InterpFrame();
628 State.Current = &State.BottomFrame;
629 return false;
630}
631
632const CXXMethodDecl *
633Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl,
634 const CXXRecordDecl *StaticDecl,
635 const CXXMethodDecl *InitialFunction) const {
636 assert(DynamicDecl);
637 assert(StaticDecl);
638 assert(InitialFunction);
639
640 const CXXRecordDecl *CurRecord = DynamicDecl;
641 const CXXMethodDecl *FoundFunction = InitialFunction;
642 for (;;) {
643 const CXXMethodDecl *Overrider =
644 FoundFunction->getCorrespondingMethodDeclaredInClass(RD: CurRecord, MayBeBase: false);
645 if (Overrider)
646 return Overrider;
647
648 // Common case of only one base class.
649 if (CurRecord->getNumBases() == 1) {
650 CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl();
651 continue;
652 }
653
654 // Otherwise, go to the base class that will lead to the StaticDecl.
655 for (const CXXBaseSpecifier &Spec : CurRecord->bases()) {
656 const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl();
657 if (Base == StaticDecl || Base->isDerivedFrom(Base: StaticDecl)) {
658 CurRecord = Base;
659 break;
660 }
661 }
662 }
663
664 llvm_unreachable(
665 "Couldn't find an overriding function in the class hierarchy?");
666 return nullptr;
667}
668
669const Function *Context::getOrCreateFunction(const FunctionDecl *FuncDecl) {
670 assert(FuncDecl);
671 if (const Function *Func = P->getFunction(F: FuncDecl))
672 return Func;
673
674 // Manually created functions that haven't been assigned proper
675 // parameters yet.
676 if (!FuncDecl->param_empty() && !FuncDecl->param_begin())
677 return nullptr;
678
679 bool IsLambdaStaticInvoker = false;
680 if (const auto *MD = dyn_cast<CXXMethodDecl>(Val: FuncDecl);
681 MD && MD->isLambdaStaticInvoker()) {
682 // For a lambda static invoker, we might have to pick a specialized
683 // version if the lambda is generic. In that case, the picked function
684 // will *NOT* be a static invoker anymore. However, it will still
685 // be a non-static member function, this (usually) requiring an
686 // instance pointer. We suppress that later in this function.
687 IsLambdaStaticInvoker = true;
688 }
689 // Set up argument indices.
690 unsigned ParamOffset = 0;
691
692 // If the return is not a primitive, a pointer to the storage where the
693 // value is initialized in is passed as the first argument. See 'RVO'
694 // elsewhere in the code.
695 QualType Ty = FuncDecl->getReturnType();
696 bool HasRVO = false;
697 if (!Ty->isVoidType() && !canClassify(T: Ty)) {
698 HasRVO = true;
699 ParamOffset += align(Size: primSize(Type: PT_Ptr));
700 }
701
702 // If the function decl is a member decl, the next parameter is
703 // the 'this' pointer. This parameter is pop()ed from the
704 // InterpStack when calling the function.
705 bool HasThisPointer = false;
706 if (const auto *MD = dyn_cast<CXXMethodDecl>(Val: FuncDecl)) {
707 if (!IsLambdaStaticInvoker) {
708 HasThisPointer = MD->isInstance();
709 if (MD->isImplicitObjectMemberFunction())
710 ParamOffset += align(Size: primSize(Type: PT_Ptr));
711 }
712
713 if (isLambdaCallOperator(MD)) {
714 // The parent record needs to be complete, we need to know about all
715 // the lambda captures.
716 if (!MD->getParent()->isCompleteDefinition())
717 return nullptr;
718 if (MD->isStatic()) {
719 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
720 FieldDecl *LTC;
721
722 MD->getParent()->getCaptureFields(Captures&: LC, ThisCapture&: LTC);
723 // Static lambdas cannot have any captures. If this one does,
724 // it has already been diagnosed and we can only ignore it.
725 if (!LC.empty())
726 return nullptr;
727 }
728 }
729 }
730
731 // Assign descriptors to all parameters.
732 // Composite objects are lowered to pointers.
733 llvm::SmallVector<Function::ParamDescriptor> ParamDescriptors;
734 ParamDescriptors.reserve(N: FuncDecl->getNumParams());
735
736 const auto *FuncProto = FuncDecl->getType()->getAs<FunctionProtoType>();
737 unsigned BlockOffset = 0;
738 for (auto [ParamIndex, PD] : llvm::enumerate(First: FuncDecl->parameters())) {
739 bool IsConst = PD->getType().isConstQualified();
740 bool IsVolatile = PD->getType().isVolatileQualified();
741
742 if (PD->isInvalidDecl() ||
743 !getASTContext().hasSameType(T1: PD->getType(),
744 T2: FuncProto->getParamType(i: ParamIndex)))
745 return nullptr;
746
747 OptPrimType T = classify(T: PD->getType());
748 PrimType PT = T.value_or(PT: PT_Ptr);
749 Descriptor *Desc = P->createDescriptor(D: PD, T: PT, SourceTy: nullptr, IsConst,
750 /*IsTemporary=*/false,
751 /*IsMutable=*/false, IsVolatile);
752 unsigned PrimTSize = align(Size: primSize(Type: PT));
753 ParamDescriptors.emplace_back(Args&: Desc, Args&: ParamOffset, Args&: BlockOffset, Args&: PT);
754 ParamOffset += PrimTSize;
755 BlockOffset += sizeof(Block) + PrimTSize;
756 }
757
758 // Create a handle over the emitted code.
759 assert(!P->getFunction(FuncDecl));
760 const Function *Func =
761 P->createFunction(Def: FuncDecl, Args&: ParamOffset, Args: std::move(ParamDescriptors),
762 Args&: HasThisPointer, Args&: HasRVO, Args&: IsLambdaStaticInvoker);
763 return Func;
764}
765
766const Function *Context::getOrCreateObjCBlock(const BlockExpr *E) {
767 const BlockDecl *BD = E->getBlockDecl();
768 // Set up argument indices.
769 unsigned ParamOffset = 0;
770 llvm::SmallVector<Function::ParamDescriptor> ParamDescriptors;
771
772 // Assign descriptors to all parameters.
773 // Composite objects are lowered to pointers.
774 for (const ParmVarDecl *PD : BD->parameters()) {
775 bool IsConst = PD->getType().isConstQualified();
776 bool IsVolatile = PD->getType().isVolatileQualified();
777
778 OptPrimType T = classify(T: PD->getType());
779 PrimType PT = T.value_or(PT: PT_Ptr);
780 Descriptor *Desc = P->createDescriptor(D: PD, T: PT, SourceTy: nullptr, IsConst,
781 /*IsTemporary=*/false,
782 /*IsMutable=*/false, IsVolatile);
783 ParamDescriptors.emplace_back(Args&: Desc, Args&: ParamOffset, Args: ~0u, Args&: PT);
784 ParamOffset += align(Size: primSize(Type: PT));
785 }
786
787 if (BD->hasCaptures())
788 return nullptr;
789
790 // Create a handle over the emitted code.
791 Function *Func =
792 P->createFunction(Args&: E, Args&: ParamOffset, Args: std::move(ParamDescriptors),
793 /*HasThisPointer=*/Args: false, /*HasRVO=*/Args: false,
794 /*IsLambdaStaticInvoker=*/Args: false);
795
796 assert(Func);
797 Func->setDefined(true);
798 // We don't compile the BlockDecl code at all right now.
799 Func->setIsFullyCompiled(true);
800
801 return Func;
802}
803
804unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
805 const RecordDecl *DerivedDecl) const {
806 assert(BaseDecl);
807 assert(DerivedDecl);
808 const auto *FinalDecl = cast<CXXRecordDecl>(Val: BaseDecl);
809 const RecordDecl *CurDecl = DerivedDecl;
810 const Record *CurRecord = P->getOrCreateRecord(RD: CurDecl);
811 assert(CurDecl && FinalDecl);
812
813 unsigned OffsetSum = 0;
814 for (;;) {
815 assert(CurRecord->getNumBases() > 0);
816 // One level up
817 for (const Record::Base &B : CurRecord->bases()) {
818 const auto *BaseDecl = cast<CXXRecordDecl>(Val: B.Decl);
819
820 if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(Base: FinalDecl)) {
821 OffsetSum += B.Offset;
822 CurRecord = B.R;
823 CurDecl = BaseDecl;
824 break;
825 }
826 }
827 if (CurDecl == FinalDecl)
828 break;
829 }
830
831 assert(OffsetSum > 0);
832 return OffsetSum;
833}
834
835const Record *Context::getRecord(const RecordDecl *D) const {
836 return P->getOrCreateRecord(RD: D);
837}
838
839bool Context::isUnevaluatedBuiltin(unsigned ID) {
840 return ID == Builtin::BI__builtin_classify_type ||
841 ID == Builtin::BI__builtin_os_log_format_buffer_size ||
842 ID == Builtin::BI__builtin_constant_p || ID == Builtin::BI__noop;
843}
844