@@ -114,31 +114,25 @@ template <class Emitter> class LoopScope final {
114114public:
115115 using LabelTy = typename Compiler<Emitter>::LabelTy;
116116 using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
117+ using LabelInfo = typename Compiler<Emitter>::LabelInfo;
117118
118- LoopScope (Compiler<Emitter> *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel)
119- : Ctx(Ctx), OldBreakLabel(Ctx->BreakLabel),
120- OldContinueLabel (Ctx->ContinueLabel),
121- OldBreakVarScope(Ctx->BreakVarScope),
122- OldContinueVarScope(Ctx->ContinueVarScope) {
123- this ->Ctx ->BreakLabel = BreakLabel;
124- this ->Ctx ->ContinueLabel = ContinueLabel;
125- this ->Ctx ->BreakVarScope = this ->Ctx ->VarScope ;
126- this ->Ctx ->ContinueVarScope = this ->Ctx ->VarScope ;
127- }
119+ LoopScope (Compiler<Emitter> *Ctx, const Stmt *Name, LabelTy BreakLabel,
120+ LabelTy ContinueLabel)
121+ : Ctx(Ctx) {
122+ #ifndef NDEBUG
123+ for (const LabelInfo &LI : Ctx->LabelInfoStack )
124+ assert (LI.Name != Name);
125+ #endif
128126
129- ~LoopScope () {
130- this ->Ctx ->BreakLabel = OldBreakLabel;
131- this ->Ctx ->ContinueLabel = OldContinueLabel;
132- this ->Ctx ->ContinueVarScope = OldContinueVarScope;
133- this ->Ctx ->BreakVarScope = OldBreakVarScope;
127+ this ->Ctx ->LabelInfoStack .emplace_back (Name, BreakLabel, ContinueLabel,
128+ /* DefaultLabel=*/ std::nullopt ,
129+ Ctx->VarScope );
134130 }
135131
132+ ~LoopScope () { this ->Ctx ->LabelInfoStack .pop_back (); }
133+
136134private:
137135 Compiler<Emitter> *Ctx;
138- OptLabelTy OldBreakLabel;
139- OptLabelTy OldContinueLabel;
140- VariableScope<Emitter> *OldBreakVarScope;
141- VariableScope<Emitter> *OldContinueVarScope;
142136};
143137
144138// Sets the context for a switch scope, mapping labels.
@@ -147,32 +141,30 @@ template <class Emitter> class SwitchScope final {
147141 using LabelTy = typename Compiler<Emitter>::LabelTy;
148142 using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
149143 using CaseMap = typename Compiler<Emitter>::CaseMap;
144+ using LabelInfo = typename Compiler<Emitter>::LabelInfo;
145+
146+ SwitchScope (Compiler<Emitter> *Ctx, const Stmt *Name, CaseMap &&CaseLabels,
147+ LabelTy BreakLabel, OptLabelTy DefaultLabel)
148+ : Ctx(Ctx), OldCaseLabels(std::move(this ->Ctx->CaseLabels)) {
149+ #ifndef NDEBUG
150+ for (const LabelInfo &LI : Ctx->LabelInfoStack )
151+ assert (LI.Name != Name);
152+ #endif
150153
151- SwitchScope (Compiler<Emitter> *Ctx, CaseMap &&CaseLabels, LabelTy BreakLabel,
152- OptLabelTy DefaultLabel)
153- : Ctx(Ctx), OldBreakLabel(Ctx->BreakLabel),
154- OldDefaultLabel (this ->Ctx->DefaultLabel),
155- OldCaseLabels(std::move(this ->Ctx->CaseLabels)),
156- OldLabelVarScope(Ctx->BreakVarScope) {
157- this ->Ctx ->BreakLabel = BreakLabel;
158- this ->Ctx ->DefaultLabel = DefaultLabel;
159154 this ->Ctx ->CaseLabels = std::move (CaseLabels);
160- this ->Ctx ->BreakVarScope = this ->Ctx ->VarScope ;
155+ this ->Ctx ->LabelInfoStack .emplace_back (Name, BreakLabel,
156+ /* ContinueLabel=*/ std::nullopt ,
157+ DefaultLabel, Ctx->VarScope );
161158 }
162159
163160 ~SwitchScope () {
164- this ->Ctx ->BreakLabel = OldBreakLabel;
165- this ->Ctx ->DefaultLabel = OldDefaultLabel;
166161 this ->Ctx ->CaseLabels = std::move (OldCaseLabels);
167- this ->Ctx ->BreakVarScope = OldLabelVarScope ;
162+ this ->Ctx ->LabelInfoStack . pop_back () ;
168163 }
169164
170165private:
171166 Compiler<Emitter> *Ctx;
172- OptLabelTy OldBreakLabel;
173- OptLabelTy OldDefaultLabel;
174167 CaseMap OldCaseLabels;
175- VariableScope<Emitter> *OldLabelVarScope;
176168};
177169
178170template <class Emitter > class StmtExprScope final {
@@ -2949,19 +2941,17 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
29492941 if (!this ->emitSetLocal (*SubExprT, LocalIndex, E))
29502942 return false ;
29512943 return this ->emitGetPtrLocal (LocalIndex, E);
2952- } else {
2944+ }
29532945
2954- if (!this ->checkLiteralType (SubExpr))
2946+ if (!this ->checkLiteralType (SubExpr))
2947+ return false ;
2948+ const Expr *Inner = E->getSubExpr ()->skipRValueSubobjectAdjustments ();
2949+ if (UnsignedOrNone LocalIndex =
2950+ allocateLocal (E, Inner->getType (), E->getExtendingDecl ())) {
2951+ InitLinkScope<Emitter> ILS (this , InitLink::Temp (*LocalIndex));
2952+ if (!this ->emitGetPtrLocal (*LocalIndex, E))
29552953 return false ;
2956-
2957- const Expr *Inner = E->getSubExpr ()->skipRValueSubobjectAdjustments ();
2958- if (UnsignedOrNone LocalIndex =
2959- allocateLocal (E, Inner->getType (), E->getExtendingDecl ())) {
2960- InitLinkScope<Emitter> ILS (this , InitLink::Temp (*LocalIndex));
2961- if (!this ->emitGetPtrLocal (*LocalIndex, E))
2962- return false ;
2963- return this ->visitInitializer (SubExpr) && this ->emitFinishInit (E);
2964- }
2954+ return this ->visitInitializer (SubExpr) && this ->emitFinishInit (E);
29652955 }
29662956 return false ;
29672957}
@@ -5687,7 +5677,8 @@ bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {
56875677
56885678 LabelTy CondLabel = this ->getLabel (); // Label before the condition.
56895679 LabelTy EndLabel = this ->getLabel (); // Label after the loop.
5690- LoopScope<Emitter> LS (this , EndLabel, CondLabel);
5680+ LocalScope<Emitter> WholeLoopScope (this );
5681+ LoopScope<Emitter> LS (this , S, EndLabel, CondLabel);
56915682
56925683 this ->fallthrough (CondLabel);
56935684 this ->emitLabel (CondLabel);
@@ -5717,8 +5708,7 @@ bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {
57175708 return false ;
57185709 this ->fallthrough (EndLabel);
57195710 this ->emitLabel (EndLabel);
5720-
5721- return true ;
5711+ return WholeLoopScope.destroyLocals ();
57225712}
57235713
57245714template <class Emitter > bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {
@@ -5728,7 +5718,8 @@ template <class Emitter> bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {
57285718 LabelTy StartLabel = this ->getLabel ();
57295719 LabelTy EndLabel = this ->getLabel ();
57305720 LabelTy CondLabel = this ->getLabel ();
5731- LoopScope<Emitter> LS (this , EndLabel, CondLabel);
5721+ LocalScope<Emitter> WholeLoopScope (this );
5722+ LoopScope<Emitter> LS (this , S, EndLabel, CondLabel);
57325723
57335724 this ->fallthrough (StartLabel);
57345725 this ->emitLabel (StartLabel);
@@ -5750,7 +5741,7 @@ template <class Emitter> bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {
57505741
57515742 this ->fallthrough (EndLabel);
57525743 this ->emitLabel (EndLabel);
5753- return true ;
5744+ return WholeLoopScope. destroyLocals () ;
57545745}
57555746
57565747template <class Emitter >
@@ -5764,19 +5755,21 @@ bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
57645755 LabelTy EndLabel = this ->getLabel ();
57655756 LabelTy CondLabel = this ->getLabel ();
57665757 LabelTy IncLabel = this ->getLabel ();
5767- LoopScope<Emitter> LS (this , EndLabel, IncLabel);
57685758
5759+ LocalScope<Emitter> WholeLoopScope (this );
57695760 if (Init && !this ->visitStmt (Init))
57705761 return false ;
57715762
5763+ // Start of the loop body {
57725764 this ->fallthrough (CondLabel);
57735765 this ->emitLabel (CondLabel);
57745766
5775- // Start of loop body.
57765767 LocalScope<Emitter> CondScope (this );
5777- if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt ())
5768+ LoopScope<Emitter> LS (this , S, EndLabel, IncLabel);
5769+ if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt ()) {
57785770 if (!visitDeclStmt (CondDecl))
57795771 return false ;
5772+ }
57805773
57815774 if (Cond) {
57825775 if (!this ->visitBool (Cond))
@@ -5799,12 +5792,12 @@ bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
57995792 return false ;
58005793 if (!this ->jump (CondLabel))
58015794 return false ;
5802- // End of loop body.
5795+ // } End of loop body.
58035796
58045797 this ->emitLabel (EndLabel);
58055798 // If we jumped out of the loop above, we still need to clean up the condition
58065799 // scope.
5807- return CondScope.destroyLocals ();
5800+ return CondScope.destroyLocals () && WholeLoopScope. destroyLocals () ;
58085801}
58095802
58105803template <class Emitter >
@@ -5820,7 +5813,8 @@ bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
58205813 LabelTy EndLabel = this ->getLabel ();
58215814 LabelTy CondLabel = this ->getLabel ();
58225815 LabelTy IncLabel = this ->getLabel ();
5823- LoopScope<Emitter> LS (this , EndLabel, IncLabel);
5816+ LocalScope<Emitter> WholeLoopScope (this );
5817+ LoopScope<Emitter> LS (this , S, EndLabel, IncLabel);
58245818
58255819 // Emit declarations needed in the loop.
58265820 if (Init && !this ->visitStmt (Init))
@@ -5859,29 +5853,78 @@ bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
58595853
58605854 this ->fallthrough (EndLabel);
58615855 this ->emitLabel (EndLabel);
5862- return true ;
5856+ return WholeLoopScope. destroyLocals () ;
58635857}
58645858
58655859template <class Emitter >
58665860bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
5867- if (!BreakLabel )
5861+ if (LabelInfoStack. empty () )
58685862 return false ;
58695863
5870- for (VariableScope<Emitter> *C = VarScope; C != BreakVarScope;
5864+ OptLabelTy TargetLabel = std::nullopt ;
5865+ const Stmt *TargetLoop = S->getNamedLoopOrSwitch ();
5866+ const VariableScope<Emitter> *BreakScope = nullptr ;
5867+
5868+ if (!TargetLoop) {
5869+ for (const auto &LI : llvm::reverse (LabelInfoStack)) {
5870+ if (LI.BreakLabel ) {
5871+ TargetLabel = *LI.BreakLabel ;
5872+ BreakScope = LI.BreakOrContinueScope ;
5873+ break ;
5874+ }
5875+ }
5876+ } else {
5877+ for (auto LI : LabelInfoStack) {
5878+ if (LI.Name == TargetLoop) {
5879+ TargetLabel = *LI.BreakLabel ;
5880+ BreakScope = LI.BreakOrContinueScope ;
5881+ break ;
5882+ }
5883+ }
5884+ }
5885+
5886+ assert (TargetLabel);
5887+
5888+ for (VariableScope<Emitter> *C = this ->VarScope ; C != BreakScope;
58715889 C = C->getParent ())
58725890 C->emitDestruction ();
5873- return this ->jump (*BreakLabel);
5891+
5892+ return this ->jump (*TargetLabel);
58745893}
58755894
58765895template <class Emitter >
58775896bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
5878- if (!ContinueLabel )
5897+ if (LabelInfoStack. empty () )
58795898 return false ;
58805899
5881- for (VariableScope<Emitter> *C = VarScope;
5882- C && C->getParent () != ContinueVarScope; C = C->getParent ())
5900+ OptLabelTy TargetLabel = std::nullopt ;
5901+ const Stmt *TargetLoop = S->getNamedLoopOrSwitch ();
5902+ const VariableScope<Emitter> *ContinueScope = nullptr ;
5903+
5904+ if (!TargetLoop) {
5905+ for (const auto &LI : llvm::reverse (LabelInfoStack)) {
5906+ if (LI.ContinueLabel ) {
5907+ TargetLabel = *LI.ContinueLabel ;
5908+ ContinueScope = LI.BreakOrContinueScope ;
5909+ break ;
5910+ }
5911+ }
5912+ } else {
5913+ for (auto LI : LabelInfoStack) {
5914+ if (LI.Name == TargetLoop) {
5915+ TargetLabel = *LI.ContinueLabel ;
5916+ ContinueScope = LI.BreakOrContinueScope ;
5917+ break ;
5918+ }
5919+ }
5920+ }
5921+ assert (TargetLabel);
5922+
5923+ for (VariableScope<Emitter> *C = VarScope; C != ContinueScope;
5924+ C = C->getParent ())
58835925 C->emitDestruction ();
5884- return this ->jump (*ContinueLabel);
5926+
5927+ return this ->jump (*TargetLabel);
58855928}
58865929
58875930template <class Emitter >
@@ -5894,7 +5937,7 @@ bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
58945937 LocalScope<Emitter> LS (this );
58955938
58965939 LabelTy EndLabel = this ->getLabel ();
5897- OptLabelTy DefaultLabel = std::nullopt ;
5940+ UnsignedOrNone DefaultLabel = std::nullopt ;
58985941 unsigned CondVar =
58995942 this ->allocateLocalPrimitive (Cond, CondT, /* IsConst=*/ true );
59005943
@@ -5955,7 +5998,8 @@ bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
59555998 return false ;
59565999 }
59576000
5958- SwitchScope<Emitter> SS (this , std::move (CaseLabels), EndLabel, DefaultLabel);
6001+ SwitchScope<Emitter> SS (this , S, std::move (CaseLabels), EndLabel,
6002+ DefaultLabel);
59596003 if (!this ->visitStmt (S->getBody ()))
59606004 return false ;
59616005 this ->emitLabel (EndLabel);
@@ -5971,7 +6015,18 @@ bool Compiler<Emitter>::visitCaseStmt(const CaseStmt *S) {
59716015
59726016template <class Emitter >
59736017bool Compiler<Emitter>::visitDefaultStmt(const DefaultStmt *S) {
5974- this ->emitLabel (*DefaultLabel);
6018+ if (LabelInfoStack.empty ())
6019+ return false ;
6020+
6021+ LabelTy DefaultLabel;
6022+ for (const LabelInfo &LI : llvm::reverse (LabelInfoStack)) {
6023+ if (LI.DefaultLabel ) {
6024+ DefaultLabel = *LI.DefaultLabel ;
6025+ break ;
6026+ }
6027+ }
6028+
6029+ this ->emitLabel (DefaultLabel);
59756030 return this ->visitStmt (S->getSubStmt ());
59766031}
59776032
0 commit comments