psabiehpi.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Information about the current procedure that is being compiled
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit psabiehpi;
  18. { $define debug_eh}
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. { common }
  23. cclasses,
  24. { global }
  25. globtype,
  26. { symtable }
  27. symconst,symtype,symdef,symsym,
  28. node,
  29. { aasm }
  30. cpubase,cgbase,cgutils,
  31. aasmbase,aasmdata,aasmtai,
  32. psub;
  33. type
  34. TPSABIEHAction = class
  35. landingpad : TAsmLabel;
  36. actiontablelabel : TAsmLabel;
  37. actionlist : TAsmList;
  38. first : boolean;
  39. constructor Create(pad : TAsmLabel);
  40. destructor Destroy; override;
  41. function AddAction(p: tobjectdef): LongInt;
  42. end;
  43. { This object gives information on the current routine being
  44. compiled.
  45. }
  46. tpsabiehprocinfo = class(tcgprocinfo)
  47. { psabieh stuff, might be subject to be moved elsewhere }
  48. { gcc exception table list that belongs to this routine }
  49. callsite_table_data,
  50. action_table_data,
  51. gcc_except_table_data : TAsmList;
  52. typefilterlistlabel,typefilterlistlabelref,
  53. callsitetablestart,callsitetableend : TAsmLabel;
  54. callsitelaststart : TAsmLabel;
  55. typefilterlist,
  56. landingpadstack,
  57. actionstack : tfplist;
  58. CurrentCallSiteNumber : Longint;
  59. destructor destroy; override;
  60. { PSABIEH stuff }
  61. procedure PushAction(action: TPSABIEHAction);
  62. function CurrentAction: TPSABIEHAction;inline;
  63. function PopAction(action: TPSABIEHAction): boolean;
  64. { a landing pad is also an action, however, when the landing pad is popped from the stack
  65. the area covered by this landing pad ends, i.e. it is popped at the beginning of the finally/except clause,
  66. the action above is popped at the end of the finally/except clause, so if on clauses add new types, they
  67. are added to CurrentAction }
  68. procedure PushLandingPad(action: TPSABIEHAction);
  69. function CurrentLandingPad: TPSABIEHAction;inline;
  70. function PopLandingPad(action: TPSABIEHAction): boolean;
  71. procedure CreateNewPSABIEHCallsite;
  72. { adds a new type to the type filter list and returns its index
  73. be aware, that this method can also handle catch all filters so it
  74. is valid to pass nil }
  75. function AddTypeFilter(p: tobjectdef): Longint;
  76. procedure set_eh_info; override;
  77. procedure setup_eh; override;
  78. procedure finish_eh; override;
  79. end;
  80. implementation
  81. uses
  82. cutils,
  83. verbose,
  84. systems,
  85. dwarfbase,
  86. cfidwarf,
  87. globals,
  88. procinfo,
  89. symtable,
  90. defutil,
  91. tgobj,
  92. cgobj,
  93. parabase,paramgr,
  94. hlcgobj,
  95. pass_2,
  96. ncgflw;
  97. type
  98. { Utility class for exception handling state management that is used
  99. by tryexcept/tryfinally/on nodes (in a separate class so it can both
  100. be shared and overridden)
  101. Never instantiated. }
  102. tpsabiehexceptionstatehandler = class(tcgexceptionstatehandler)
  103. protected
  104. class procedure begin_catch_internal(list: TAsmList; excepttype: tobjectdef; nextonlabel: tasmlabel; add_catch: boolean; out exceptlocdef: tdef; out
  105. exceptlocreg: tregister);
  106. class procedure catch_all_start_internal(list: TAsmList; add_catch: boolean);
  107. public
  108. class procedure get_exception_temps(list:TAsmList;var t:texceptiontemps); override;
  109. class procedure unget_exception_temps(list:TAsmList;const t:texceptiontemps); override;
  110. class procedure new_exception(list:TAsmList;const t:texceptiontemps; const exceptframekind: texceptframekind; out exceptstate: texceptionstate); override;
  111. { start of "except/finally" block }
  112. class procedure emit_except_label(list: TAsmList; exceptframekind: texceptframekind; var exceptionstate: texceptionstate;var exceptiontemps:texceptiontemps); override;
  113. { end of a try-block, label comes after the end of try/except or
  114. try/finally }
  115. class procedure end_try_block(list: TAsmList; exceptframekind: texceptframekind; const t: texceptiontemps; var exceptionstate: texceptionstate; endlabel: TAsmLabel); override;
  116. class procedure free_exception(list: TAsmList; const t: texceptiontemps; const s: texceptionstate; a: aint; endexceptlabel: tasmlabel; onlyfree:boolean); override;
  117. class procedure handle_reraise(list:TAsmList;const t:texceptiontemps;const entrystate: texceptionstate; const exceptframekind: texceptframekind); override;
  118. { start of an "on" (catch) block }
  119. class procedure begin_catch(list: TAsmList; excepttype: tobjectdef; nextonlabel: tasmlabel; out exceptlocdef: tdef; out exceptlocreg: tregister); override;
  120. { end of an "on" (catch) block }
  121. class procedure end_catch(list: TAsmList); override;
  122. { called for a catch all exception }
  123. class procedure catch_all_start(list: TAsmList); override;
  124. class procedure catch_all_end(list: TAsmList); override;
  125. class procedure catch_all_add(list: TAsmList); override;
  126. class procedure cleanupobjectstack(list: TAsmList); override;
  127. class procedure popaddrstack(list: TAsmList); override;
  128. end;
  129. constructor TPSABIEHAction.Create(pad: TAsmLabel);
  130. begin
  131. landingpad:=pad;
  132. actionlist:=TAsmList.create;
  133. current_asmdata.getlabel(actiontablelabel,alt_data);
  134. actionlist.concat(tai_label.create(actiontablelabel));
  135. first:=true;
  136. end;
  137. destructor TPSABIEHAction.Destroy;
  138. begin
  139. if not(actionlist.Empty) then
  140. Internalerror(2019020501);
  141. actionlist.Free;
  142. inherited Destroy;
  143. end;
  144. function TPSABIEHAction.AddAction(p: tobjectdef) : LongInt;
  145. var
  146. index: LongInt;
  147. begin
  148. { if not first entry, signal that another action follows }
  149. if not(first) then
  150. actionlist.concat(tai_const.Create_uleb128bit(1));
  151. first:=false;
  152. { catch all? }
  153. if p=tobjectdef(-1) then
  154. index:=(current_procinfo as tpsabiehprocinfo).AddTypeFilter(nil)
  155. else if assigned(p) then
  156. index:=(current_procinfo as tpsabiehprocinfo).AddTypeFilter(p)
  157. else
  158. index:=-1;
  159. {$ifdef debug_eh}
  160. if p=tobjectdef(-1) then
  161. actionlist.concat(tai_comment.Create(strpnew('Catch all')))
  162. else if assigned(p) then
  163. actionlist.concat(tai_comment.Create(strpnew('Action for '+p.GetTypeName)))
  164. else
  165. actionlist.concat(tai_comment.Create(strpnew('Cleanup')));
  166. {$endif debug_eh}
  167. if assigned(p) then
  168. actionlist.concat(tai_const.Create_uleb128bit(index+1))
  169. else
  170. actionlist.concat(tai_const.Create_uleb128bit(0));
  171. Result:=index;
  172. end;
  173. {****************************************************************************
  174. tpsabiehprocinfo
  175. ****************************************************************************}
  176. destructor tpsabiehprocinfo.destroy;
  177. begin
  178. gcc_except_table_data.free;
  179. actionstack.free;
  180. landingpadstack.free;
  181. typefilterlist.free;
  182. callsite_table_data.Free;
  183. action_table_data.Free;
  184. inherited;
  185. end;
  186. procedure tpsabiehprocinfo.PushAction(action: TPSABIEHAction);
  187. begin
  188. actionstack.add(action);
  189. end;
  190. function tpsabiehprocinfo.PopAction(action: TPSABIEHAction): boolean;
  191. var
  192. curpos: tasmlabel;
  193. begin
  194. include(flags,pi_has_except_table_data);
  195. if CurrentAction<>action then
  196. internalerror(2019021006);
  197. { no further actions follow, finalize table }
  198. if landingpadstack.count>0 then
  199. begin
  200. current_asmdata.getlabel(curpos,alt_data);
  201. action.actionlist.concat(tai_label.create(curpos));
  202. action.actionlist.concat(tai_const.Create_rel_sym(aitconst_sleb128bit,curpos,TPSABIEHAction(landingpadstack[landingpadstack.count-1]).actiontablelabel));
  203. end
  204. else
  205. action.actionlist.concat(tai_const.Create_uleb128bit(0));
  206. action_table_data.concatList(action.actionlist);
  207. actionstack.count:=actionstack.count-1;
  208. result:=actionstack.count=0;
  209. end;
  210. procedure tpsabiehprocinfo.PushLandingPad(action: TPSABIEHAction);
  211. begin
  212. landingpadstack.add(action);
  213. end;
  214. function tpsabiehprocinfo.CurrentLandingPad: TPSABIEHAction;
  215. begin
  216. result:=TPSABIEHAction(landingpadstack.last);
  217. end;
  218. function tpsabiehprocinfo.PopLandingPad(action: TPSABIEHAction): boolean;
  219. begin
  220. if CurrentLandingPad<>action then
  221. internalerror(2019021007);
  222. landingpadstack.count:=landingpadstack.count-1;
  223. result:=landingpadstack.count=0;
  224. end;
  225. procedure tpsabiehprocinfo.CreateNewPSABIEHCallsite;
  226. var
  227. callsiteend : TAsmLabel;
  228. begin
  229. include(flags,pi_has_except_table_data);
  230. { first, finish last entry }
  231. if assigned(callsitelaststart) and assigned(CurrentLandingPad) then
  232. begin
  233. {$ifdef debug_eh}
  234. if assigned(CurrentLandingPad.actiontablelabel) then
  235. callsite_table_data.concat(tai_comment.Create(strpnew('Call site '+tostr(CurrentCallSiteNumber)+', action table index = '+tostr(landingpadstack.count-1))))
  236. else
  237. callsite_table_data.concat(tai_comment.Create(strpnew('Call site '+tostr(CurrentCallSiteNumber)+', no action')));
  238. {$endif debug_eh}
  239. callsite_table_data.concat(tai_const.create_rel_sym(aitconst_uleb128bit,TDwarfAsmCFI(current_asmdata.AsmCFI).get_frame_start,callsitelaststart));
  240. current_asmdata.getlabel(callsiteend,alt_eh_end);
  241. current_asmdata.CurrAsmList.concat(tai_label.create(callsiteend));
  242. callsite_table_data.concat(tai_const.create_rel_sym(aitconst_uleb128bit,callsitelaststart,callsiteend));
  243. { landing pad? }
  244. if assigned(CurrentLandingPad.landingpad) then
  245. callsite_table_data.concat(tai_const.create_rel_sym(aitconst_uleb128bit,TDwarfAsmCFI(current_asmdata.AsmCFI).get_frame_start,CurrentLandingPad.landingpad))
  246. else
  247. callsite_table_data.concat(tai_const.Create_uleb128bit(0));
  248. { action number set? if yes, concat }
  249. if assigned(CurrentLandingPad.actiontablelabel) then
  250. begin
  251. callsite_table_data.concat(tai_const.Create_rel_sym_offset(aitconst_uleb128bit,callsitetableend,CurrentLandingPad.actiontablelabel,1));
  252. {$ifdef debug_eh}
  253. current_asmdata.CurrAsmList.concat(tai_comment.Create(strpnew('New call site '+tostr(CurrentCallSiteNumber)+', action table index = '+tostr(landingpadstack.count-1))));
  254. {$endif debug_eh}
  255. end
  256. else
  257. begin
  258. callsite_table_data.concat(tai_const.Create_uleb128bit(0));
  259. {$ifdef debug_eh}
  260. current_asmdata.CurrAsmList.concat(tai_comment.Create(strpnew('New call site '+tostr(CurrentCallSiteNumber)+', no action')));
  261. {$endif debug_eh}
  262. end
  263. end;
  264. current_asmdata.getlabel(callsitelaststart,alt_eh_begin);
  265. current_asmdata.CurrAsmList.concat(tai_label.create(callsitelaststart));
  266. Inc(CurrentCallSiteNumber);
  267. end;
  268. function tpsabiehprocinfo.AddTypeFilter(p: tobjectdef) : Longint;
  269. var
  270. i: Integer;
  271. begin
  272. for i:=0 to typefilterlist.count-1 do
  273. begin
  274. if tobjectdef(typefilterlist[i])=p then
  275. begin
  276. result:=i;
  277. exit;
  278. end;
  279. end;
  280. result:=typefilterlist.add(p);
  281. end;
  282. procedure tpsabiehprocinfo.set_eh_info;
  283. begin
  284. inherited set_eh_info;
  285. if (tf_use_psabieh in target_info.flags) and not(pi_has_except_table_data in flags) then
  286. (current_asmdata.AsmCFI as TDwarfAsmCFI).LSDALabel:=nil;
  287. end;
  288. function tpsabiehprocinfo.CurrentAction: TPSABIEHAction; inline;
  289. begin
  290. result:=TPSABIEHAction(actionstack.last);
  291. end;
  292. procedure tpsabiehprocinfo.setup_eh;
  293. var
  294. gcc_except_table: tai_section;
  295. begin
  296. gcc_except_table_data:=TAsmList.Create;
  297. callsite_table_data:=TAsmList.Create;
  298. action_table_data:=TAsmList.Create;
  299. actionstack:=TFPList.Create;
  300. landingpadstack:=TFPList.Create;
  301. typefilterlist:=TFPList.Create;
  302. gcc_except_table:=new_section(gcc_except_table_data,sec_gcc_except_table,'',0);
  303. gcc_except_table.secflags:=SF_A;
  304. gcc_except_table.secprogbits:=SPB_PROGBITS;
  305. if not(current_asmdata.AsmCFI is TDwarfAsmCFI) then
  306. internalerror(2019021003);
  307. {$ifdef debug_eh}
  308. gcc_except_table_data.concat(tai_comment.Create(strpnew('gcc_except_table for '+procdef.fullprocname(true))));
  309. {$endif debug_eh}
  310. current_asmdata.getlabel(TDwarfAsmCFI(current_asmdata.AsmCFI).LSDALabel,alt_data);
  311. current_asmdata.getlabel(callsitetablestart,alt_data);
  312. current_asmdata.getlabel(callsitetableend,alt_data);
  313. callsite_table_data.concat(tai_label.create(callsitetablestart));
  314. cexceptionstatehandler:=tpsabiehexceptionstatehandler;
  315. end;
  316. procedure tpsabiehprocinfo.finish_eh;
  317. var
  318. i: Integer;
  319. begin
  320. if (tf_use_psabieh in target_info.flags) then
  321. begin
  322. if pi_has_except_table_data in flags then
  323. begin
  324. gcc_except_table_data.concat(tai_label.create(TDwarfAsmCFI(current_asmdata.AsmCFI).LSDALabel));
  325. { landing pad base is relative to procedure start, so write an omit }
  326. gcc_except_table_data.concat(tai_const.create_8bit(DW_EH_PE_omit));
  327. if typefilterlist.count>0 then
  328. begin
  329. gcc_except_table_data.concat(tai_const.create_8bit(DW_EH_PE_udata4));
  330. current_asmdata.getlabel(typefilterlistlabel,alt_data);
  331. current_asmdata.getlabel(typefilterlistlabelref,alt_data);
  332. gcc_except_table_data.concat(tai_const.create_rel_sym(aitconst_uleb128bit,typefilterlistlabel,typefilterlistlabelref));
  333. gcc_except_table_data.concat(tai_label.create(typefilterlistlabel));
  334. end
  335. else
  336. { default types table encoding }
  337. gcc_except_table_data.concat(tai_const.create_8bit(DW_EH_PE_omit));
  338. { call-site table encoded using uleb128 }
  339. gcc_except_table_data.concat(tai_const.create_8bit(DW_EH_PE_uleb128));
  340. gcc_except_table_data.concat(tai_const.create_rel_sym(aitconst_uleb128bit,callsitetablestart,callsitetableend));
  341. callsite_table_data.concat(tai_label.create(callsitetableend));
  342. {$ifdef debug_eh}
  343. gcc_except_table_data.concat(tai_comment.Create(strpnew('Call site table for '+procdef.fullprocname(true))));
  344. {$endif debug_eh}
  345. gcc_except_table_data.concatList(callsite_table_data);
  346. { action table must follow immediatly after callsite table }
  347. {$ifdef debug_eh}
  348. if not(action_table_data.Empty) then
  349. gcc_except_table_data.concat(tai_comment.Create(strpnew('Action table for '+procdef.fullprocname(true))));
  350. {$endif debug_eh}
  351. gcc_except_table_data.concatlist(action_table_data);
  352. if typefilterlist.count>0 then
  353. begin
  354. {$ifdef debug_eh}
  355. gcc_except_table_data.concat(tai_comment.Create(strpnew('Type filter list for '+procdef.fullprocname(true))));
  356. {$endif debug_eh}
  357. for i:=typefilterlist.count-1 downto 0 do
  358. begin
  359. {$ifdef debug_eh}
  360. gcc_except_table_data.concat(tai_comment.Create(strpnew('Type filter '+tostr(i))));
  361. {$endif debug_eh}
  362. if assigned(typefilterlist[i]) then
  363. gcc_except_table_data.concat(tai_const.Create_sym(current_asmdata.RefAsmSymbol(tobjectdef(typefilterlist[i]).vmt_mangledname, AT_DATA)))
  364. else
  365. gcc_except_table_data.concat(tai_const.Create_32bit(0));
  366. end;
  367. { the types are resolved by the negative offset, so the label must be written after all types }
  368. gcc_except_table_data.concat(tai_label.create(typefilterlistlabelref));
  369. end;
  370. new_section(gcc_except_table_data,sec_code,'',0);
  371. aktproccode.concatlist(gcc_except_table_data);
  372. end;
  373. end;
  374. end;
  375. class procedure tpsabiehexceptionstatehandler.get_exception_temps(list: TAsmList; var t: texceptiontemps);
  376. begin
  377. tg.gethltemp(list,ossinttype,ossinttype.size,tt_persistent,t.reasonbuf);
  378. end;
  379. class procedure tpsabiehexceptionstatehandler.unget_exception_temps(list: TAsmList; const t: texceptiontemps);
  380. begin
  381. tg.ungettemp(list,t.reasonbuf);
  382. (current_procinfo as tpsabiehprocinfo).PopAction((current_procinfo as tpsabiehprocinfo).CurrentAction);
  383. end;
  384. class procedure tpsabiehexceptionstatehandler.new_exception(list: TAsmList; const t: texceptiontemps;
  385. const exceptframekind: texceptframekind; out exceptstate: texceptionstate);
  386. var
  387. reg: tregister;
  388. action: TPSABIEHAction;
  389. begin
  390. exceptstate.oldflowcontrol:=flowcontrol;
  391. current_asmdata.getjumplabel(exceptstate.exceptionlabel);
  392. if exceptframekind<>tek_except then
  393. begin
  394. current_asmdata.getjumplabel(exceptstate.finallycodelabel);
  395. action:=TPSABIEHAction.Create(exceptstate.finallycodelabel);
  396. end
  397. else
  398. begin
  399. exceptstate.finallycodelabel:=nil;
  400. action:=TPSABIEHAction.Create(exceptstate.exceptionlabel);
  401. end;
  402. (current_procinfo as tpsabiehprocinfo).CreateNewPSABIEHCallsite;
  403. (current_procinfo as tpsabiehprocinfo).PushAction(action);
  404. (current_procinfo as tpsabiehprocinfo).PushLandingPad(action);
  405. if exceptframekind<>tek_except then
  406. { no safecall? }
  407. if use_cleanup(exceptframekind) then
  408. (current_procinfo as tpsabiehprocinfo).CurrentAction.AddAction(nil)
  409. else
  410. { if safecall, catch all }
  411. (current_procinfo as tpsabiehprocinfo).CurrentAction.AddAction(tobjectdef(-1));
  412. flowcontrol:=[fc_inflowcontrol,fc_catching_exceptions];
  413. if exceptframekind<>tek_except then
  414. begin
  415. reg:=hlcg.getintregister(list,ossinttype);
  416. hlcg.a_load_const_reg(list,ossinttype,1,reg);
  417. hlcg.g_exception_reason_save(list,ossinttype,ossinttype,reg,t.reasonbuf);
  418. end;
  419. end;
  420. class procedure tpsabiehexceptionstatehandler.emit_except_label(list: TAsmList; exceptframekind: texceptframekind;
  421. var exceptionstate: texceptionstate;var exceptiontemps:texceptiontemps);
  422. begin
  423. hlcg.g_unreachable(list);
  424. hlcg.a_label(list,exceptionstate.exceptionlabel);
  425. if exceptframekind<>tek_except then
  426. begin
  427. if not assigned(exceptionstate.finallycodelabel) then
  428. internalerror(2019021002);
  429. hlcg.a_label(list,exceptionstate.finallycodelabel);
  430. exceptionstate.finallycodelabel:=nil;
  431. exceptiontemps.unwind_info:=cg.getaddressregister(list);
  432. hlcg.a_load_reg_reg(list,voidpointertype,voidpointertype,NR_FUNCTION_RESULT_REG,exceptiontemps.unwind_info);
  433. end;
  434. end;
  435. class procedure tpsabiehexceptionstatehandler.end_try_block(list: TAsmList; exceptframekind: texceptframekind; const t: texceptiontemps;
  436. var exceptionstate: texceptionstate; endlabel: TAsmLabel);
  437. var
  438. reg: TRegister;
  439. begin
  440. (current_procinfo as tpsabiehprocinfo).CreateNewPSABIEHCallsite;
  441. (current_procinfo as tpsabiehprocinfo).PopLandingPad((current_procinfo as tpsabiehprocinfo).CurrentLandingPad);
  442. if exceptframekind<>tek_except then
  443. begin
  444. { record that no exception happened in the reason buf, in case we are in a try block of a finally statement }
  445. reg:=hlcg.getintregister(list,ossinttype);
  446. hlcg.a_load_const_reg(list,ossinttype,0,reg);
  447. hlcg.g_exception_reason_save(list,ossinttype,ossinttype,reg,t.reasonbuf);
  448. end;
  449. inherited;
  450. if exceptframekind=tek_except then
  451. hlcg.a_jmp_always(list,endlabel);
  452. end;
  453. class procedure tpsabiehexceptionstatehandler.free_exception(list: TAsmList; const t: texceptiontemps; const s: texceptionstate; a: aint;
  454. endexceptlabel: tasmlabel; onlyfree: boolean);
  455. begin
  456. (current_procinfo as tpsabiehprocinfo).CreateNewPSABIEHCallsite;
  457. // inherited free_exception(list, t, s, a, endexceptlabel, onlyfree);
  458. end;
  459. class procedure tpsabiehexceptionstatehandler.handle_reraise(list: TAsmList; const t: texceptiontemps; const entrystate: texceptionstate;
  460. const exceptframekind: texceptframekind);
  461. var
  462. cgpara1: tcgpara;
  463. pd: tprocdef;
  464. action, ReRaiseLandingPad: TPSABIEHAction;
  465. psabiehprocinfo: tpsabiehprocinfo;
  466. begin
  467. if not(fc_catching_exceptions in flowcontrol) and
  468. use_cleanup(exceptframekind) then
  469. begin
  470. { Resume might not be called outside of an landing pad else
  471. the unwind is immediatly terminated, so create an empty landing pad }
  472. psabiehprocinfo:=current_procinfo as tpsabiehprocinfo;
  473. psabiehprocinfo.CreateNewPSABIEHCallsite;
  474. ReRaiseLandingPad:=TPSABIEHAction.Create(nil);
  475. psabiehprocinfo.PushAction(ReRaiseLandingPad);
  476. psabiehprocinfo.PushLandingPad(ReRaiseLandingPad);
  477. pd:=search_system_proc('fpc_resume');
  478. cgpara1.init;
  479. paramanager.getintparaloc(list,pd,1,cgpara1);
  480. hlcg.a_load_reg_cgpara(list,voidpointertype,t.unwind_info,cgpara1);
  481. paramanager.freecgpara(list,cgpara1);
  482. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_resume',[@cgpara1],nil).resetiftemp;
  483. cgpara1.done;
  484. psabiehprocinfo.CreateNewPSABIEHCallsite;
  485. psabiehprocinfo.PopLandingPad(psabiehprocinfo.CurrentLandingPad);
  486. psabiehprocinfo.PopAction(ReRaiseLandingPad);
  487. end
  488. else
  489. begin
  490. psabiehprocinfo:=current_procinfo as tpsabiehprocinfo;
  491. { empty landing pad needed to avoid immediate termination? }
  492. if psabiehprocinfo.landingpadstack.Count=0 then
  493. begin
  494. psabiehprocinfo.CreateNewPSABIEHCallsite;
  495. ReRaiseLandingPad:=TPSABIEHAction.Create(nil);
  496. psabiehprocinfo.PushAction(ReRaiseLandingPad);
  497. psabiehprocinfo.PushLandingPad(ReRaiseLandingPad);
  498. end
  499. else
  500. ReRaiseLandingPad:=nil;
  501. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_reraise',[],nil).resetiftemp;
  502. if assigned(ReRaiseLandingPad) then
  503. begin
  504. psabiehprocinfo.CreateNewPSABIEHCallsite;
  505. psabiehprocinfo.PopLandingPad(psabiehprocinfo.CurrentLandingPad);
  506. psabiehprocinfo.PopAction(ReRaiseLandingPad);
  507. end;
  508. end;
  509. end;
  510. class procedure tpsabiehexceptionstatehandler.begin_catch_internal(list: TAsmList; excepttype: tobjectdef; nextonlabel: tasmlabel;
  511. add_catch: boolean; out exceptlocdef: tdef; out exceptlocreg: tregister);
  512. var
  513. catchstartlab : tasmlabel;
  514. begincatchres,
  515. typeidres,
  516. paraloc1: tcgpara;
  517. pd: tprocdef;
  518. landingpadstructdef,
  519. landingpadtypeiddef: tdef;
  520. rttisym: TAsmSymbol;
  521. rttidef: tdef;
  522. rttiref: treference;
  523. wrappedexception,
  524. exceptiontypeidreg,
  525. landingpadres: tregister;
  526. exceptloc: tlocation;
  527. indirect: boolean;
  528. otherunit: boolean;
  529. typeindex : aint;
  530. begin
  531. paraloc1.init;
  532. rttidef:=nil;
  533. rttisym:=nil;
  534. if add_catch then
  535. begin
  536. if assigned(excepttype) then
  537. begin
  538. otherunit:=findunitsymtable(excepttype.owner).moduleid<>findunitsymtable(current_procinfo.procdef.owner).moduleid;
  539. indirect:=(tf_supports_packages in target_info.flags) and
  540. (target_info.system in systems_indirect_var_imports) and
  541. (cs_imported_data in current_settings.localswitches) and
  542. otherunit;
  543. { add "catch exceptiontype" clause to the landing pad }
  544. rttidef:=cpointerdef.getreusable(excepttype.vmt_def);
  545. rttisym:=current_asmdata.RefAsmSymbol(excepttype.vmt_mangledname, AT_DATA, indirect);
  546. end;
  547. end;
  548. { check if the exception is handled by this node }
  549. if assigned(excepttype) then
  550. begin
  551. typeindex:=(current_procinfo as tpsabiehprocinfo).CurrentAction.AddAction(excepttype);
  552. current_asmdata.getjumplabel(catchstartlab);
  553. {$ifdef i386}
  554. hlcg.a_cmp_const_reg_label (list,osuinttype,OC_EQ,typeindex+1,NR_FUNCTION_RESULT64_HIGH_REG,catchstartlab);
  555. {$else i386}
  556. { we need to find a way to fix this in a generic way }
  557. Internalerror(2019021008);
  558. {$endif i386}
  559. hlcg.a_jmp_always(list,nextonlabel);
  560. hlcg.a_label(list,catchstartlab);
  561. end
  562. else
  563. (current_procinfo as tpsabiehprocinfo).CurrentAction.AddAction(tobjectdef(-1));
  564. wrappedexception:=hlcg.getaddressregister(list,voidpointertype);
  565. pd:=search_system_proc('fpc_psabi_begin_catch');
  566. paramanager.getintparaloc(list, pd, 1, paraloc1);
  567. hlcg.a_load_reg_cgpara(list,voidpointertype,wrappedexception,paraloc1);
  568. begincatchres:=hlcg.g_call_system_proc(list,pd,[@paraloc1],nil);
  569. location_reset(exceptloc, LOC_REGISTER, def_cgsize(begincatchres.def));
  570. exceptloc.register:=hlcg.getaddressregister(list, begincatchres.def);
  571. hlcg.gen_load_cgpara_loc(list, begincatchres.def, begincatchres, exceptloc, true);
  572. begincatchres.resetiftemp;
  573. paraloc1.done;
  574. exceptlocdef:=begincatchres.def;
  575. exceptlocreg:=exceptloc.register;
  576. end;
  577. class procedure tpsabiehexceptionstatehandler.catch_all_start_internal(list: TAsmList; add_catch: boolean);
  578. var
  579. exceptlocdef: tdef;
  580. exceptlocreg: tregister;
  581. begin
  582. begin_catch_internal(list,nil,nil,add_catch,exceptlocdef,exceptlocreg);
  583. end;
  584. class procedure tpsabiehexceptionstatehandler.begin_catch(list: TAsmList; excepttype: tobjectdef; nextonlabel: tasmlabel; out exceptlocdef: tdef; out
  585. exceptlocreg: tregister);
  586. begin
  587. begin_catch_internal(list,excepttype,nextonlabel,true,exceptlocdef,exceptlocreg);
  588. end;
  589. class procedure tpsabiehexceptionstatehandler.end_catch(list: TAsmList);
  590. begin
  591. hlcg.g_call_system_proc(list,'fpc_psabi_end_catch',[],nil).resetiftemp;
  592. inherited;
  593. end;
  594. class procedure tpsabiehexceptionstatehandler.catch_all_start(list: TAsmList);
  595. begin
  596. catch_all_start_internal(list,true);
  597. end;
  598. class procedure tpsabiehexceptionstatehandler.catch_all_add(list: TAsmList);
  599. begin
  600. (current_procinfo as tpsabiehprocinfo).CurrentAction.AddAction(nil);
  601. end;
  602. class procedure tpsabiehexceptionstatehandler.catch_all_end(list: TAsmList);
  603. begin
  604. hlcg.g_call_system_proc(list,'fpc_psabi_end_catch',[],nil).resetiftemp;
  605. end;
  606. class procedure tpsabiehexceptionstatehandler.cleanupobjectstack(list: TAsmList);
  607. begin
  608. // inherited cleanupobjectstack(list);
  609. //!!! some catch all clause needed?
  610. //!!! internalerror(2019021004)
  611. end;
  612. class procedure tpsabiehexceptionstatehandler.popaddrstack(list: TAsmList);
  613. begin
  614. { there is no addr stack, so do nothing }
  615. end;
  616. end.