• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "eh_func.h"
17 #include "cgfunc.h"
18 #include "cg.h"
19 #include "mir_builder.h"
20 #include "switch_lowerer.h"
21 
22 namespace maplebe {
23 using namespace maple;
24 
DumpEHTry(const MIRModule & mirModule)25 void EHTry::DumpEHTry(const MIRModule &mirModule)
26 {
27     if (tryNode != nullptr) {
28         tryNode->Dump();
29     }
30 
31     if (endTryNode != nullptr) {
32         endTryNode->Dump();
33     }
34 
35     for (const auto *currCatch : catchVec) {
36         if (currCatch == nullptr) {
37             continue;
38         }
39         currCatch->Dump();
40     }
41 }
42 
ConvertThrowToRuntime(CGFunc & cgFunc,BaseNode & arg)43 void EHThrow::ConvertThrowToRuntime(CGFunc &cgFunc, BaseNode &arg)
44 {
45     MIRFunction &mirFunc = cgFunc.GetFunction();
46     MIRModule *mirModule = mirFunc.GetModule();
47     MIRFunction *calleeFunc =
48         mirModule->GetMIRBuilder()->GetOrCreateFunction("MCC_ThrowException", static_cast<TyIdx>(PTY_void));
49     cgFunc.GetBecommon().UpdateTypeTable(*calleeFunc->GetMIRFuncType());
50     calleeFunc->SetNoReturn();
51     MapleVector<BaseNode *> args(mirModule->GetMIRBuilder()->GetCurrentFuncCodeMpAllocator()->Adapter());
52     args.emplace_back(&arg);
53     CallNode *callAssign = mirModule->GetMIRBuilder()->CreateStmtCall(calleeFunc->GetPuidx(), args);
54     mirFunc.GetBody()->ReplaceStmt1WithStmt2(rethrow, callAssign);
55 }
56 
ConvertThrowToRethrow(CGFunc & cgFunc)57 void EHThrow::ConvertThrowToRethrow(CGFunc &cgFunc)
58 {
59     MIRFunction &mirFunc = cgFunc.GetFunction();
60     MIRModule *mirModule = mirFunc.GetModule();
61     MIRBuilder *mirBuilder = mirModule->GetMIRBuilder();
62     MIRFunction *unFunc = mirBuilder->GetOrCreateFunction("MCC_RethrowException", static_cast<TyIdx>(PTY_void));
63     cgFunc.GetBecommon().UpdateTypeTable(*unFunc->GetMIRFuncType());
64     unFunc->SetNoReturn();
65     MapleVector<BaseNode *> args(mirBuilder->GetCurrentFuncCodeMpAllocator()->Adapter());
66     args.emplace_back(rethrow->Opnd(0));
67     CallNode *callNode = mirBuilder->CreateStmtCall(unFunc->GetPuidx(), args);
68     mirFunc.GetBody()->ReplaceStmt1WithStmt2(rethrow, callNode);
69 }
70 
EHFunc(CGFunc & func)71 EHFunc::EHFunc(CGFunc &func)
72     : cgFunc(&func),
73       tryVec(func.GetFuncScopeAllocator()->Adapter()),
74       ehTyTable(func.GetFuncScopeAllocator()->Adapter()),
75       ty2IndexTable(std::less<TyIdx>(), func.GetFuncScopeAllocator()->Adapter()),
76       rethrowVec(func.GetFuncScopeAllocator()->Adapter())
77 {
78 }
79 
BuildEHFunc()80 EHFunc *CGFunc::BuildEHFunc()
81 {
82     EHFunc *newEHFunc = GetMemoryPool()->New<EHFunc>(*this);
83     SetEHFunc(*newEHFunc);
84     std::vector<std::pair<LabelIdx, CatchNode *>> catchVec;
85     newEHFunc->MergeCatchToTry(catchVec);
86     newEHFunc->BuildEHTypeTable(catchVec);
87     newEHFunc->InsertEHSwitchTable();
88     newEHFunc->GenerateCleanupLabel();
89 
90     GetBecommon().BeGetOrCreatePointerType(*GlobalTables::GetTypeTable().GetVoid());
91     if (newEHFunc->NeedFullLSDA()) {
92         newEHFunc->CreateLSDA();
93     }
94     if (GetCG()->GetCGOptions().GenerateExceptionHandlingCode()) {
95         newEHFunc->CreateTypeInfoSt();
96     }
97 
98     return newEHFunc;
99 }
100 
NeedFullLSDA() const101 bool EHFunc::NeedFullLSDA() const
102 {
103     return false;
104 }
105 
NeedFastLSDA() const106 bool EHFunc::NeedFastLSDA() const
107 {
108     return false;
109 }
110 
HasTry() const111 bool EHFunc::HasTry() const
112 {
113     return !tryVec.empty();
114 }
115 
CreateTypeInfoSt()116 void EHFunc::CreateTypeInfoSt()
117 {
118     MIRFunction &mirFunc = cgFunc->GetFunction();
119     bool ctorDefined = false;
120     if (mirFunc.GetAttr(FUNCATTR_constructor) && !mirFunc.GetAttr(FUNCATTR_static) && (mirFunc.GetBody() != nullptr)) {
121         ctorDefined = true;
122     }
123 
124     if (!ctorDefined) {
125         return;
126     }
127 
128     const auto *classType = static_cast<const MIRClassType *>(mirFunc.GetClassType());
129     if (cgFunc->GetMirModule().IsCModule() && classType == nullptr) {
130         return;
131     }
132     DEBUG_ASSERT(classType != nullptr, "");
133     if (classType->GetMethods().empty() && (classType->GetFieldsSize() == 0)) {
134         return;
135     }
136 }
137 
138 /*
139  * merge catch to try
140  */
MergeCatchToTry(const std::vector<std::pair<LabelIdx,CatchNode * >> & catchVec)141 void EHFunc::MergeCatchToTry(const std::vector<std::pair<LabelIdx, CatchNode *>> &catchVec)
142 {
143     size_t tryOffsetCount;
144     for (auto *ehTry : tryVec) {
145         tryOffsetCount = ehTry->GetTryNode()->GetOffsetsCount();
146         for (size_t i = 0; i < tryOffsetCount; i++) {
147             auto o = ehTry->GetTryNode()->GetOffset(i);
148             for (const auto &catchVecPair : catchVec) {
149                 LabelIdx lbIdx = catchVecPair.first;
150                 if (lbIdx == o) {
151                     ehTry->PushBackCatchVec(*catchVecPair.second);
152                     break;
153                 }
154             }
155         }
156         CHECK_FATAL(ehTry->GetCatchVecSize() == tryOffsetCount,
157                     "EHTry instance offset does not equal catch node amount.");
158     }
159 }
160 
161 /* catchvec is going to be released by the caller */
BuildEHTypeTable(const std::vector<std::pair<LabelIdx,CatchNode * >> & catchVec)162 void EHFunc::BuildEHTypeTable(const std::vector<std::pair<LabelIdx, CatchNode *>> &catchVec)
163 {
164     if (!catchVec.empty()) {
165         /* the first one assume to be <*void> */
166         TyIdx voidTyIdx(PTY_void);
167         ehTyTable.emplace_back(voidTyIdx);
168         ty2IndexTable[voidTyIdx] = 0;
169         /* create void pointer and update becommon's size table */
170         cgFunc->GetBecommon().UpdateTypeTable(*GlobalTables::GetTypeTable().GetVoidPtr());
171     }
172 
173     /* create the type table for this function, just iterate each catch */
174     CatchNode *jCatchNode = nullptr;
175     size_t catchNodeSize;
176     for (const auto &catchVecPair : catchVec) {
177         jCatchNode = catchVecPair.second;
178         catchNodeSize = jCatchNode->Size();
179         for (size_t i = 0; i < catchNodeSize; i++) {
180             MIRType *mirTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(jCatchNode->GetExceptionTyIdxVecElement(i));
181             DEBUG_ASSERT(mirTy->GetKind() == kTypePointer, "mirTy is not pointer type");
182             TyIdx ehTyIdx = static_cast<MIRPtrType *>(mirTy)->GetPointedTyIdx();
183             if (ty2IndexTable.find(ehTyIdx) != ty2IndexTable.end()) {
184                 continue;
185             }
186 
187             ty2IndexTable[ehTyIdx] = ehTyTable.size();
188             ehTyTable.emplace_back(ehTyIdx);
189         }
190     }
191 }
192 
DumpEHFunc() const193 void EHFunc::DumpEHFunc() const
194 {
195     MIRModule &mirModule = *cgFunc->GetFunction().GetModule();
196     for (uint32 i = 0; i < this->tryVec.size(); i++) {
197         LogInfo::MapleLogger() << "\n========== start " << i << " th eh:\n";
198         EHTry *ehTry = tryVec[i];
199         ehTry->DumpEHTry(mirModule);
200         LogInfo::MapleLogger() << "========== end " << i << " th eh =========\n";
201     }
202 
203     LogInfo::MapleLogger() << "\n========== start LSDA type table ========\n";
204     for (uint32 i = 0; i < this->ehTyTable.size(); i++) {
205         LogInfo::MapleLogger() << i << " vector to ";
206         GlobalTables::GetTypeTable().GetTypeFromTyIdx(ehTyTable[i])->Dump(0);
207         LogInfo::MapleLogger() << "\n";
208     }
209     LogInfo::MapleLogger() << "========== end LSDA type table ========\n";
210 
211     LogInfo::MapleLogger() << "\n========== start type-index map ========\n";
212     for (const auto &ty2indexTablePair : ty2IndexTable) {
213         GlobalTables::GetTypeTable().GetTypeFromTyIdx(ty2indexTablePair.first)->Dump(0);
214         LogInfo::MapleLogger() << " map to ";
215         LogInfo::MapleLogger() << ty2indexTablePair.second << "\n";
216     }
217     LogInfo::MapleLogger() << "========== end type-index map ========\n";
218 }
219 
220 /*
221  * cleanup_label is an LabelNode, and placed just before endLabel.
222  * cleanup_label is the first statement of cleanupbb.
223  * the layout of clean up code is:
224  * //return bb
225  *   ...
226  * //cleanup bb = lastbb->prev; cleanupbb->PrependBB(retbb)
227  *   cleanup_label:
228  *     ...
229  * //lastbb
230  *   endLabel:
231  *     .cfi_endproc
232  *   .Label.xx.end:
233  *     .size
234  */
GenerateCleanupLabel()235 void EHFunc::GenerateCleanupLabel()
236 {
237     MIRModule *mirModule = cgFunc->GetFunction().GetModule();
238     cgFunc->SetCleanupLabel(*mirModule->GetMIRBuilder()->CreateStmtLabel(CreateLabel(".LCLEANUP")));
239     BlockNode *blockNode = cgFunc->GetFunction().GetBody();
240     blockNode->InsertBefore(cgFunc->GetEndLabel(), cgFunc->GetCleanupLabel());
241 }
242 
InsertDefaultLabelAndAbortFunc(BlockNode & blkNode,SwitchNode & switchNode,const StmtNode & beforeEndLabel)243 void EHFunc::InsertDefaultLabelAndAbortFunc(BlockNode &blkNode, SwitchNode &switchNode, const StmtNode &beforeEndLabel)
244 {
245     MIRModule &mirModule = *cgFunc->GetFunction().GetModule();
246     LabelIdx dfLabIdx = cgFunc->GetFunction().GetLabelTab()->CreateLabel();
247     cgFunc->GetFunction().GetLabelTab()->AddToStringLabelMap(dfLabIdx);
248     StmtNode *dfLabStmt = mirModule.GetMIRBuilder()->CreateStmtLabel(dfLabIdx);
249     blkNode.InsertAfter(&beforeEndLabel, dfLabStmt);
250     MIRFunction *calleeFunc = mirModule.GetMIRBuilder()->GetOrCreateFunction("abort", static_cast<TyIdx>(PTY_void));
251     cgFunc->GetBecommon().UpdateTypeTable(*calleeFunc->GetMIRFuncType());
252     MapleVector<BaseNode *> args(mirModule.GetMIRBuilder()->GetCurrentFuncCodeMpAllocator()->Adapter());
253     CallNode *callExit = mirModule.GetMIRBuilder()->CreateStmtCall(calleeFunc->GetPuidx(), args);
254     blkNode.InsertAfter(dfLabStmt, callExit);
255     switchNode.SetDefaultLabel(dfLabIdx);
256 }
257 
FillSwitchTable(SwitchNode & switchNode,const EHTry & ehTry)258 void EHFunc::FillSwitchTable(SwitchNode &switchNode, const EHTry &ehTry)
259 {
260     CatchNode *catchNode = nullptr;
261     MIRType *exceptionType = nullptr;
262     MIRPtrType *ptType = nullptr;
263     size_t catchVecSize = ehTry.GetCatchVecSize();
264     /* update switch node's cases */
265     for (size_t i = 0; i < catchVecSize; i++) {
266         catchNode = ehTry.GetCatchNodeAt(i);
267         for (size_t j = 0; j < catchNode->Size(); j++) {
268             exceptionType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(catchNode->GetExceptionTyIdxVecElement(j));
269             ptType = static_cast<MIRPtrType *>(exceptionType);
270             MapleMap<TyIdx, uint32>::iterator ty2IdxIt = ty2IndexTable.find(ptType->GetPointedTyIdx());
271             DEBUG_ASSERT(ty2IdxIt != ty2IndexTable.end(), "find tyIdx failed!");
272             uint32 tableIdx = ty2IdxIt->second;
273             LabelNode *catchLabelNode = static_cast<LabelNode *>(catchNode->GetPrev());
274             CasePair p(tableIdx, catchLabelNode->GetLabelIdx());
275             bool inserted = false;
276             for (auto x : switchNode.GetSwitchTable()) {
277                 if (x == p) {
278                     inserted = true;
279                     break;
280                 }
281             }
282             if (!inserted) {
283                 switchNode.InsertCasePair(p);
284             }
285         }
286     }
287 }
288 
289 /* this is also the landing pad code. */
InsertEHSwitchTable()290 void EHFunc::InsertEHSwitchTable()
291 {
292     MIRModule &mirModule = *cgFunc->GetFunction().GetModule();
293     BlockNode *blockNode = cgFunc->GetFunction().GetBody();
294     CHECK_FATAL(blockNode != nullptr, "get function body failed in EHThrow::InsertEHSwitchTable");
295     StmtNode *endLabelPrevNode = nullptr;
296     SwitchNode *switchNode = nullptr;
297     for (auto *ehTry : tryVec) {
298         endLabelPrevNode = cgFunc->GetEndLabel()->GetPrev();
299         /*
300          * get the next statement of the trynode. when no throw happend in try block, jump to the statement directly
301          * create a switch statement and insert after tryend;
302          */
303         switchNode = mirModule.CurFuncCodeMemPool()->New<SwitchNode>(mirModule);
304         /* create a new label as default, and if program excute here, error it */
305         InsertDefaultLabelAndAbortFunc(*blockNode, *switchNode, *endLabelPrevNode);
306         /* create s special symbol that use the second return of __builtin_eh_return() */
307         MIRSymbol *mirSymbol = mirModule.GetMIRBuilder()->CreateSymbol(TyIdx(PTY_i32), "__eh_index__", kStVar, kScAuto,
308                                                                        &cgFunc->GetFunction(), kScopeLocal);
309         switchNode->SetSwitchOpnd(mirModule.GetMIRBuilder()->CreateExprDread(*mirSymbol));
310         FillSwitchTable(*switchNode, *ehTry);
311         SwitchLowerer switchLower(mirModule, *switchNode, *cgFunc->GetFuncScopeAllocator());
312         blockNode->InsertBlockAfter(*switchLower.LowerSwitch(), endLabelPrevNode);
313         ehTry->SetFallthruGoto(endLabelPrevNode->GetNext());
314     }
315     if (!CGOptions::IsQuiet()) {
316         cgFunc->GetFunction().Dump();
317     }
318 }
319 
CreateLabel(const std::string & cstr)320 LabelIdx EHFunc::CreateLabel(const std::string &cstr)
321 {
322     MIRSymbol *mirSymbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(cgFunc->GetFunction().GetStIdx().Idx());
323     CHECK_FATAL(mirSymbol != nullptr, "get function symbol failed in EHFunc::CreateLabel");
324     std::string funcName = mirSymbol->GetName();
325     std::string labStr = funcName.append(cstr).append(std::to_string(labelIdx++));
326     return cgFunc->GetFunction().GetOrCreateLableIdxFromName(labStr);
327 }
328 
CreateLSDAHeader()329 void EHFunc::CreateLSDAHeader()
330 {
331     constexpr uint8 startEncoding = 0xff;
332     constexpr uint8 typeEncoding = 0x9b;
333     constexpr uint8 callSiteEncoding = 0x1;
334     MIRBuilder *mirBuilder = cgFunc->GetFunction().GetModule()->GetMIRBuilder();
335 
336     LSDAHeader *lsdaHeaders = cgFunc->GetMemoryPool()->New<LSDAHeader>();
337     LabelIdx lsdaHdLblIdx = CreateLabel("LSDAHD"); /* LSDA head */
338     LabelNode *lsdaHdLblNode = mirBuilder->CreateStmtLabel(lsdaHdLblIdx);
339     lsdaHeaders->SetLSDALabel(*lsdaHdLblNode);
340 
341     LabelIdx lsdaTTStartIdx = CreateLabel("LSDAALLS"); /* LSDA all start; */
342     LabelNode *lsdaTTLblNode = mirBuilder->CreateStmtLabel(lsdaTTStartIdx);
343     LabelIdx lsdaTTEndIdx = CreateLabel("LSDAALLE"); /* LSDA all end; */
344     LabelNode *lsdaCSTELblNode = mirBuilder->CreateStmtLabel(lsdaTTEndIdx);
345     lsdaHeaders->SetTTypeOffset(lsdaTTLblNode, lsdaCSTELblNode);
346 
347     lsdaHeaders->SetLPStartEncoding(startEncoding);
348     lsdaHeaders->SetTTypeEncoding(typeEncoding);
349     lsdaHeaders->SetCallSiteEncoding(callSiteEncoding);
350     lsdaHeader = lsdaHeaders;
351 }
352 
FillLSDACallSiteTable()353 void EHFunc::FillLSDACallSiteTable()
354 {
355     constexpr uint8 callSiteFirstAction = 0x1;
356     MIRBuilder *mirBuilder = cgFunc->GetFunction().GetModule()->GetMIRBuilder();
357     BlockNode *bodyNode = cgFunc->GetFunction().GetBody();
358 
359     lsdaCallSiteTable = cgFunc->GetMemoryPool()->New<LSDACallSiteTable>(*cgFunc->GetFuncScopeAllocator());
360     LabelIdx lsdaCSTStartIdx = CreateLabel("LSDACSTS"); /* LSDA callsite table start; */
361     LabelNode *lsdaCSTStartLabel = mirBuilder->CreateStmtLabel(lsdaCSTStartIdx);
362     LabelIdx lsdaCSTEndIdx = CreateLabel("LSDACSTE"); /* LSDA callsite table end; */
363     LabelNode *lsdaCSTEndLabel = mirBuilder->CreateStmtLabel(lsdaCSTEndIdx);
364     lsdaCallSiteTable->SetCSTable(lsdaCSTStartLabel, lsdaCSTEndLabel);
365 
366     /* create LDSACallSite for each EHTry instance */
367     for (auto *ehTry : tryVec) {
368         DEBUG_ASSERT(ehTry != nullptr, "null ptr check");
369         /* replace try with a label which is the callsite_start */
370         LabelIdx csStartLblIdx = CreateLabel("LSDACS");
371         LabelNode *csLblNode = mirBuilder->CreateStmtLabel(csStartLblIdx);
372         LabelIdx csEndLblIdx = CreateLabel("LSDACE");
373         LabelNode *ceLblNode = mirBuilder->CreateStmtLabel(csEndLblIdx);
374         TryNode *tryNode = ehTry->GetTryNode();
375         bodyNode->ReplaceStmt1WithStmt2(tryNode, csLblNode);
376         StmtNode *endTryNode = ehTry->GetEndtryNode();
377         bodyNode->ReplaceStmt1WithStmt2(endTryNode, ceLblNode);
378 
379         LabelNode *ladpadEndLabel = nullptr;
380         if (ehTry->GetFallthruGoto()) {
381             ladpadEndLabel = mirBuilder->CreateStmtLabel(CreateLabel("LSDALPE"));
382             bodyNode->InsertBefore(ehTry->GetFallthruGoto(), ladpadEndLabel);
383         } else {
384             ladpadEndLabel = ceLblNode;
385         }
386         /* When there is only one catch, the exception table is optimized. */
387         if (ehTry->GetCatchVecSize() == 1) {
388             ladpadEndLabel = static_cast<LabelNode *>(ehTry->GetCatchNodeAt(0)->GetPrev());
389         }
390 
391         LSDACallSite *lsdaCallSite = cgFunc->GetMemoryPool()->New<LSDACallSite>();
392         LabelPair csStart(cgFunc->GetStartLabel(), csLblNode);
393         LabelPair csLength(csLblNode, ceLblNode);
394         LabelPair csLandingPad(cgFunc->GetStartLabel(), ladpadEndLabel);
395         lsdaCallSite->Init(csStart, csLength, csLandingPad, callSiteFirstAction);
396         ehTry->SetLSDACallSite(*lsdaCallSite);
397         lsdaCallSiteTable->PushBack(*lsdaCallSite);
398     }
399 }
400 
CreateLSDA()401 void EHFunc::CreateLSDA()
402 {
403     constexpr uint8 callSiteCleanUpAction = 0x0;
404     /* create header */
405     CreateLSDAHeader();
406     /* create and fill callsite table */
407     FillLSDACallSiteTable();
408 
409     for (auto *rethrow : rethrowVec) {
410         DEBUG_ASSERT(rethrow != nullptr, "null ptr check");
411         if (rethrow->HasLSDA()) {
412             LSDACallSite *lsdaCallSite = cgFunc->GetMemoryPool()->New<LSDACallSite>();
413             LabelPair csStart(cgFunc->GetStartLabel(), rethrow->GetStartLabel());
414             LabelPair csLength(rethrow->GetStartLabel(), rethrow->GetEndLabel());
415             LabelPair csLandingPad(nullptr, nullptr);
416             lsdaCallSite->Init(csStart, csLength, csLandingPad, callSiteCleanUpAction);
417             lsdaCallSiteTable->PushBack(*lsdaCallSite);
418         }
419     }
420 
421     /* LSDAAction table */
422     CreateLSDAAction();
423 }
424 
CreateLSDAAction()425 void EHFunc::CreateLSDAAction()
426 {
427     constexpr uint8 actionTableNextEncoding = 0x7d;
428     /* iterate each try and its corresponding catch */
429     LSDAActionTable *actionTable = cgFunc->GetMemoryPool()->New<LSDAActionTable>(*cgFunc->GetFuncScopeAllocator());
430     lsdaActionTable = actionTable;
431 
432     for (auto *ehTry : tryVec) {
433         LSDAAction *lastAction = nullptr;
434         for (int32 j = static_cast<int32>(ehTry->GetCatchVecSize()) - 1; j >= 0; --j) {
435             CatchNode *catchNode = ehTry->GetCatchNodeAt(j);
436             DEBUG_ASSERT(catchNode != nullptr, "null ptr check");
437             for (uint32 idx = 0; idx < catchNode->Size(); ++idx) {
438                 MIRPtrType *ptType = static_cast<MIRPtrType *>(
439                     GlobalTables::GetTypeTable().GetTypeFromTyIdx(catchNode->GetExceptionTyIdxVecElement(idx)));
440                 uint32 tyIndex = ty2IndexTable[ptType->GetPointedTyIdx()]; /* get the index of ptType of ehTyTable; */
441                 DEBUG_ASSERT(tyIndex != 0, "exception type index not allow equal zero");
442                 LSDAAction *lsdaAction = cgFunc->GetMemoryPool()->New<LSDAAction>(
443                     tyIndex, lastAction == nullptr ? 0 : actionTableNextEncoding);
444                 lastAction = lsdaAction;
445                 actionTable->PushBack(*lsdaAction);
446             }
447         }
448 
449         CHECK_FATAL(actionTable->Size(), "must not be zero");
450         /* record actionTable group offset, per LSDAAction object in actionTable occupy 2 bytes */
451         ehTry->SetCSAction((actionTable->Size() - 1) * 2 + 1);
452     }
453 }
454 
PhaseRun(maplebe::CGFunc & f)455 bool CgBuildEHFunc::PhaseRun(maplebe::CGFunc &f)
456 {
457     f.BuildEHFunc();
458     return false;
459 }
460 MAPLE_TRANSFORM_PHASE_REGISTER(CgBuildEHFunc, buildehfunc)
461 } /* namespace maplebe */
462