psabiehpi.pas 32 KB

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