psabiehpi.pas 31 KB

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