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))
194 const auto *BaseDecl =
Base->getAsCXXRecordDecl();
196 const Record::Base *B = R->
getBase(BaseDecl);
198 if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
200 if (!this->visitInitializer(InitExpr))
202 if (!this->emitFinishInitPop(InitExpr))
205 assert(IFD->getChainingSize() >= 2);
207 unsigned NestedFieldOffset = 0;
208 const Record::Field *NestedField =
nullptr;
209 for (
const NamedDecl *ND : IFD->chain()) {
210 const auto *FD = cast<FieldDecl>(ND);
211 const Record *FieldRecord =
212 this->
P.getOrCreateRecord(FD->getParent());
215 NestedField = FieldRecord->
getField(FD);
218 NestedFieldOffset += NestedField->Offset;
222 if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr))
225 assert(
Init->isDelegatingInitializer());
226 if (!this->emitThis(InitExpr))
228 if (!this->visitInitializer(
Init->getInit()))
230 if (!this->emitPopPtr(InitExpr))
236 if (
const auto *Body = F->
getBody())
237 if (!visitStmt(Body))
247template <
class Emitter>
249 switch (S->getStmtClass()) {
250 case Stmt::CompoundStmtClass:
251 return visitCompoundStmt(cast<CompoundStmt>(S));
252 case Stmt::DeclStmtClass:
253 return visitDeclStmt(cast<DeclStmt>(S));
254 case Stmt::ReturnStmtClass:
255 return visitReturnStmt(cast<ReturnStmt>(S));
256 case Stmt::IfStmtClass:
257 return visitIfStmt(cast<IfStmt>(S));
258 case Stmt::WhileStmtClass:
259 return visitWhileStmt(cast<WhileStmt>(S));
260 case Stmt::DoStmtClass:
261 return visitDoStmt(cast<DoStmt>(S));
262 case Stmt::ForStmtClass:
263 return visitForStmt(cast<ForStmt>(S));
264 case Stmt::CXXForRangeStmtClass:
265 return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
266 case Stmt::BreakStmtClass:
267 return visitBreakStmt(cast<BreakStmt>(S));
268 case Stmt::ContinueStmtClass:
269 return visitContinueStmt(cast<ContinueStmt>(S));
270 case Stmt::SwitchStmtClass:
271 return visitSwitchStmt(cast<SwitchStmt>(S));
272 case Stmt::CaseStmtClass:
273 return visitCaseStmt(cast<CaseStmt>(S));
274 case Stmt::DefaultStmtClass:
275 return visitDefaultStmt(cast<DefaultStmt>(S));
276 case Stmt::AttributedStmtClass:
277 return visitAttributedStmt(cast<AttributedStmt>(S));
278 case Stmt::CXXTryStmtClass:
279 return visitCXXTryStmt(cast<CXXTryStmt>(S));
280 case Stmt::NullStmtClass:
283 case Stmt::GCCAsmStmtClass:
284 case Stmt::MSAsmStmtClass:
285 case Stmt::GotoStmtClass:
286 case Stmt::LabelStmtClass:
287 return this->emitInvalid(S);
289 if (
auto *Exp = dyn_cast<Expr>(S))
290 return this->discard(Exp);
298template <
class Emitter>
300 if (isa<NullStmt>(S))
303 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
304 for (
auto *InnerStmt : CS->body())
305 if (!visitStmt(InnerStmt))
310 return this->visitStmt(S);
313template <
class Emitter>
318 if (!visitStmt(InnerStmt))
323template <
class Emitter>
325 for (
auto *D : DS->
decls()) {
326 if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, UsingEnumDecl>(D))
329 const auto *VD = dyn_cast<VarDecl>(D);
332 if (!this->visitVarDecl(VD))
339template <
class Emitter>
345 if (!this->visit(RE))
348 return this->emitRet(*ReturnType, RS);
349 }
else if (RE->getType()->isVoidType()) {
350 if (!this->visit(RE))
354 if (!this->emitRVOPtr(RE))
356 if (!this->visitInitializer(RE))
358 if (!this->emitPopPtr(RE))
362 return this->emitRetVoid(RS);
368 return this->emitRetVoid(RS);
371template <
class Emitter>
376 return visitStmt(IS->
getThen());
380 if (
auto *CondInit = IS->
getInit())
381 if (!visitStmt(CondInit))
385 if (!visitDeclStmt(CondDecl))
388 if (!this->visitBool(IS->
getCond()))
392 LabelTy LabelElse = this->getLabel();
393 LabelTy LabelEnd = this->getLabel();
394 if (!this->jumpFalse(LabelElse))
398 if (!this->jump(LabelEnd))
400 this->emitLabel(LabelElse);
401 if (!visitStmt(Else))
403 this->emitLabel(LabelEnd);
405 LabelTy LabelEnd = this->getLabel();
406 if (!this->jumpFalse(LabelEnd))
410 this->emitLabel(LabelEnd);
416template <
class Emitter>
418 const Expr *Cond = S->getCond();
419 const Stmt *Body = S->getBody();
421 LabelTy CondLabel = this->getLabel();
422 LabelTy EndLabel = this->getLabel();
425 this->emitLabel(CondLabel);
427 if (
const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
428 if (!visitDeclStmt(CondDecl))
431 if (!this->visitBool(Cond))
433 if (!this->jumpFalse(EndLabel))
439 if (!this->visitLoopBody(Body))
443 if (!this->jump(CondLabel))
445 this->emitLabel(EndLabel);
450template <
class Emitter>
452 const Expr *Cond = S->getCond();
453 const Stmt *Body = S->getBody();
455 LabelTy StartLabel = this->getLabel();
456 LabelTy EndLabel = this->getLabel();
457 LabelTy CondLabel = this->getLabel();
461 this->emitLabel(StartLabel);
465 if (!this->visitLoopBody(Body))
467 this->emitLabel(CondLabel);
468 if (!this->visitBool(Cond))
471 if (!this->jumpTrue(StartLabel))
474 this->emitLabel(EndLabel);
478template <
class Emitter>
482 const Expr *Cond = S->getCond();
484 const Stmt *Body = S->getBody();
486 LabelTy EndLabel = this->getLabel();
487 LabelTy CondLabel = this->getLabel();
488 LabelTy IncLabel = this->getLabel();
494 this->emitLabel(CondLabel);
496 if (
const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
497 if (!visitDeclStmt(CondDecl))
500 if (!this->visitBool(Cond))
502 if (!this->jumpFalse(EndLabel))
509 if (Body && !this->visitLoopBody(Body))
511 this->emitLabel(IncLabel);
512 if (
Inc && !this->discard(
Inc))
516 if (!this->jump(CondLabel))
518 this->emitLabel(EndLabel);
522template <
class Emitter>
525 const Expr *Cond = S->getCond();
527 const Stmt *Body = S->getBody();
528 const Stmt *BeginStmt = S->getBeginStmt();
529 const Stmt *RangeStmt = S->getRangeStmt();
530 const Stmt *EndStmt = S->getEndStmt();
531 const VarDecl *LoopVar = S->getLoopVariable();
533 LabelTy EndLabel = this->getLabel();
534 LabelTy CondLabel = this->getLabel();
535 LabelTy IncLabel = this->getLabel();
541 if (!this->visitStmt(RangeStmt))
543 if (!this->visitStmt(BeginStmt))
545 if (!this->visitStmt(EndStmt))
549 this->emitLabel(CondLabel);
550 if (!this->visitBool(Cond))
552 if (!this->jumpFalse(EndLabel))
555 if (!this->visitVarDecl(LoopVar))
563 if (!this->visitLoopBody(Body))
565 this->emitLabel(IncLabel);
566 if (!this->discard(
Inc))
569 if (!this->jump(CondLabel))
572 this->emitLabel(EndLabel);
576template <
class Emitter>
581 this->VarScope->emitDestructors();
582 return this->jump(*BreakLabel);
585template <
class Emitter>
590 this->VarScope->emitDestructors();
591 return this->jump(*ContinueLabel);
594template <
class Emitter>
596 const Expr *Cond = S->getCond();
598 LabelTy EndLabel = this->getLabel();
599 OptLabelTy DefaultLabel = std::nullopt;
601 if (
const auto *CondInit = S->getInit())
602 if (!visitStmt(CondInit))
605 if (
const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
606 if (!visitDeclStmt(CondDecl))
611 unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT,
true,
false);
612 if (!this->visit(Cond))
614 if (!this->emitSetLocal(CondT, CondVar, S))
619 for (
const SwitchCase *SC = S->getSwitchCaseList(); SC;
620 SC = SC->getNextSwitchCase()) {
621 if (
const auto *CS = dyn_cast<CaseStmt>(SC)) {
623 if (CS->caseStmtIsGNURange())
625 CaseLabels[SC] = this->getLabel();
631 if (!this->emitGetLocal(CondT, CondVar, CS))
633 if (!this->visit(
Value))
637 if (!this->emitEQ(ValueT, S))
639 if (!this->jumpTrue(CaseLabels[CS]))
642 assert(!DefaultLabel);
643 DefaultLabel = this->getLabel();
650 if (!this->jump(*DefaultLabel))
653 if (!this->jump(EndLabel))
658 if (!this->visitStmt(S->getBody()))
660 this->emitLabel(EndLabel);
664template <
class Emitter>
666 this->emitLabel(CaseLabels[S]);
667 return this->visitStmt(S->getSubStmt());
670template <
class Emitter>
672 this->emitLabel(*DefaultLabel);
673 return this->visitStmt(S->getSubStmt());
676template <
class Emitter>
679 return this->visitStmt(S->getSubStmt());
682template <
class Emitter>
685 return this->visitStmt(S->getTryBlock());
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 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.
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.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T