psabiehpi.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  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 cleanupobjectstack(list: TAsmList); override;
  126. class procedure popaddrstack(list: TAsmList); override;
  127. end;
  128. constructor TPSABIEHAction.Create(pad: TAsmLabel);
  129. begin
  130. landingpad:=pad;
  131. actionlist:=TAsmList.create;
  132. current_asmdata.getlabel(actiontablelabel,alt_data);
  133. actionlist.concat(tai_label.create(actiontablelabel));
  134. first:=true;
  135. end;
  136. destructor TPSABIEHAction.Destroy;
  137. begin
  138. if not(actionlist.Empty) then
  139. Internalerror(2019020501);
  140. actionlist.Free;
  141. inherited Destroy;
  142. end;
  143. function TPSABIEHAction.AddAction(p: tobjectdef) : LongInt;
  144. var
  145. index: LongInt;
  146. begin
  147. { if not first entry, signal that another action follows }
  148. if not(first) then
  149. actionlist.concat(tai_const.Create_uleb128bit(1));
  150. first:=false;
  151. { catch all? }
  152. if p=tobjectdef(-1) then
  153. index:=(current_procinfo as tpsabiehprocinfo).AddTypeFilter(nil)
  154. else if assigned(p) then
  155. index:=(current_procinfo as tpsabiehprocinfo).AddTypeFilter(p)
  156. else
  157. index:=-1;
  158. {$ifdef debug_eh}
  159. if p=tobjectdef(-1) then
  160. actionlist.concat(tai_comment.Create(strpnew('Catch all')))
  161. else if assigned(p) then
  162. actionlist.concat(tai_comment.Create(strpnew('Action for '+p.GetTypeName)))
  163. else
  164. actionlist.concat(tai_comment.Create(strpnew('Cleanup')));
  165. {$endif debug_eh}
  166. if assigned(p) then
  167. actionlist.concat(tai_const.Create_uleb128bit(index+1))
  168. else
  169. actionlist.concat(tai_const.Create_uleb128bit(0));
  170. Result:=index;
  171. end;
  172. {****************************************************************************
  173. tpsabiehprocinfo
  174. ****************************************************************************}
  175. destructor tpsabiehprocinfo.destroy;
  176. begin
  177. gcc_except_table_data.free;
  178. actionstack.free;
  179. landingpadstack.free;
  180. typefilterlist.free;
  181. callsite_table_data.Free;
  182. action_table_data.Free;
  183. inherited;
  184. end;
  185. procedure tpsabiehprocinfo.PushAction(action: TPSABIEHAction);
  186. begin
  187. actionstack.add(action);
  188. end;
  189. function tpsabiehprocinfo.PopAction(action: TPSABIEHAction): boolean;
  190. var
  191. curpos: tasmlabel;
  192. begin
  193. include(flags,pi_has_except_table_data);
  194. if CurrentAction<>action then
  195. internalerror(2019021006);
  196. { no further actions follow, finalize table }
  197. if landingpadstack.count>0 then
  198. begin
  199. current_asmdata.getlabel(curpos,alt_data);
  200. action.actionlist.concat(tai_label.create(curpos));
  201. action.actionlist.concat(tai_const.Create_rel_sym(aitconst_sleb128bit,curpos,TPSABIEHAction(landingpadstack[landingpadstack.count-1]).actiontablelabel));
  202. end
  203. else
  204. action.actionlist.concat(tai_const.Create_uleb128bit(0));
  205. action_table_data.concatList(action.actionlist);
  206. actionstack.count:=actionstack.count-1;
  207. result:=actionstack.count=0;
  208. end;
  209. procedure tpsabiehprocinfo.PushLandingPad(action: TPSABIEHAction);
  210. begin
  211. landingpadstack.add(action);
  212. end;
  213. function tpsabiehprocinfo.CurrentLandingPad: TPSABIEHAction;
  214. begin
  215. result:=TPSABIEHAction(landingpadstack.last);
  216. end;
  217. function tpsabiehprocinfo.PopLandingPad(action: TPSABIEHAction): boolean;
  218. begin
  219. if CurrentLandingPad<>action then
  220. internalerror(2019021007);
  221. landingpadstack.count:=landingpadstack.count-1;
  222. result:=landingpadstack.count=0;
  223. end;
  224. procedure tpsabiehprocinfo.CreateNewPSABIEHCallsite;
  225. var
  226. callsiteend : TAsmLabel;
  227. begin
  228. include(flags,pi_has_except_table_data);
  229. { first, finish last entry }
  230. if assigned(callsitelaststart) and assigned(CurrentLandingPad) then
  231. begin
  232. {$ifdef debug_eh}
  233. if assigned(CurrentLandingPad.actiontablelabel) then
  234. callsite_table_data.concat(tai_comment.Create(strpnew('Call site '+tostr(CurrentCallSiteNumber)+', action table index = '+tostr(landingpadstack.count-1))))
  235. else
  236. callsite_table_data.concat(tai_comment.Create(strpnew('Call site '+tostr(CurrentCallSiteNumber)+', no action')));
  237. {$endif debug_eh}
  238. callsite_table_data.concat(tai_const.create_rel_sym(aitconst_uleb128bit,TDwarfAsmCFI(current_asmdata.AsmCFI).get_frame_start,callsitelaststart));
  239. current_asmdata.getlabel(callsiteend,alt_eh_end);
  240. current_asmdata.CurrAsmList.concat(tai_label.create(callsiteend));
  241. callsite_table_data.concat(tai_const.create_rel_sym(aitconst_uleb128bit,callsitelaststart,callsiteend));
  242. { landing pad? }
  243. if assigned(CurrentLandingPad.landingpad) then
  244. callsite_table_data.concat(tai_const.create_rel_sym(aitconst_uleb128bit,TDwarfAsmCFI(current_asmdata.AsmCFI).get_frame_start,CurrentLandingPad.landingpad))
  245. else
  246. callsite_table_data.concat(tai_const.Create_uleb128bit(0));
  247. { action number set? if yes, concat }
  248. if assigned(CurrentLandingPad.actiontablelabel) then
  249. begin
  250. callsite_table_data.concat(tai_const.Create_rel_sym_offset(aitconst_uleb128bit,callsitetableend,CurrentLandingPad.actiontablelabel,1));
  251. {$ifdef debug_eh}
  252. current_asmdata.CurrAsmList.concat(tai_comment.Create(strpnew('New call site '+tostr(CurrentCallSiteNumber)+', action table index = '+tostr(landingpadstack.count-1))));
  253. {$endif debug_eh}
  254. end
  255. else
  256. begin
  257. callsite_table_data.concat(tai_const.Create_uleb128bit(0));
  258. {$ifdef debug_eh}
  259. current_asmdata.CurrAsmList.concat(tai_comment.Create(strpnew('New call site '+tostr(CurrentCallSiteNumber)+', no action')));
  260. {$endif debug_eh}
  261. end
  262. end;
  263. current_asmdata.getlabel(callsitelaststart,alt_eh_begin);
  264. current_asmdata.CurrAsmList.concat(tai_label.create(callsitelaststart));
  265. Inc(CurrentCallSiteNumber);
  266. end;
  267. function tpsabiehprocinfo.AddTypeFilter(p: tobjectdef) : Longint;
  268. var
  269. i: Integer;
  270. begin
  271. for i:=0 to typefilterlist.count-1 do
  272. begin
  273. if tobjectdef(typefilterlist[i])=p then
  274. begin
  275. result:=i;
  276. exit;
  277. end;
  278. end;
  279. result:=typefilterlist.add(p);
  280. end;
  281. procedure tpsabiehprocinfo.set_eh_info;
  282. begin
  283. inherited set_eh_info;
  284. if (tf_use_psabieh in target_info.flags) and not(pi_has_except_table_data in flags) then
  285. (current_asmdata.AsmCFI as TDwarfAsmCFI).LSDALabel:=nil;
  286. end;
  287. function tpsabiehprocinfo.CurrentAction: TPSABIEHAction; inline;
  288. begin
  289. result:=TPSABIEHAction(actionstack.last);
  290. end;
  291. procedure tpsabiehprocinfo.setup_eh;
  292. var
  293. gcc_except_table: tai_section;
  294. begin
  295. gcc_except_table_data:=TAsmList.Create;
  296. callsite_table_data:=TAsmList.Create;
  297. action_table_data:=TAsmList.Create;
  298. actionstack:=TFPList.Create;
  299. landingpadstack:=TFPList.Create;
  300. typefilterlist:=TFPList.Create;
  301. gcc_except_table:=new_section(gcc_except_table_data,sec_gcc_except_table,'',0);
  302. gcc_except_table.secflags:=SF_A;
  303. gcc_except_table.secprogbits:=SPB_PROGBITS;
  304. if not(current_asmdata.AsmCFI is TDwarfAsmCFI) then
  305. internalerror(2019021003);
  306. {$ifdef debug_eh}
  307. gcc_except_table_data.concat(tai_comment.Create(strpnew('gcc_except_table for '+procdef.fullprocname(true))));
  308. {$endif debug_eh}
  309. current_asmdata.getlabel(TDwarfAsmCFI(current_asmdata.AsmCFI).LSDALabel,alt_data);
  310. current_asmdata.getlabel(callsitetablestart,alt_data);
  311. current_asmdata.getlabel(callsitetableend,alt_data);
  312. callsite_table_data.concat(tai_label.create(callsitetablestart));
  313. cexceptionstatehandler:=tpsabiehexceptionstatehandler;
  314. end;
  315. procedure tpsabiehprocinfo.finish_eh;
  316. var
  317. i: Integer;
  318. begin
  319. if (tf_use_psabieh in target_info.flags) then
  320. begin
  321. if pi_has_except_table_data in flags then
  322. begin
  323. gcc_except_table_data.concat(tai_label.create(TDwarfAsmCFI(current_asmdata.AsmCFI).LSDALabel));
  324. { landing pad base is relative to procedure start, so write an omit }
  325. gcc_except_table_data.concat(tai_const.create_8bit(DW_EH_PE_omit));
  326. if typefilterlist.count>0 then
  327. begin
  328. gcc_except_table_data.concat(tai_const.create_8bit(DW_EH_PE_udata4));
  329. current_asmdata.getlabel(typefilterlistlabel,alt_data);
  330. current_asmdata.getlabel(typefilterlistlabelref,alt_data);
  331. gcc_except_table_data.concat(tai_const.create_rel_sym(aitconst_uleb128bit,typefilterlistlabel,typefilterlistlabelref));
  332. gcc_except_table_data.concat(tai_label.create(typefilterlistlabel));
  333. end
  334. else
  335. { default types table encoding }
  336. gcc_except_table_data.concat(tai_const.create_8bit(DW_EH_PE_omit));
  337. { call-site table encoded using uleb128 }
  338. gcc_except_table_data.concat(tai_const.create_8bit(DW_EH_PE_uleb128));
  339. gcc_except_table_data.concat(tai_const.create_rel_sym(aitconst_uleb128bit,callsitetablestart,callsitetableend));
  340. callsite_table_data.concat(tai_label.create(callsitetableend));
  341. {$ifdef debug_eh}
  342. gcc_except_table_data.concat(tai_comment.Create(strpnew('Call site table for '+procdef.fullprocname(true))));
  343. {$endif debug_eh}
  344. gcc_except_table_data.concatList(callsite_table_data);
  345. { action table must follow immediatly after callsite table }
  346. {$ifdef debug_eh}
  347. if not(action_table_data.Empty) then
  348. gcc_except_table_data.concat(tai_comment.Create(strpnew('Action table for '+procdef.fullprocname(true))));
  349. {$endif debug_eh}
  350. gcc_except_table_data.concatlist(action_table_data);
  351. if typefilterlist.count>0 then
  352. begin
  353. {$ifdef debug_eh}
  354. gcc_except_table_data.concat(tai_comment.Create(strpnew('Type filter list for '+procdef.fullprocname(true))));
  355. {$endif debug_eh}
  356. for i:=typefilterlist.count-1 downto 0 do
  357. begin
  358. {$ifdef debug_eh}
  359. gcc_except_table_data.concat(tai_comment.Create(strpnew('Type filter '+tostr(i))));
  360. {$endif debug_eh}
  361. if assigned(typefilterlist[i]) then
  362. gcc_except_table_data.concat(tai_const.Create_sym(current_asmdata.RefAsmSymbol(tobjectdef(typefilterlist[i]).vmt_mangledname, AT_DATA)))
  363. else
  364. gcc_except_table_data.concat(tai_const.Create_32bit(0));
  365. end;
  366. { the types are resolved by the negative offset, so the label must be written after all types }
  367. gcc_except_table_data.concat(tai_label.create(typefilterlistlabelref));
  368. end;
  369. new_section(gcc_except_table_data,sec_code,'',0);
  370. aktproccode.concatlist(gcc_except_table_data);
  371. end;
  372. end;
  373. end;
  374. class procedure tpsabiehexceptionstatehandler.get_exception_temps(list: TAsmList; var t: texceptiontemps);
  375. begin
  376. tg.gethltemp(list,ossinttype,ossinttype.size,tt_persistent,t.reasonbuf);
  377. end;
  378. class procedure tpsabiehexceptionstatehandler.unget_exception_temps(list: TAsmList; const t: texceptiontemps);
  379. begin
  380. tg.ungettemp(list,t.reasonbuf);
  381. (current_procinfo as tpsabiehprocinfo).PopAction((current_procinfo as tpsabiehprocinfo).CurrentAction);
  382. end;
  383. class procedure tpsabiehexceptionstatehandler.new_exception(list: TAsmList; const t: texceptiontemps;
  384. const exceptframekind: texceptframekind; out exceptstate: texceptionstate);
  385. var
  386. reg: tregister;
  387. action: TPSABIEHAction;
  388. begin
  389. exceptstate.oldflowcontrol:=flowcontrol;
  390. current_asmdata.getjumplabel(exceptstate.exceptionlabel);
  391. if exceptframekind<>tek_except then
  392. begin
  393. current_asmdata.getjumplabel(exceptstate.finallycodelabel);
  394. action:=TPSABIEHAction.Create(exceptstate.finallycodelabel);
  395. end
  396. else
  397. begin
  398. exceptstate.finallycodelabel:=nil;
  399. action:=TPSABIEHAction.Create(exceptstate.exceptionlabel);
  400. end;
  401. (current_procinfo as tpsabiehprocinfo).CreateNewPSABIEHCallsite;
  402. (current_procinfo as tpsabiehprocinfo).PushAction(action);
  403. (current_procinfo as tpsabiehprocinfo).PushLandingPad(action);
  404. if exceptframekind<>tek_except then
  405. (current_procinfo as tpsabiehprocinfo).CurrentAction.AddAction(nil);
  406. flowcontrol:=[fc_inflowcontrol,fc_catching_exceptions];
  407. if exceptframekind<>tek_except then
  408. begin
  409. reg:=hlcg.getintregister(list,ossinttype);
  410. hlcg.a_load_const_reg(list,ossinttype,1,reg);
  411. hlcg.g_exception_reason_save(list,ossinttype,ossinttype,reg,t.reasonbuf);
  412. end;
  413. end;
  414. class procedure tpsabiehexceptionstatehandler.emit_except_label(list: TAsmList; exceptframekind: texceptframekind;
  415. var exceptionstate: texceptionstate;var exceptiontemps:texceptiontemps);
  416. begin
  417. hlcg.g_unreachable(list);
  418. hlcg.a_label(list,exceptionstate.exceptionlabel);
  419. if exceptframekind<>tek_except then
  420. begin
  421. if not assigned(exceptionstate.finallycodelabel) then
  422. internalerror(2019021002);
  423. hlcg.a_label(list,exceptionstate.finallycodelabel);
  424. exceptionstate.finallycodelabel:=nil;
  425. exceptiontemps.unwind_info:=cg.getaddressregister(list);
  426. hlcg.a_load_reg_reg(list,voidpointertype,voidpointertype,NR_FUNCTION_RESULT_REG,exceptiontemps.unwind_info);
  427. end;
  428. end;
  429. class procedure tpsabiehexceptionstatehandler.end_try_block(list: TAsmList; exceptframekind: texceptframekind; const t: texceptiontemps;
  430. var exceptionstate: texceptionstate; endlabel: TAsmLabel);
  431. var
  432. reg: TRegister;
  433. begin
  434. (current_procinfo as tpsabiehprocinfo).CreateNewPSABIEHCallsite;
  435. (current_procinfo as tpsabiehprocinfo).PopLandingPad((current_procinfo as tpsabiehprocinfo).CurrentLandingPad);
  436. if exceptframekind<>tek_except then
  437. begin
  438. { record that no exception happened in the reason buf, in case we are in a try block of a finally statement }
  439. reg:=hlcg.getintregister(list,ossinttype);
  440. hlcg.a_load_const_reg(list,ossinttype,0,reg);
  441. hlcg.g_exception_reason_save(list,ossinttype,ossinttype,reg,t.reasonbuf);
  442. end;
  443. inherited;
  444. if exceptframekind=tek_except then
  445. hlcg.a_jmp_always(list,endlabel);
  446. end;
  447. class procedure tpsabiehexceptionstatehandler.free_exception(list: TAsmList; const t: texceptiontemps; const s: texceptionstate; a: aint;
  448. endexceptlabel: tasmlabel; onlyfree: boolean);
  449. begin
  450. (current_procinfo as tpsabiehprocinfo).CreateNewPSABIEHCallsite;
  451. // inherited free_exception(list, t, s, a, endexceptlabel, onlyfree);
  452. end;
  453. class procedure tpsabiehexceptionstatehandler.handle_reraise(list: TAsmList; const t: texceptiontemps; const entrystate: texceptionstate;
  454. const exceptframekind: texceptframekind);
  455. var
  456. cgpara1: tcgpara;
  457. pd: tprocdef;
  458. action: TPSABIEHAction;
  459. begin
  460. cgpara1.init;
  461. if not(fc_catching_exceptions in flowcontrol) and
  462. use_cleanup(exceptframekind) then
  463. begin
  464. pd:=search_system_proc('fpc_resume');
  465. paramanager.getintparaloc(list,pd,1,cgpara1);
  466. hlcg.a_load_reg_cgpara(list,voidpointertype,t.unwind_info,cgpara1);
  467. paramanager.freecgpara(list,cgpara1);
  468. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_resume',[@cgpara1],nil).resetiftemp
  469. end
  470. else
  471. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_reraise',[],nil).resetiftemp;
  472. cgpara1.done;
  473. end;
  474. class procedure tpsabiehexceptionstatehandler.begin_catch_internal(list: TAsmList; excepttype: tobjectdef; nextonlabel: tasmlabel;
  475. add_catch: boolean; out exceptlocdef: tdef; out exceptlocreg: tregister);
  476. var
  477. catchstartlab : tasmlabel;
  478. begincatchres,
  479. typeidres,
  480. paraloc1: tcgpara;
  481. pd: tprocdef;
  482. landingpadstructdef,
  483. landingpadtypeiddef: tdef;
  484. rttisym: TAsmSymbol;
  485. rttidef: tdef;
  486. rttiref: treference;
  487. wrappedexception,
  488. exceptiontypeidreg,
  489. landingpadres: tregister;
  490. exceptloc: tlocation;
  491. indirect: boolean;
  492. otherunit: boolean;
  493. typeindex : aint;
  494. begin
  495. paraloc1.init;
  496. rttidef:=nil;
  497. rttisym:=nil;
  498. if add_catch then
  499. begin
  500. if assigned(excepttype) then
  501. begin
  502. otherunit:=findunitsymtable(excepttype.owner).moduleid<>findunitsymtable(current_procinfo.procdef.owner).moduleid;
  503. indirect:=(tf_supports_packages in target_info.flags) and
  504. (target_info.system in systems_indirect_var_imports) and
  505. (cs_imported_data in current_settings.localswitches) and
  506. otherunit;
  507. { add "catch exceptiontype" clause to the landing pad }
  508. rttidef:=cpointerdef.getreusable(excepttype.vmt_def);
  509. rttisym:=current_asmdata.RefAsmSymbol(excepttype.vmt_mangledname, AT_DATA, indirect);
  510. end;
  511. end;
  512. { check if the exception is handled by this node }
  513. if assigned(excepttype) then
  514. begin
  515. typeindex:=(current_procinfo as tpsabiehprocinfo).CurrentAction.AddAction(excepttype);
  516. current_asmdata.getjumplabel(catchstartlab);
  517. {$ifdef i386}
  518. hlcg.a_cmp_const_reg_label (list,osuinttype,OC_EQ,typeindex+1,NR_FUNCTION_RESULT64_HIGH_REG,catchstartlab);
  519. {$else i386}
  520. { we need to find a way to fix this in a generic way }
  521. Internalerror(2019021008);
  522. {$endif i386}
  523. hlcg.a_jmp_always(list,nextonlabel);
  524. hlcg.a_label(list,catchstartlab);
  525. end
  526. else
  527. (current_procinfo as tpsabiehprocinfo).CurrentAction.AddAction(tobjectdef(-1));
  528. wrappedexception:=hlcg.getaddressregister(list,voidpointertype);
  529. pd:=search_system_proc('fpc_psabi_begin_catch');
  530. paramanager.getintparaloc(list, pd, 1, paraloc1);
  531. hlcg.a_load_reg_cgpara(list,voidpointertype,wrappedexception,paraloc1);
  532. begincatchres:=hlcg.g_call_system_proc(list,pd,[@paraloc1],nil);
  533. location_reset(exceptloc, LOC_REGISTER, def_cgsize(begincatchres.def));
  534. exceptloc.register:=hlcg.getaddressregister(list, begincatchres.def);
  535. hlcg.gen_load_cgpara_loc(list, begincatchres.def, begincatchres, exceptloc, true);
  536. begincatchres.resetiftemp;
  537. paraloc1.done;
  538. exceptlocdef:=begincatchres.def;
  539. exceptlocreg:=exceptloc.register;
  540. end;
  541. class procedure tpsabiehexceptionstatehandler.catch_all_start_internal(list: TAsmList; add_catch: boolean);
  542. var
  543. exceptlocdef: tdef;
  544. exceptlocreg: tregister;
  545. begin
  546. begin_catch_internal(list,nil,nil,add_catch,exceptlocdef,exceptlocreg);
  547. end;
  548. class procedure tpsabiehexceptionstatehandler.begin_catch(list: TAsmList; excepttype: tobjectdef; nextonlabel: tasmlabel; out exceptlocdef: tdef; out
  549. exceptlocreg: tregister);
  550. begin
  551. begin_catch_internal(list,excepttype,nextonlabel,true,exceptlocdef,exceptlocreg);
  552. end;
  553. class procedure tpsabiehexceptionstatehandler.end_catch(list: TAsmList);
  554. begin
  555. hlcg.g_call_system_proc(list,'fpc_psabi_end_catch',[],nil).resetiftemp;
  556. inherited;
  557. end;
  558. class procedure tpsabiehexceptionstatehandler.catch_all_start(list: TAsmList);
  559. begin
  560. catch_all_start_internal(list,true);
  561. end;
  562. class procedure tpsabiehexceptionstatehandler.catch_all_end(list: TAsmList);
  563. begin
  564. hlcg.g_call_system_proc(list,'fpc_psabi_end_catch',[],nil).resetiftemp;
  565. end;
  566. class procedure tpsabiehexceptionstatehandler.cleanupobjectstack(list: TAsmList);
  567. begin
  568. // inherited cleanupobjectstack(list);
  569. //!!! some catch all clause needed?
  570. //!!! internalerror(2019021004)
  571. end;
  572. class procedure tpsabiehexceptionstatehandler.popaddrstack(list: TAsmList);
  573. begin
  574. { there is no addr stack, so do nothing }
  575. end;
  576. end.