36 using LabelTy =
typename ByteCodeStmtGen<Emitter>::LabelTy;
37 using OptLabelTy =
typename ByteCodeStmtGen<Emitter>::OptLabelTy;
42 OldContinueLabel(
Ctx->ContinueLabel) {
43 this->Ctx->BreakLabel = BreakLabel;
44 this->Ctx->ContinueLabel = ContinueLabel;
48 this->
Ctx->BreakLabel = OldBreakLabel;
49 this->
Ctx->ContinueLabel = OldContinueLabel;
60 using LabelTy =
typename ByteCodeStmtGen<Emitter>::LabelTy;
61 using OptLabelTy =
typename ByteCodeStmtGen<Emitter>::OptLabelTy;
62 using CaseMap =
typename ByteCodeStmtGen<Emitter>::CaseMap;
67 OldDefaultLabel(this->
Ctx->DefaultLabel),
68 OldCaseLabels(
std::move(this->
Ctx->CaseLabels)) {
69 this->Ctx->BreakLabel = BreakLabel;
70 this->Ctx->DefaultLabel = DefaultLabel;
71 this->Ctx->CaseLabels = std::move(CaseLabels);
75 this->
Ctx->BreakLabel = OldBreakLabel;
76 this->
Ctx->DefaultLabel = OldDefaultLabel;
77 this->
Ctx->CaseLabels = std::move(OldCaseLabels);
89template <
class Emitter>
94 assert(cast<CompoundStmt>(MD->
getBody())->body_empty());
102 assert(
Func->hasThisPointer());
105 if (
Func->hasRVO()) {
106 if (!this->emitRVOPtr(MD))
114 if (!this->emitNullPtr(MD))
119 auto It = this->Params.find(PVD);
120 assert(It != this->Params.end());
124 PrimType ParamType = this->classify(PVD->getType()).value_or(
PT_Ptr);
125 if (!this->emitGetParam(ParamType, It->second.Offset, MD))
129 if (!this->emitCall(
Func, LambdaCallOp))
134 return this->emitRet(*ReturnType, MD);
137 return this->emitRetVoid(MD);
140template <
class Emitter>
146 if (
const auto *MD = dyn_cast<CXXMethodDecl>(F);
148 return this->emitLambdaStaticInvokerBody(MD);
151 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(F)) {
153 const Record *R = this->getRecord(RD);
157 for (
const auto *
Init : Ctor->inits()) {
161 const Expr *InitExpr =
Init->getInit();
165 if (std::optional<PrimType> T = this->classify(InitExpr)) {
166 if (!this->visit(InitExpr))
170 if (!this->emitInitThisBitField(*T, F, InitExpr))
173 if (!this->emitInitThisField(*T, F->
Offset, InitExpr))
179 if (!this->emitGetPtrThisField(F->
Offset, InitExpr))
182 if (!this->visitInitializer(InitExpr))
185 if (!this->emitPopPtr(InitExpr))
191 const auto *BaseDecl =
Base->getAsCXXRecordDecl();
195 if (!this->emitGetPtrThisBase(B->
Offset, InitExpr))
197 if (!this->visitInitializer(InitExpr))
199 if (!this->emitInitPtrPop(InitExpr))
202 assert(
Init->isDelegatingInitializer());
203 if (!this->emitThis(InitExpr))
205 if (!this->visitInitializer(
Init->getInit()))
207 if (!this->emitPopPtr(InitExpr))
213 if (
const auto *Body = F->
getBody())
214 if (!visitStmt(Body))
224template <
class Emitter>
226 switch (S->getStmtClass()) {
227 case Stmt::CompoundStmtClass:
228 return visitCompoundStmt(cast<CompoundStmt>(S));
229 case Stmt::DeclStmtClass:
230 return visitDeclStmt(cast<DeclStmt>(S));
231 case Stmt::ReturnStmtClass:
232 return visitReturnStmt(cast<ReturnStmt>(S));
233 case Stmt::IfStmtClass:
234 return visitIfStmt(cast<IfStmt>(S));
235 case Stmt::WhileStmtClass:
236 return visitWhileStmt(cast<WhileStmt>(S));
237 case Stmt::DoStmtClass:
238 return visitDoStmt(cast<DoStmt>(S));
239 case Stmt::ForStmtClass:
240 return visitForStmt(cast<ForStmt>(S));
241 case Stmt::CXXForRangeStmtClass:
242 return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
243 case Stmt::BreakStmtClass:
244 return visitBreakStmt(cast<BreakStmt>(S));
245 case Stmt::ContinueStmtClass:
246 return visitContinueStmt(cast<ContinueStmt>(S));
247 case Stmt::SwitchStmtClass:
248 return visitSwitchStmt(cast<SwitchStmt>(S));
249 case Stmt::CaseStmtClass:
250 return visitCaseStmt(cast<CaseStmt>(S));
251 case Stmt::DefaultStmtClass:
252 return visitDefaultStmt(cast<DefaultStmt>(S));
253 case Stmt::GCCAsmStmtClass:
254 case Stmt::MSAsmStmtClass:
255 return visitAsmStmt(cast<AsmStmt>(S));
256 case Stmt::AttributedStmtClass:
257 return visitAttributedStmt(cast<AttributedStmt>(S));
258 case Stmt::CXXTryStmtClass:
259 return visitCXXTryStmt(cast<CXXTryStmt>(S));
260 case Stmt::NullStmtClass:
263 if (
auto *Exp = dyn_cast<Expr>(S))
264 return this->discard(Exp);
265 return this->bail(S);
272template <
class Emitter>
274 if (isa<NullStmt>(S))
277 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
278 for (
auto *InnerStmt : CS->body())
279 if (!visitStmt(InnerStmt))
284 return this->visitStmt(S);
287template <
class Emitter>
292 if (!visitStmt(InnerStmt))
297template <
class Emitter>
299 for (
auto *D : DS->
decls()) {
300 if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl>(D))
303 const auto *VD = dyn_cast<VarDecl>(D);
306 if (!this->visitVarDecl(VD))
313template <
class Emitter>
319 if (!this->visit(RE))
322 return this->emitRet(*ReturnType, RS);
323 }
else if (RE->getType()->isVoidType()) {
324 if (!this->visit(RE))
328 if (!this->emitRVOPtr(RE))
330 if (!this->visitInitializer(RE))
332 if (!this->emitPopPtr(RE))
336 return this->emitRetVoid(RS);
342 return this->emitRetVoid(RS);
345template <
class Emitter>
350 return visitStmt(IS->
getThen());
354 if (
auto *CondInit = IS->
getInit())
355 if (!visitStmt(CondInit))
359 if (!visitDeclStmt(CondDecl))
362 if (!this->visitBool(IS->
getCond()))
366 LabelTy LabelElse = this->getLabel();
367 LabelTy LabelEnd = this->getLabel();
368 if (!this->jumpFalse(LabelElse))
372 if (!this->jump(LabelEnd))
374 this->emitLabel(LabelElse);
375 if (!visitStmt(Else))
377 this->emitLabel(LabelEnd);
379 LabelTy LabelEnd = this->getLabel();
380 if (!this->jumpFalse(LabelEnd))
384 this->emitLabel(LabelEnd);
390template <
class Emitter>
392 const Expr *Cond = S->getCond();
393 const Stmt *Body = S->getBody();
395 LabelTy CondLabel = this->getLabel();
396 LabelTy EndLabel = this->getLabel();
399 this->emitLabel(CondLabel);
400 if (!this->visitBool(Cond))
402 if (!this->jumpFalse(EndLabel))
408 if (!this->visitLoopBody(Body))
412 if (!this->jump(CondLabel))
414 this->emitLabel(EndLabel);
419template <
class Emitter>
421 const Expr *Cond = S->getCond();
422 const Stmt *Body = S->getBody();
424 LabelTy StartLabel = this->getLabel();
425 LabelTy EndLabel = this->getLabel();
426 LabelTy CondLabel = this->getLabel();
430 this->emitLabel(StartLabel);
434 if (!this->visitLoopBody(Body))
436 this->emitLabel(CondLabel);
437 if (!this->visitBool(Cond))
440 if (!this->jumpTrue(StartLabel))
443 this->emitLabel(EndLabel);
447template <
class Emitter>
451 const Expr *Cond = S->getCond();
453 const Stmt *Body = S->getBody();
455 LabelTy EndLabel = this->getLabel();
456 LabelTy CondLabel = this->getLabel();
457 LabelTy IncLabel = this->getLabel();
463 this->emitLabel(CondLabel);
465 if (!this->visitBool(Cond))
467 if (!this->jumpFalse(EndLabel))
474 if (Body && !this->visitLoopBody(Body))
476 this->emitLabel(IncLabel);
477 if (
Inc && !this->discard(
Inc))
481 if (!this->jump(CondLabel))
483 this->emitLabel(EndLabel);
487template <
class Emitter>
490 const Expr *Cond = S->getCond();
492 const Stmt *Body = S->getBody();
493 const Stmt *BeginStmt = S->getBeginStmt();
494 const Stmt *RangeStmt = S->getRangeStmt();
495 const Stmt *EndStmt = S->getEndStmt();
496 const VarDecl *LoopVar = S->getLoopVariable();
498 LabelTy EndLabel = this->getLabel();
499 LabelTy CondLabel = this->getLabel();
500 LabelTy IncLabel = this->getLabel();
506 if (!this->visitStmt(RangeStmt))
508 if (!this->visitStmt(BeginStmt))
510 if (!this->visitStmt(EndStmt))
514 this->emitLabel(CondLabel);
515 if (!this->visitBool(Cond))
517 if (!this->jumpFalse(EndLabel))
520 if (!this->visitVarDecl(LoopVar))
528 if (!this->visitLoopBody(Body))
530 this->emitLabel(IncLabel);
531 if (!this->discard(
Inc))
534 if (!this->jump(CondLabel))
537 this->emitLabel(EndLabel);
541template <
class Emitter>
546 this->VarScope->emitDestructors();
547 return this->jump(*BreakLabel);
550template <
class Emitter>
555 this->VarScope->emitDestructors();
556 return this->jump(*ContinueLabel);
559template <
class Emitter>
561 const Expr *Cond = S->getCond();
564 LabelTy EndLabel = this->getLabel();
565 OptLabelTy DefaultLabel = std::nullopt;
566 unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT,
true,
false);
568 if (
const auto *CondInit = S->getInit())
569 if (!visitStmt(CondInit))
573 if (!this->visit(Cond))
575 if (!this->emitSetLocal(CondT, CondVar, S))
580 for (
const SwitchCase *SC = S->getSwitchCaseList(); SC;
581 SC = SC->getNextSwitchCase()) {
582 if (
const auto *CS = dyn_cast<CaseStmt>(SC)) {
584 if (CS->caseStmtIsGNURange())
586 CaseLabels[SC] = this->getLabel();
592 if (!this->emitGetLocal(CondT, CondVar, CS))
594 if (!this->visit(
Value))
598 if (!this->emitEQ(ValueT, S))
600 if (!this->jumpTrue(CaseLabels[CS]))
603 assert(!DefaultLabel);
604 DefaultLabel = this->getLabel();
611 if (!this->jump(*DefaultLabel))
614 if (!this->jump(EndLabel))
619 if (!this->visitStmt(S->getBody()))
621 this->emitLabel(EndLabel);
625template <
class Emitter>
627 this->emitLabel(CaseLabels[S]);
628 return this->visitStmt(S->getSubStmt());
631template <
class Emitter>
633 this->emitLabel(*DefaultLabel);
634 return this->visitStmt(S->getSubStmt());
637template <
class Emitter>
639 return this->emitInvalid(S);
642template <
class Emitter>
645 return this->visitStmt(S->getSubStmt());
648template <
class Emitter>
651 return this->visitStmt(S->getTryBlock());
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
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.
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 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.
Stmt - This represents one statement.
SwitchStmt - This represents a 'switch' stmt.
The base class of the type hierarchy.
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.
Expression scope which tracks potentially lifetime extended temporaries which are hoisted to the pare...
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 * 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.
Describes a record field.