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