35 using LabelTy =
typename ByteCodeStmtGen<Emitter>::LabelTy;
36 using OptLabelTy =
typename ByteCodeStmtGen<Emitter>::OptLabelTy;
41 OldContinueLabel(
Ctx->ContinueLabel) {
42 this->Ctx->BreakLabel = BreakLabel;
43 this->Ctx->ContinueLabel = ContinueLabel;
47 this->
Ctx->BreakLabel = OldBreakLabel;
48 this->
Ctx->ContinueLabel = OldContinueLabel;
59 using LabelTy =
typename ByteCodeStmtGen<Emitter>::LabelTy;
60 using OptLabelTy =
typename ByteCodeStmtGen<Emitter>::OptLabelTy;
61 using CaseMap =
typename ByteCodeStmtGen<Emitter>::CaseMap;
66 OldDefaultLabel(this->
Ctx->DefaultLabel),
67 OldCaseLabels(
std::move(this->
Ctx->CaseLabels)) {
68 this->Ctx->BreakLabel = BreakLabel;
69 this->Ctx->DefaultLabel = DefaultLabel;
70 this->Ctx->CaseLabels = std::move(CaseLabels);
74 this->
Ctx->BreakLabel = OldBreakLabel;
75 this->
Ctx->DefaultLabel = OldDefaultLabel;
76 this->
Ctx->CaseLabels = std::move(OldCaseLabels);
88template <
class Emitter>
93 assert(cast<CompoundStmt>(MD->
getBody())->body_empty());
101 assert(
Func->hasThisPointer());
104 if (
Func->hasRVO()) {
105 if (!this->emitRVOPtr(MD))
113 if (!this->emitNullPtr(
nullptr, MD))
118 auto It = this->Params.find(PVD);
119 assert(It != this->Params.end());
123 PrimType ParamType = this->classify(PVD->getType()).value_or(
PT_Ptr);
124 if (!this->emitGetParam(ParamType, It->second.Offset, MD))
128 if (!this->emitCall(
Func, 0, LambdaCallOp))
133 return this->emitRet(*ReturnType, MD);
136 return this->emitRetVoid(MD);
139template <
class Emitter>
144 auto emitFieldInitializer = [&](
const Record::Field *F,
unsigned FieldOffset,
145 const Expr *InitExpr) ->
bool {
147 if (InitExpr->getType().isNull())
150 if (std::optional<PrimType>
T = this->classify(InitExpr)) {
151 if (!this->visit(InitExpr))
155 return this->emitInitThisBitField(*
T, F, FieldOffset, InitExpr);
156 return this->emitInitThisField(*
T, FieldOffset, InitExpr);
160 if (!this->emitGetPtrThisField(FieldOffset, InitExpr))
163 if (!this->visitInitializer(InitExpr))
166 return this->emitPopPtr(InitExpr);
170 if (
const auto *MD = dyn_cast<CXXMethodDecl>(F);
172 return this->emitLambdaStaticInvokerBody(MD);
175 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(F)) {
177 const Record *R = this->getRecord(RD);
181 for (
const auto *
Init : Ctor->inits()) {
185 const Expr *InitExpr =
Init->getInit();
189 if (!emitFieldInitializer(F, F->Offset, InitExpr))
192 const auto *BaseDecl =
Base->getAsCXXRecordDecl();
195 if (
Init->isBaseVirtual()) {
197 if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))
203 const Record::Base *B = R->
getBase(BaseDecl);
205 if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
209 if (!this->visitInitializer(InitExpr))
211 if (!this->emitFinishInitPop(InitExpr))
214 assert(IFD->getChainingSize() >= 2);
216 unsigned NestedFieldOffset = 0;
217 const Record::Field *NestedField =
nullptr;
218 for (
const NamedDecl *ND : IFD->chain()) {
219 const auto *FD = cast<FieldDecl>(ND);
220 const Record *FieldRecord =
221 this->
P.getOrCreateRecord(FD->getParent());
224 NestedField = FieldRecord->
getField(FD);
227 NestedFieldOffset += NestedField->Offset;
231 if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr))
234 assert(
Init->isDelegatingInitializer());
235 if (!this->emitThis(InitExpr))
237 if (!this->visitInitializer(
Init->getInit()))
239 if (!this->emitPopPtr(InitExpr))
245 if (
const auto *Body = F->
getBody())
246 if (!visitStmt(Body))
256template <
class Emitter>
258 switch (S->getStmtClass()) {
259 case Stmt::CompoundStmtClass:
260 return visitCompoundStmt(cast<CompoundStmt>(S));
261 case Stmt::DeclStmtClass:
262 return visitDeclStmt(cast<DeclStmt>(S));
263 case Stmt::ReturnStmtClass:
264 return visitReturnStmt(cast<ReturnStmt>(S));
265 case Stmt::IfStmtClass:
266 return visitIfStmt(cast<IfStmt>(S));
267 case Stmt::WhileStmtClass:
268 return visitWhileStmt(cast<WhileStmt>(S));
269 case Stmt::DoStmtClass:
270 return visitDoStmt(cast<DoStmt>(S));
271 case Stmt::ForStmtClass:
272 return visitForStmt(cast<ForStmt>(S));
273 case Stmt::CXXForRangeStmtClass:
274 return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
275 case Stmt::BreakStmtClass:
276 return visitBreakStmt(cast<BreakStmt>(S));
277 case Stmt::ContinueStmtClass:
278 return visitContinueStmt(cast<ContinueStmt>(S));
279 case Stmt::SwitchStmtClass:
280 return visitSwitchStmt(cast<SwitchStmt>(S));
281 case Stmt::CaseStmtClass:
282 return visitCaseStmt(cast<CaseStmt>(S));
283 case Stmt::DefaultStmtClass:
284 return visitDefaultStmt(cast<DefaultStmt>(S));
285 case Stmt::AttributedStmtClass:
286 return visitAttributedStmt(cast<AttributedStmt>(S));
287 case Stmt::CXXTryStmtClass:
288 return visitCXXTryStmt(cast<CXXTryStmt>(S));
289 case Stmt::NullStmtClass:
292 case Stmt::GCCAsmStmtClass:
293 case Stmt::MSAsmStmtClass:
294 case Stmt::GotoStmtClass:
295 return this->emitInvalid(S);
296 case Stmt::LabelStmtClass:
297 return this->visitStmt(cast<LabelStmt>(S)->getSubStmt());
299 if (
auto *Exp = dyn_cast<Expr>(S))
300 return this->discard(Exp);
308template <
class Emitter>
310 if (isa<NullStmt>(S))
313 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
314 for (
auto *InnerStmt : CS->body())
315 if (!visitStmt(InnerStmt))
320 return this->visitStmt(S);
323template <
class Emitter>
328 if (!visitStmt(InnerStmt))
333template <
class Emitter>
335 for (
auto *D : DS->
decls()) {
340 const auto *VD = dyn_cast<VarDecl>(D);
343 if (!this->visitVarDecl(VD))
350template <
class Emitter>
356 if (!this->visit(RE))
359 return this->emitRet(*ReturnType, RS);
360 }
else if (RE->getType()->isVoidType()) {
361 if (!this->visit(RE))
365 if (!this->emitRVOPtr(RE))
367 if (!this->visitInitializer(RE))
369 if (!this->emitPopPtr(RE))
373 return this->emitRetVoid(RS);
379 return this->emitRetVoid(RS);
382template <
class Emitter>
387 return visitStmt(IS->
getThen());
391 if (
auto *CondInit = IS->
getInit())
392 if (!visitStmt(CondInit))
396 if (!visitDeclStmt(CondDecl))
399 if (!this->visitBool(IS->
getCond()))
403 LabelTy LabelElse = this->getLabel();
404 LabelTy LabelEnd = this->getLabel();
405 if (!this->jumpFalse(LabelElse))
409 if (!this->jump(LabelEnd))
411 this->emitLabel(LabelElse);
412 if (!visitStmt(Else))
414 this->emitLabel(LabelEnd);
416 LabelTy LabelEnd = this->getLabel();
417 if (!this->jumpFalse(LabelEnd))
421 this->emitLabel(LabelEnd);
427template <
class Emitter>
429 const Expr *Cond = S->getCond();
430 const Stmt *Body = S->getBody();
432 LabelTy CondLabel = this->getLabel();
433 LabelTy EndLabel = this->getLabel();
436 this->emitLabel(CondLabel);
438 if (
const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
439 if (!visitDeclStmt(CondDecl))
442 if (!this->visitBool(Cond))
444 if (!this->jumpFalse(EndLabel))
450 if (!this->visitLoopBody(Body))
454 if (!this->jump(CondLabel))
456 this->emitLabel(EndLabel);
461template <
class Emitter>
463 const Expr *Cond = S->getCond();
464 const Stmt *Body = S->getBody();
466 LabelTy StartLabel = this->getLabel();
467 LabelTy EndLabel = this->getLabel();
468 LabelTy CondLabel = this->getLabel();
472 this->emitLabel(StartLabel);
476 if (!this->visitLoopBody(Body))
478 this->emitLabel(CondLabel);
479 if (!this->visitBool(Cond))
482 if (!this->jumpTrue(StartLabel))
485 this->emitLabel(EndLabel);
489template <
class Emitter>
493 const Expr *Cond = S->getCond();
495 const Stmt *Body = S->getBody();
497 LabelTy EndLabel = this->getLabel();
498 LabelTy CondLabel = this->getLabel();
499 LabelTy IncLabel = this->getLabel();
505 this->emitLabel(CondLabel);
507 if (
const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
508 if (!visitDeclStmt(CondDecl))
511 if (!this->visitBool(Cond))
513 if (!this->jumpFalse(EndLabel))
520 if (Body && !this->visitLoopBody(Body))
522 this->emitLabel(IncLabel);
523 if (
Inc && !this->discard(
Inc))
527 if (!this->jump(CondLabel))
529 this->emitLabel(EndLabel);
533template <
class Emitter>
536 const Expr *Cond = S->getCond();
538 const Stmt *Body = S->getBody();
539 const Stmt *BeginStmt = S->getBeginStmt();
540 const Stmt *RangeStmt = S->getRangeStmt();
541 const Stmt *EndStmt = S->getEndStmt();
542 const VarDecl *LoopVar = S->getLoopVariable();
544 LabelTy EndLabel = this->getLabel();
545 LabelTy CondLabel = this->getLabel();
546 LabelTy IncLabel = this->getLabel();
552 if (!this->visitStmt(RangeStmt))
554 if (!this->visitStmt(BeginStmt))
556 if (!this->visitStmt(EndStmt))
560 this->emitLabel(CondLabel);
561 if (!this->visitBool(Cond))
563 if (!this->jumpFalse(EndLabel))
566 if (!this->visitVarDecl(LoopVar))
574 if (!this->visitLoopBody(Body))
576 this->emitLabel(IncLabel);
577 if (!this->discard(
Inc))
580 if (!this->jump(CondLabel))
583 this->emitLabel(EndLabel);
587template <
class Emitter>
592 this->VarScope->emitDestructors();
593 return this->jump(*BreakLabel);
596template <
class Emitter>
601 this->VarScope->emitDestructors();
602 return this->jump(*ContinueLabel);
605template <
class Emitter>
607 const Expr *Cond = S->getCond();
609 LabelTy EndLabel = this->getLabel();
610 OptLabelTy DefaultLabel = std::nullopt;
612 if (
const auto *CondInit = S->getInit())
613 if (!visitStmt(CondInit))
616 if (
const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
617 if (!visitDeclStmt(CondDecl))
622 unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT,
true,
false);
623 if (!this->visit(Cond))
625 if (!this->emitSetLocal(CondT, CondVar, S))
630 for (
const SwitchCase *SC = S->getSwitchCaseList(); SC;
631 SC = SC->getNextSwitchCase()) {
632 if (
const auto *CS = dyn_cast<CaseStmt>(SC)) {
634 if (CS->caseStmtIsGNURange())
636 CaseLabels[SC] = this->getLabel();
642 if (!this->emitGetLocal(CondT, CondVar, CS))
644 if (!this->visit(
Value))
648 if (!this->emitEQ(ValueT, S))
650 if (!this->jumpTrue(CaseLabels[CS]))
653 assert(!DefaultLabel);
654 DefaultLabel = this->getLabel();
661 if (!this->jump(*DefaultLabel))
664 if (!this->jump(EndLabel))
669 if (!this->visitStmt(S->getBody()))
671 this->emitLabel(EndLabel);
675template <
class Emitter>
677 this->emitLabel(CaseLabels[S]);
678 return this->visitStmt(S->getSubStmt());
681template <
class Emitter>
683 this->emitLabel(*DefaultLabel);
684 return this->visitStmt(S->getSubStmt());
687template <
class Emitter>
690 for (
const Attr *A : S->getAttrs()) {
691 auto *AA = dyn_cast<CXXAssumeAttr>(A);
695 assert(isa<NullStmt>(S->getSubStmt()));
697 const Expr *Assumption = AA->getAssumption();
705 if (!this->visitBool(Assumption))
708 if (!this->emitAssume(Assumption))
713 return this->visitStmt(S->getSubStmt());
716template <
class Emitter>
719 return this->visitStmt(S->getTryBlock());
Attr - This represents one attribute.
Represents an attribute applied to a statement.
BreakStmt - This represents a break.
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
bool isLambdaStaticInvoker() const
Determine whether this is a lambda closure type's static member function that is used for the result ...
Represents a C++ struct/union/class.
capture_const_iterator captures_end() const
capture_const_iterator captures_begin() const
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
CXXTryStmt - A C++ try block, including all handlers.
CaseStmt - Represent a case statement.
CompoundStmt - This represents a group of statements like { stmt stmt }.
ContinueStmt - This represents a continue.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
DoStmt - This represents a 'do/while' stmt.
This represents one expression.
bool isValueDependent() const
Determines whether the value of this expression depends on.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Represents a member of a struct/union/class.
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Represents a function declaration or definition.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
IfStmt - This represents an if/then/else.
bool isNonNegatedConsteval() const
bool isNegatedConsteval() const
DeclStmt * getConditionVariableDeclStmt()
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
Represents a field injected from an anonymous union/struct into the parent scope.
This represents a decl that may have a name.
Represents a parameter to a function.
Represents a struct/union/class.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Scope - A scope is a transient data structure that is used while parsing the program.
Represents a C++11 static_assert declaration.
Stmt - This represents one statement.
SwitchStmt - This represents a 'switch' stmt.
Represents the declaration of a struct/union/class/enum.
The base class of the type hierarchy.
Base class for declarations which introduce a typedef-name.
Represents a C++ using-enum-declaration.
Represents a variable declaration or definition.
WhileStmt - This represents a 'while' stmt.
Scope for storage declared in a compound statement.
Compilation context for statements.
bool visitFunc(const FunctionDecl *F) override
Emits the destructors of the variables of.
Scope managing label targets.
LabelScope(ByteCodeStmtGen< Emitter > *Ctx)
ByteCodeStmtGen< Emitter > * Ctx
ByteCodeStmtGen instance.
Generic scope for local variables.
Sets the context for break/continue statements.
LoopScope(ByteCodeStmtGen< Emitter > *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel)
typename ByteCodeStmtGen< Emitter >::LabelTy LabelTy
typename ByteCodeStmtGen< Emitter >::OptLabelTy OptLabelTy
Structure/Class descriptor.
const Field * getField(const FieldDecl *FD) const
Returns a field.
const Base * getVirtualBase(const RecordDecl *RD) const
Returns a virtual base descriptor.
const Base * getBase(const RecordDecl *FD) const
Returns a base descriptor.
Describes the statement/declaration an opcode was generated from.
typename ByteCodeStmtGen< Emitter >::LabelTy LabelTy
SwitchScope(ByteCodeStmtGen< Emitter > *Ctx, CaseMap &&CaseLabels, LabelTy BreakLabel, OptLabelTy DefaultLabel)
typename ByteCodeStmtGen< Emitter >::OptLabelTy OptLabelTy
typename ByteCodeStmtGen< Emitter >::CaseMap CaseMap
PrimType
Enumeration of the primitive types of the VM.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T