00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <vector>
00043 #include <queue>
00044 #include "defs.h"
00045 #include "glob.h"
00046 #include "config.h"
00047 #include "wn.h"
00048 #include "wn_util.h"
00049
00050 #include "gnu/config.h"
00051 #include "gnu/system.h"
00052
00053 #include "srcpos.h"
00054 #include "gnu/machmode.h"
00055 #include "gnu/tree.h"
00056 #include "gnu/flags.h"
00057 #include "ir_reader.h"
00058 #include "tree_symtab.h"
00059 #include "wfe_misc.h"
00060 #include "wfe_expr.h"
00061 #include "wfe_stmt.h"
00062 #include "rt_symtab.h"
00063 #include "wfe_except.h"
00064
00065 using std::vector;
00066 using std::queue;
00067
00068 inline LABEL_IDX Get_New_Label_Idx()
00069 {
00070 LABEL_IDX result;
00071 New_LABEL(CURRENT_SYMTAB, result);
00072 return result;
00073 }
00074
00075 struct EH_INFO {
00076 LABEL_IDX outer_context;
00077 LABEL_IDX handler;
00078 tree finalization;
00079 bool label_used;
00080 EH_INFO(): outer_context(Get_New_Label_Idx()),
00081 handler (Get_New_Label_Idx()),
00082 finalization(NULL_TREE),
00083 label_used(false) {}
00084 };
00085
00086 static vector<EH_INFO> eh_info_stack;
00087 static vector<EH_INFO> catch_stack;
00088 static vector<LABEL_IDX> caught_return_label_stack;
00089 static queue <EH_INFO> eh_info_queue;
00090
00091 void WFE_Expand_EH_Region_Start()
00092 {
00093 eh_info_stack.push_back(EH_INFO());
00094 }
00095
00096 WN * Make_Runtime_Call(const char * name, TY_IDX return_ty_idx)
00097 {
00098 WN * result = WN_Create(OPR_CALL, MTYPE_V, MTYPE_V, 0);
00099 WN_st_idx(result) = Throw_Runtime_st_idx();
00100 return result;
00101 }
00102
00103 static void WFE_Expand_Internal_Throw()
00104 {
00105 WN * call_wn = Make_Runtime_Call("__throw",
00106 Make_Function_Type(MTYPE_To_TY(MTYPE_V)));
00107 WFE_Stmt_Append(call_wn, Get_Srcpos());
00108 }
00109
00110 void WFE_Expand_EH_Region_End(tree handler)
00111 {
00112 EH_INFO eh_info = eh_info_stack.back();
00113 eh_info_stack.pop_back();
00114 LABEL_IDX skip_label_idx = Get_New_Label_Idx();
00115 WN * goto_wn = WN_CreateGoto(skip_label_idx);
00116 WFE_Stmt_Append(goto_wn, Get_Srcpos());
00117 WN * outer_context_wn = WN_CreateLabel((ST_IDX) 0, eh_info.outer_context,
00118 0, NULL);
00119 WFE_Stmt_Append(outer_context_wn, Get_Srcpos());
00120 WFE_Expand_Internal_Throw();
00121 WN * skip_label_wn = WN_CreateLabel((ST_IDX) 0, skip_label_idx, 0, NULL);
00122 WFE_Stmt_Append(skip_label_wn, Get_Srcpos());
00123 eh_info.finalization = handler;
00124 eh_info_queue.push(eh_info);
00125 }
00126
00127 void WFE_Expand_Leftover_Cleanups()
00128 {
00129 while (!eh_info_queue.empty()) {
00130 EH_INFO eh_info = eh_info_queue.front();
00131 Is_True(eh_info.finalization != NULL_TREE,
00132 ("WFE_Expand_Leftover_Cleanups: unexpected leftover try-block"));
00133 WFE_Stmt_Append(
00134 WN_CreateLabel((ST_IDX) 0, eh_info.handler, 0, NULL),
00135 Get_Srcpos());
00136 WFE_Expand_Expr(eh_info.finalization, false);
00137 WFE_Stmt_Append(
00138 WN_CreateGoto(eh_info.outer_context),
00139 Get_Srcpos());
00140 eh_info_queue.pop();
00141 }
00142 }
00143
00144 void WFE_Expand_Start_All_Catch()
00145 {
00146 caught_return_label_stack.push_back(Get_New_Label_Idx());
00147 WFE_Expand_EH_Region_End(NULL_TREE);
00148
00149 LABEL_IDX outer_context = eh_info_stack.back().outer_context;
00150
00151 Is_True(!eh_info_queue.empty(),
00152 ("WFE_Expand_Start_all_Catch: \
00153 eh_info_queue unexpectedly empty: no try handler found"));
00154 while (eh_info_queue.front().finalization != NULL_TREE) {
00155 EH_INFO eh_info = eh_info_queue.front();
00156 WFE_Expand_Expr(eh_info.finalization);
00157 WFE_Stmt_Append(
00158 WN_CreateGoto(eh_info.outer_context),
00159 Get_Srcpos());
00160 eh_info_queue.pop();
00161 Is_True(!eh_info_queue.empty(),
00162 ("WFE_Expand_Start_All_Catch: \
00163 eh_info_queue unexpectedly empty: no try handler found"));
00164 }
00165
00166 EH_INFO eh_info = eh_info_queue.front();
00167 eh_info_queue.pop();
00168 catch_stack.push_back(eh_info);
00169 WFE_Expand_EH_Region_Start();
00170 eh_info_stack.back().outer_context = outer_context;
00171
00172 WFE_Stmt_Append(
00173 WN_CreateLabel((ST_IDX) 0, catch_stack.back().handler, 0, NULL),
00174 Get_Srcpos());
00175 }
00176
00177 void WFE_Expand_End_All_Catch()
00178 {
00179 Is_True(!catch_stack.empty(),
00180 ("WFE_Expand_All_Catch: catch_stack unexpectedly empty"));
00181 EH_INFO eh_info = catch_stack.back();
00182 catch_stack.pop_back();
00183 Is_True(!eh_info_stack.empty(),
00184 ("WFE_Expand_All_Catch: eh_info_stack unexpectedly empty"));
00185 LABEL_IDX outer_context = eh_info_stack.back().outer_context;
00186 WFE_Expand_EH_Region_End(NULL_TREE);
00187
00188 WFE_Stmt_Append(
00189 WN_CreateGoto(outer_context),
00190 Get_Srcpos());
00191
00192 }