ncgutil.pas 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Helper routines for all code generators
  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 ncgutil;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,
  22. globtype,
  23. cpubase,cgbase,parabase,cgutils,
  24. aasmbase,aasmtai,aasmdata,aasmcpu,
  25. symconst,symbase,symdef,symsym,symtype
  26. {$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}
  27. ,cg64f32
  28. {$endif not cpu64bitalu and not cpuhighleveltarget}
  29. ;
  30. type
  31. tloadregvars = (lr_dont_load_regvars, lr_load_regvars);
  32. pusedregvars = ^tusedregvars;
  33. tusedregvars = record
  34. intregvars, addrregvars, fpuregvars, mmregvars: Tsuperregisterworklist;
  35. end;
  36. {
  37. Not used currently, implemented because I thought we had to
  38. synchronise around if/then/else as well, but not needed. May
  39. still be useful for SSA once we get around to implementing
  40. that (JM)
  41. pusedregvarscommon = ^tusedregvarscommon;
  42. tusedregvarscommon = record
  43. allregvars, commonregvars, myregvars: tusedregvars;
  44. end;
  45. }
  46. procedure firstcomplex(p : tbinarynode);
  47. procedure maketojumpboollabels(list: TAsmList; p: tnode; truelabel, falselabel: tasmlabel);
  48. // procedure remove_non_regvars_from_loc(const t: tlocation; var regs:Tsuperregisterset);
  49. procedure location_force_mmreg(list:TAsmList;var l: tlocation;maybeconst:boolean);
  50. procedure location_allocate_register(list:TAsmList;out l: tlocation;def: tdef;constant: boolean);
  51. { allocate registers for a tlocation; assumes that loc.loc is already
  52. set to LOC_CREGISTER/LOC_CFPUREGISTER/... }
  53. procedure gen_alloc_regloc(list:TAsmList;var loc: tlocation;def: tdef);
  54. procedure register_maybe_adjust_setbase(list: TAsmList; opdef: tdef; var l: tlocation; setbase: aint);
  55. procedure alloc_proc_symbol(pd: tprocdef);
  56. procedure release_proc_symbol(pd:tprocdef);
  57. procedure gen_proc_entry_code(list:TAsmList);
  58. procedure gen_proc_exit_code(list:TAsmList);
  59. procedure gen_save_used_regs(list:TAsmList);
  60. procedure gen_restore_used_regs(list:TAsmList);
  61. procedure get_used_regvars(n: tnode; var rv: tusedregvars);
  62. { adds the regvars used in n and its children to rv.allregvars,
  63. those which were already in rv.allregvars to rv.commonregvars and
  64. uses rv.myregvars as scratch (so that two uses of the same regvar
  65. in a single tree to make it appear in commonregvars). Useful to
  66. find out which regvars are used in two different node trees
  67. e.g. in the "else" and "then" path, or in various case blocks }
  68. // procedure get_used_regvars_common(n: tnode; var rv: tusedregvarscommon);
  69. procedure gen_sync_regvars(list:TAsmList; var rv: tusedregvars);
  70. procedure gen_alloc_symtable(list:TAsmList;pd:tprocdef;st:TSymtable);
  71. procedure gen_free_symtable(list:TAsmList;st:TSymtable);
  72. procedure location_free(list: TAsmList; const location : TLocation);
  73. function getprocalign : shortint;
  74. procedure gen_load_frame_for_exceptfilter(list : TAsmList);
  75. procedure gen_alloc_regvar(list:TAsmList;sym: tabstractnormalvarsym; allocreg: boolean);
  76. implementation
  77. uses
  78. cutils,cclasses,
  79. globals,systems,verbose,
  80. defutil,
  81. procinfo,paramgr,
  82. dbgbase,
  83. nbas,ncon,nld,nmem,nutils,
  84. tgobj,cgobj,hlcgobj,hlcgcpu
  85. {$ifdef llvm}
  86. { override create_hlcodegen from hlcgcpu }
  87. , hlcgllvm
  88. {$endif}
  89. {$ifdef powerpc}
  90. , cpupi
  91. {$endif}
  92. {$ifdef powerpc64}
  93. , cpupi
  94. {$endif}
  95. {$ifdef SUPPORT_MMX}
  96. , cgx86
  97. {$endif SUPPORT_MMX}
  98. ;
  99. {*****************************************************************************
  100. Misc Helpers
  101. *****************************************************************************}
  102. {$if first_mm_imreg = 0}
  103. {$WARN 4044 OFF} { Comparison might be always false ... }
  104. {$endif}
  105. procedure location_free(list: TAsmList; const location : TLocation);
  106. begin
  107. case location.loc of
  108. LOC_VOID:
  109. ;
  110. LOC_REGISTER,
  111. LOC_CREGISTER:
  112. begin
  113. {$if defined(cpu64bitalu)}
  114. { x86-64 system v abi:
  115. structs with up to 16 bytes are returned in registers }
  116. if location.size in [OS_128,OS_S128] then
  117. begin
  118. if getsupreg(location.register)<first_int_imreg then
  119. cg.ungetcpuregister(list,location.register);
  120. if getsupreg(location.registerhi)<first_int_imreg then
  121. cg.ungetcpuregister(list,location.registerhi);
  122. end
  123. else
  124. {$elseif not defined(cpuhighleveltarget)}
  125. if location.size in [OS_64,OS_S64] then
  126. begin
  127. if getsupreg(location.register64.reglo)<first_int_imreg then
  128. cg.ungetcpuregister(list,location.register64.reglo);
  129. if getsupreg(location.register64.reghi)<first_int_imreg then
  130. cg.ungetcpuregister(list,location.register64.reghi);
  131. end
  132. else
  133. {$endif cpu64bitalu and not cpuhighleveltarget}
  134. if getsupreg(location.register)<first_int_imreg then
  135. cg.ungetcpuregister(list,location.register);
  136. end;
  137. LOC_FPUREGISTER,
  138. LOC_CFPUREGISTER:
  139. begin
  140. if getsupreg(location.register)<first_fpu_imreg then
  141. cg.ungetcpuregister(list,location.register);
  142. end;
  143. LOC_MMREGISTER,
  144. LOC_CMMREGISTER :
  145. begin
  146. if getsupreg(location.register)<first_mm_imreg then
  147. cg.ungetcpuregister(list,location.register);
  148. end;
  149. LOC_REFERENCE,
  150. LOC_CREFERENCE :
  151. begin
  152. if paramanager.use_fixed_stack then
  153. location_freetemp(list,location);
  154. end;
  155. else
  156. internalerror(2004110211);
  157. end;
  158. end;
  159. procedure firstcomplex(p : tbinarynode);
  160. var
  161. fcl, fcr: longint;
  162. ncl, ncr: longint;
  163. begin
  164. { always calculate boolean AND and OR from left to right }
  165. if (p.nodetype in [orn,andn]) and
  166. is_boolean(p.left.resultdef) then
  167. begin
  168. if nf_swapped in p.flags then
  169. internalerror(200709253);
  170. end
  171. else
  172. begin
  173. fcl:=node_resources_fpu(p.left);
  174. fcr:=node_resources_fpu(p.right);
  175. ncl:=node_complexity(p.left);
  176. ncr:=node_complexity(p.right);
  177. { We swap left and right if
  178. a) right needs more floating point registers than left, and
  179. left needs more than 0 floating point registers (if it
  180. doesn't need any, swapping won't change the floating
  181. point register pressure)
  182. b) both left and right need an equal amount of floating
  183. point registers or right needs no floating point registers,
  184. and in addition right has a higher complexity than left
  185. (+- needs more integer registers, but not necessarily)
  186. }
  187. if ((fcr>fcl) and
  188. (fcl>0)) or
  189. (((fcr=fcl) or
  190. (fcr=0)) and
  191. (ncr>ncl)) and
  192. { if one tree contains nodes being conditionally executated, we cannot swap the trees
  193. as the other tree might depend on all nodes being executed, this applies for example
  194. for temp. create nodes with init part, they must be executed else things break, see
  195. issue #34653
  196. }
  197. not(has_conditional_nodes(p.right)) then
  198. p.swapleftright
  199. end;
  200. end;
  201. procedure maketojumpboollabels(list: TAsmList; p: tnode; truelabel, falselabel: tasmlabel);
  202. {
  203. produces jumps to true respectively false labels using boolean expressions
  204. }
  205. var
  206. opsize : tcgsize;
  207. storepos : tfileposinfo;
  208. tmpreg : tregister;
  209. begin
  210. if nf_error in p.flags then
  211. exit;
  212. storepos:=current_filepos;
  213. current_filepos:=p.fileinfo;
  214. if is_boolean(p.resultdef) then
  215. begin
  216. if is_constboolnode(p) then
  217. begin
  218. if Tordconstnode(p).value.uvalue<>0 then
  219. cg.a_jmp_always(list,truelabel)
  220. else
  221. cg.a_jmp_always(list,falselabel)
  222. end
  223. else
  224. begin
  225. opsize:=def_cgsize(p.resultdef);
  226. case p.location.loc of
  227. LOC_SUBSETREG,LOC_CSUBSETREG:
  228. begin
  229. if p.location.sreg.bitlen=1 then
  230. begin
  231. tmpreg:=cg.getintregister(list,p.location.sreg.subsetregsize);
  232. hlcg.a_op_const_reg_reg(list,OP_AND,cgsize_orddef(p.location.sreg.subsetregsize),1 shl p.location.sreg.startbit,p.location.sreg.subsetreg,tmpreg);
  233. end
  234. else
  235. begin
  236. tmpreg:=cg.getintregister(list,OS_INT);
  237. hlcg.a_load_loc_reg(list,p.resultdef,osuinttype,p.location,tmpreg);
  238. end;
  239. cg.a_cmp_const_reg_label(list,OS_INT,OC_NE,0,tmpreg,truelabel);
  240. cg.a_jmp_always(list,falselabel);
  241. end;
  242. LOC_SUBSETREF,LOC_CSUBSETREF:
  243. begin
  244. if (p.location.sref.bitindexreg=NR_NO) and (p.location.sref.bitlen=1) then
  245. begin
  246. tmpreg:=cg.getintregister(list,OS_INT);
  247. hlcg.a_load_ref_reg(list,u8inttype,osuinttype,p.location.sref.ref,tmpreg);
  248. if target_info.endian=endian_big then
  249. hlcg.a_op_const_reg_reg(list,OP_AND,osuinttype,1 shl (8-(p.location.sref.startbit+1)),tmpreg,tmpreg)
  250. else
  251. hlcg.a_op_const_reg_reg(list,OP_AND,osuinttype,1 shl p.location.sref.startbit,tmpreg,tmpreg);
  252. end
  253. else
  254. begin
  255. tmpreg:=cg.getintregister(list,OS_INT);
  256. hlcg.a_load_loc_reg(list,p.resultdef,osuinttype,p.location,tmpreg);
  257. end;
  258. cg.a_cmp_const_reg_label(list,OS_INT,OC_NE,0,tmpreg,truelabel);
  259. cg.a_jmp_always(list,falselabel);
  260. end;
  261. LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
  262. begin
  263. {$if defined(cpu64bitalu)}
  264. if opsize in [OS_128,OS_S128] then
  265. begin
  266. hlcg.location_force_reg(list,p.location,p.resultdef,cgsize_orddef(opsize),true);
  267. tmpreg:=cg.getintregister(list,OS_64);
  268. cg.a_op_reg_reg_reg(list,OP_OR,OS_64,p.location.register128.reglo,p.location.register128.reghi,tmpreg);
  269. location_reset(p.location,LOC_REGISTER,OS_64);
  270. p.location.register:=tmpreg;
  271. opsize:=OS_64;
  272. end;
  273. {$elseif not defined(cpuhighleveltarget)}
  274. if opsize in [OS_64,OS_S64] then
  275. begin
  276. hlcg.location_force_reg(list,p.location,p.resultdef,cgsize_orddef(opsize),true);
  277. tmpreg:=cg.getintregister(list,OS_32);
  278. cg.a_op_reg_reg_reg(list,OP_OR,OS_32,p.location.register64.reglo,p.location.register64.reghi,tmpreg);
  279. location_reset(p.location,LOC_REGISTER,OS_32);
  280. p.location.register:=tmpreg;
  281. opsize:=OS_32;
  282. end;
  283. {$endif cpu64bitalu and not cpuhighleveltarget}
  284. cg.a_cmp_const_loc_label(list,opsize,OC_NE,0,p.location,truelabel);
  285. cg.a_jmp_always(list,falselabel);
  286. end;
  287. LOC_JUMP:
  288. begin
  289. if truelabel<>p.location.truelabel then
  290. begin
  291. cg.a_label(list,p.location.truelabel);
  292. cg.a_jmp_always(list,truelabel);
  293. end;
  294. if falselabel<>p.location.falselabel then
  295. begin
  296. cg.a_label(list,p.location.falselabel);
  297. cg.a_jmp_always(list,falselabel);
  298. end;
  299. end;
  300. {$ifdef cpuflags}
  301. LOC_FLAGS :
  302. begin
  303. cg.a_jmp_flags(list,p.location.resflags,truelabel);
  304. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  305. cg.a_jmp_always(list,falselabel);
  306. end;
  307. {$endif cpuflags}
  308. else
  309. begin
  310. printnode(output,p);
  311. internalerror(200308241);
  312. end;
  313. end;
  314. end;
  315. location_reset_jump(p.location,truelabel,falselabel);
  316. end
  317. else
  318. internalerror(200112305);
  319. current_filepos:=storepos;
  320. end;
  321. (*
  322. This code needs fixing. It is not safe to use rgint; on the m68000 it
  323. would be rgaddr.
  324. procedure remove_non_regvars_from_loc(const t: tlocation; var regs:Tsuperregisterset);
  325. begin
  326. case t.loc of
  327. LOC_REGISTER:
  328. begin
  329. { can't be a regvar, since it would be LOC_CREGISTER then }
  330. exclude(regs,getsupreg(t.register));
  331. if t.register64.reghi<>NR_NO then
  332. exclude(regs,getsupreg(t.register64.reghi));
  333. end;
  334. LOC_CREFERENCE,LOC_REFERENCE:
  335. begin
  336. if not(cs_opt_regvar in current_settings.optimizerswitches) or
  337. (getsupreg(t.reference.base) in cg.rgint.usableregs) then
  338. exclude(regs,getsupreg(t.reference.base));
  339. if not(cs_opt_regvar in current_settings.optimizerswitches) or
  340. (getsupreg(t.reference.index) in cg.rgint.usableregs) then
  341. exclude(regs,getsupreg(t.reference.index));
  342. end;
  343. end;
  344. end;
  345. *)
  346. {*****************************************************************************
  347. TLocation
  348. *****************************************************************************}
  349. procedure register_maybe_adjust_setbase(list: TAsmList; opdef: tdef; var l: tlocation; setbase: aint);
  350. var
  351. tmpreg: tregister;
  352. begin
  353. if (setbase<>0) then
  354. begin
  355. { subtract the setbase }
  356. case l.loc of
  357. LOC_CREGISTER:
  358. begin
  359. tmpreg := hlcg.getintregister(list,opdef);
  360. hlcg.a_op_const_reg_reg(list,OP_SUB,opdef,setbase,l.register,tmpreg);
  361. l.loc:=LOC_REGISTER;
  362. l.register:=tmpreg;
  363. end;
  364. LOC_REGISTER:
  365. begin
  366. hlcg.a_op_const_reg(list,OP_SUB,opdef,setbase,l.register);
  367. end;
  368. else
  369. internalerror(2007091502);
  370. end;
  371. end;
  372. end;
  373. procedure location_force_mmreg(list:TAsmList;var l: tlocation;maybeconst:boolean);
  374. var
  375. reg : tregister;
  376. begin
  377. if (l.loc<>LOC_MMREGISTER) and
  378. ((l.loc<>LOC_CMMREGISTER) or (not maybeconst)) then
  379. begin
  380. reg:=cg.getmmregister(list,OS_VECTOR);
  381. cg.a_loadmm_loc_reg(list,OS_VECTOR,l,reg,nil);
  382. location_freetemp(list,l);
  383. location_reset(l,LOC_MMREGISTER,OS_VECTOR);
  384. l.register:=reg;
  385. end;
  386. end;
  387. procedure location_allocate_register(list: TAsmList;out l: tlocation;def: tdef;constant: boolean);
  388. begin
  389. l.size:=def_cgsize(def);
  390. if (def.typ=floatdef) and
  391. not(cs_fp_emulation in current_settings.moduleswitches) then
  392. begin
  393. if use_vectorfpu(def) then
  394. begin
  395. if constant then
  396. location_reset(l,LOC_CMMREGISTER,l.size)
  397. else
  398. location_reset(l,LOC_MMREGISTER,l.size);
  399. l.register:=cg.getmmregister(list,l.size);
  400. end
  401. else
  402. begin
  403. if constant then
  404. location_reset(l,LOC_CFPUREGISTER,l.size)
  405. else
  406. location_reset(l,LOC_FPUREGISTER,l.size);
  407. l.register:=cg.getfpuregister(list,l.size);
  408. end;
  409. end
  410. else
  411. begin
  412. if constant then
  413. location_reset(l,LOC_CREGISTER,l.size)
  414. else
  415. location_reset(l,LOC_REGISTER,l.size);
  416. {$if defined(cpu64bitalu)}
  417. if l.size in [OS_128,OS_S128,OS_F128] then
  418. begin
  419. l.register128.reglo:=cg.getintregister(list,OS_64);
  420. l.register128.reghi:=cg.getintregister(list,OS_64);
  421. end
  422. else
  423. {$elseif not defined(cpuhighleveltarget)}
  424. if l.size in [OS_64,OS_S64,OS_F64] then
  425. begin
  426. l.register64.reglo:=cg.getintregister(list,OS_32);
  427. l.register64.reghi:=cg.getintregister(list,OS_32);
  428. end
  429. else
  430. {$endif cpu64bitalu and not cpuhighleveltarget}
  431. { Note: for widths of records (and maybe objects, classes, etc.) an
  432. address register could be set here, but that is later
  433. changed to an intregister neverthless when in the
  434. tcgassignmentnode thlcgobj.maybe_change_load_node_reg is
  435. called for the temporary node; so the workaround for now is
  436. to fix the symptoms... }
  437. l.register:=hlcg.getregisterfordef(list,def);
  438. end;
  439. end;
  440. {****************************************************************************
  441. Init/Finalize Code
  442. ****************************************************************************}
  443. { generates the code for incrementing the reference count of parameters and
  444. initialize out parameters }
  445. procedure init_paras(p:TObject;arg:pointer);
  446. var
  447. href : treference;
  448. hsym : tparavarsym;
  449. eldef : tdef;
  450. list : TAsmList;
  451. needs_inittable : boolean;
  452. begin
  453. list:=TAsmList(arg);
  454. if (tsym(p).typ=paravarsym) then
  455. begin
  456. needs_inittable:=is_managed_type(tparavarsym(p).vardef);
  457. if not needs_inittable then
  458. exit;
  459. case tparavarsym(p).varspez of
  460. vs_value :
  461. begin
  462. { variants are already handled by the call to fpc_variant_copy_overwrite if
  463. they are passed by reference }
  464. if not((tparavarsym(p).vardef.typ=variantdef) and
  465. paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
  466. begin
  467. hlcg.location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,
  468. is_open_array(tparavarsym(p).vardef) or
  469. ((target_info.system in systems_caller_copy_addr_value_para) and
  470. paramanager.push_addr_param(vs_value,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)),
  471. sizeof(pint));
  472. if is_open_array(tparavarsym(p).vardef) then
  473. begin
  474. { open arrays do not contain correct element count in their rtti,
  475. the actual count must be passed separately. }
  476. hsym:=tparavarsym(get_high_value_sym(tparavarsym(p)));
  477. eldef:=tarraydef(tparavarsym(p).vardef).elementdef;
  478. if not assigned(hsym) then
  479. internalerror(201003031);
  480. hlcg.g_array_rtti_helper(list,eldef,href,hsym.initialloc,'fpc_addref_array');
  481. end
  482. else
  483. hlcg.g_incrrefcount(list,tparavarsym(p).vardef,href);
  484. end;
  485. end;
  486. vs_out :
  487. begin
  488. { we have no idea about the alignment at the callee side,
  489. and the user also cannot specify "unaligned" here, so
  490. assume worst case }
  491. hlcg.location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,true,1);
  492. if is_open_array(tparavarsym(p).vardef) then
  493. begin
  494. hsym:=tparavarsym(get_high_value_sym(tparavarsym(p)));
  495. eldef:=tarraydef(tparavarsym(p).vardef).elementdef;
  496. if not assigned(hsym) then
  497. internalerror(201103033);
  498. hlcg.g_array_rtti_helper(list,eldef,href,hsym.initialloc,'fpc_initialize_array');
  499. end
  500. else
  501. hlcg.g_initialize(list,tparavarsym(p).vardef,href);
  502. end;
  503. else
  504. ;
  505. end;
  506. end;
  507. end;
  508. procedure gen_alloc_regloc(list:TAsmList;var loc: tlocation;def: tdef);
  509. begin
  510. case loc.loc of
  511. LOC_CREGISTER:
  512. begin
  513. {$if defined(cpu64bitalu)}
  514. if loc.size in [OS_128,OS_S128] then
  515. begin
  516. loc.register128.reglo:=cg.getintregister(list,OS_64);
  517. loc.register128.reghi:=cg.getintregister(list,OS_64);
  518. end
  519. else
  520. {$elseif not defined(cpuhighleveltarget)}
  521. if loc.size in [OS_64,OS_S64] then
  522. begin
  523. loc.register64.reglo:=cg.getintregister(list,OS_32);
  524. loc.register64.reghi:=cg.getintregister(list,OS_32);
  525. end
  526. else
  527. {$endif cpu64bitalu and not cpuhighleveltarget}
  528. if hlcg.def2regtyp(def)=R_ADDRESSREGISTER then
  529. loc.register:=hlcg.getaddressregister(list,def)
  530. else
  531. loc.register:=cg.getintregister(list,loc.size);
  532. end;
  533. LOC_CFPUREGISTER:
  534. begin
  535. loc.register:=cg.getfpuregister(list,loc.size);
  536. end;
  537. LOC_CMMREGISTER:
  538. begin
  539. loc.register:=cg.getmmregister(list,loc.size);
  540. end;
  541. else
  542. ;
  543. end;
  544. end;
  545. procedure gen_alloc_regvar(list:TAsmList;sym: tabstractnormalvarsym; allocreg: boolean);
  546. var
  547. usedef: tdef;
  548. varloc: tai_varloc;
  549. begin
  550. if allocreg then
  551. begin
  552. if sym.typ=paravarsym then
  553. usedef:=tparavarsym(sym).paraloc[calleeside].def
  554. else
  555. usedef:=sym.vardef;
  556. gen_alloc_regloc(list,sym.initialloc,usedef);
  557. end;
  558. if (pi_has_label in current_procinfo.flags) then
  559. begin
  560. { Allocate register already, to prevent first allocation to be
  561. inside a loop }
  562. {$if defined(cpu64bitalu)}
  563. if sym.initialloc.size in [OS_128,OS_S128] then
  564. begin
  565. cg.a_reg_sync(list,sym.initialloc.register128.reglo);
  566. cg.a_reg_sync(list,sym.initialloc.register128.reghi);
  567. end
  568. else
  569. {$elseif defined(cpu32bitalu) and not defined(cpuhighleveltarget)}
  570. if sym.initialloc.size in [OS_64,OS_S64] then
  571. begin
  572. cg.a_reg_sync(list,sym.initialloc.register64.reglo);
  573. cg.a_reg_sync(list,sym.initialloc.register64.reghi);
  574. end
  575. else
  576. {$elseif defined(cpu16bitalu) and not defined(cpuhighleveltarget)}
  577. if sym.initialloc.size in [OS_64,OS_S64] then
  578. begin
  579. cg.a_reg_sync(list,sym.initialloc.register64.reglo);
  580. cg.a_reg_sync(list,cg.GetNextReg(sym.initialloc.register64.reglo));
  581. cg.a_reg_sync(list,sym.initialloc.register64.reghi);
  582. cg.a_reg_sync(list,cg.GetNextReg(sym.initialloc.register64.reghi));
  583. end
  584. else
  585. if sym.initialloc.size in [OS_32,OS_S32] then
  586. begin
  587. cg.a_reg_sync(list,sym.initialloc.register);
  588. cg.a_reg_sync(list,cg.GetNextReg(sym.initialloc.register));
  589. end
  590. else
  591. {$elseif defined(cpu8bitalu) and not defined(cpuhighleveltarget)}
  592. if sym.initialloc.size in [OS_64,OS_S64] then
  593. begin
  594. cg.a_reg_sync(list,sym.initialloc.register64.reglo);
  595. cg.a_reg_sync(list,cg.GetNextReg(sym.initialloc.register64.reglo));
  596. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(sym.initialloc.register64.reglo)));
  597. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(sym.initialloc.register64.reglo))));
  598. cg.a_reg_sync(list,sym.initialloc.register64.reghi);
  599. cg.a_reg_sync(list,cg.GetNextReg(sym.initialloc.register64.reghi));
  600. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(sym.initialloc.register64.reghi)));
  601. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(sym.initialloc.register64.reghi))));
  602. end
  603. else
  604. if sym.initialloc.size in [OS_32,OS_S32] then
  605. begin
  606. cg.a_reg_sync(list,sym.initialloc.register);
  607. cg.a_reg_sync(list,cg.GetNextReg(sym.initialloc.register));
  608. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(sym.initialloc.register)));
  609. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(sym.initialloc.register))));
  610. end
  611. else
  612. if sym.initialloc.size in [OS_16,OS_S16] then
  613. begin
  614. cg.a_reg_sync(list,sym.initialloc.register);
  615. cg.a_reg_sync(list,cg.GetNextReg(sym.initialloc.register));
  616. end
  617. else
  618. {$endif}
  619. cg.a_reg_sync(list,sym.initialloc.register);
  620. end;
  621. {$if defined(cpu64bitalu)}
  622. if (sym.initialloc.size in [OS_128,OS_S128]) then
  623. varloc:=tai_varloc.create128(sym,sym.initialloc.register,sym.initialloc.registerhi)
  624. else
  625. {$elseif not defined(cpuhighleveltarget)}
  626. if (sym.initialloc.size in [OS_64,OS_S64]) then
  627. varloc:=tai_varloc.create64(sym,sym.initialloc.register,sym.initialloc.registerhi)
  628. else
  629. {$endif cpu64bitalu and not cpuhighleveltarget}
  630. varloc:=tai_varloc.create(sym,sym.initialloc.register);
  631. list.concat(varloc);
  632. end;
  633. {****************************************************************************
  634. Entry/Exit
  635. ****************************************************************************}
  636. procedure alloc_proc_symbol(pd: tprocdef);
  637. var
  638. item : TCmdStrListItem;
  639. begin
  640. item := TCmdStrListItem(pd.aliasnames.first);
  641. while assigned(item) do
  642. begin
  643. { The condition to use global or local symbol must match
  644. the code written in hlcg.gen_proc_symbol to
  645. avoid change from AB_LOCAL to AB_GLOBAL, which generates
  646. erroneous code (at least for targets using GOT) }
  647. if (cs_profile in current_settings.moduleswitches) or
  648. (po_global in current_procinfo.procdef.procoptions) then
  649. current_asmdata.DefineAsmSymbol(item.str,AB_GLOBAL,AT_FUNCTION,pd)
  650. else
  651. current_asmdata.DefineAsmSymbol(item.str,AB_LOCAL,AT_FUNCTION,pd);
  652. item := TCmdStrListItem(item.next);
  653. end;
  654. end;
  655. procedure release_proc_symbol(pd:tprocdef);
  656. var
  657. idx : longint;
  658. item : TCmdStrListItem;
  659. begin
  660. item:=TCmdStrListItem(pd.aliasnames.first);
  661. while assigned(item) do
  662. begin
  663. idx:=current_asmdata.AsmSymbolDict.findindexof(item.str);
  664. if idx>=0 then
  665. current_asmdata.AsmSymbolDict.Delete(idx);
  666. item:=TCmdStrListItem(item.next);
  667. end;
  668. end;
  669. procedure gen_proc_entry_code(list:TAsmList);
  670. var
  671. hitemp,
  672. lotemp, stack_frame_size : longint;
  673. begin
  674. { generate call frame marker for dwarf call frame info }
  675. current_asmdata.asmcfi.start_frame(list);
  676. { All temps are know, write offsets used for information }
  677. if (cs_asm_source in current_settings.globalswitches) and
  678. (current_procinfo.tempstart<>tg.lasttemp) then
  679. begin
  680. if tg.direction>0 then
  681. begin
  682. lotemp:=current_procinfo.tempstart;
  683. hitemp:=tg.lasttemp;
  684. end
  685. else
  686. begin
  687. lotemp:=tg.lasttemp;
  688. hitemp:=current_procinfo.tempstart;
  689. end;
  690. list.concat(Tai_comment.Create(strpnew('Temps allocated between '+std_regname(current_procinfo.framepointer)+
  691. tostr_with_plus(lotemp)+' and '+std_regname(current_procinfo.framepointer)+tostr_with_plus(hitemp))));
  692. end;
  693. { generate target specific proc entry code }
  694. stack_frame_size := current_procinfo.calc_stackframe_size;
  695. if (stack_frame_size <> 0) and
  696. (po_nostackframe in current_procinfo.procdef.procoptions) then
  697. message1(parser_e_nostackframe_with_locals,tostr(stack_frame_size));
  698. hlcg.g_proc_entry(list,stack_frame_size,(po_nostackframe in current_procinfo.procdef.procoptions));
  699. end;
  700. procedure gen_proc_exit_code(list:TAsmList);
  701. var
  702. parasize : longint;
  703. begin
  704. { c style clearstack does not need to remove parameters from the stack, only the
  705. return value when it was pushed by arguments }
  706. if current_procinfo.procdef.proccalloption in clearstack_pocalls then
  707. begin
  708. parasize:=0;
  709. { For safecall functions with safecall-exceptions enabled the funcret is always returned as a para
  710. which is considered a normal para on the c-side, so the funcret has to be pop'ed normally. }
  711. if not ( (current_procinfo.procdef.proccalloption=pocall_safecall) and
  712. (tf_safecall_exceptions in target_info.flags) ) and
  713. paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef) then
  714. inc(parasize,sizeof(pint));
  715. end
  716. else
  717. begin
  718. parasize:=current_procinfo.para_stack_size;
  719. { the parent frame pointer para has to be removed by the caller in
  720. case of Delphi-style parent frame pointer passing }
  721. if not paramanager.use_fixed_stack and
  722. (po_delphi_nested_cc in current_procinfo.procdef.procoptions) then
  723. dec(parasize,sizeof(pint));
  724. end;
  725. { generate target specific proc exit code }
  726. hlcg.g_proc_exit(list,parasize,(po_nostackframe in current_procinfo.procdef.procoptions));
  727. { release return registers, needed for optimizer }
  728. if not is_void(current_procinfo.procdef.returndef) then
  729. paramanager.freecgpara(list,current_procinfo.procdef.funcretloc[calleeside]);
  730. { end of frame marker for call frame info }
  731. current_asmdata.asmcfi.end_frame(list);
  732. end;
  733. procedure gen_save_used_regs(list:TAsmList);
  734. begin
  735. { Pure assembler routines need to save the registers themselves }
  736. if (po_assembler in current_procinfo.procdef.procoptions) then
  737. exit;
  738. cg.g_save_registers(list);
  739. end;
  740. procedure gen_restore_used_regs(list:TAsmList);
  741. begin
  742. { Pure assembler routines need to save the registers themselves }
  743. if (po_assembler in current_procinfo.procdef.procoptions) then
  744. exit;
  745. cg.g_restore_registers(list);
  746. end;
  747. {****************************************************************************
  748. Const Data
  749. ****************************************************************************}
  750. procedure gen_alloc_symtable(list:TAsmList;pd:tprocdef;st:TSymtable);
  751. var
  752. i : longint;
  753. highsym,
  754. sym : tsym;
  755. vs : tabstractnormalvarsym;
  756. ptrdef : tdef;
  757. isaddr : boolean;
  758. begin
  759. for i:=0 to st.SymList.Count-1 do
  760. begin
  761. sym:=tsym(st.SymList[i]);
  762. case sym.typ of
  763. staticvarsym :
  764. begin
  765. vs:=tabstractnormalvarsym(sym);
  766. { The code in loadnode.pass_generatecode will create the
  767. LOC_REFERENCE instead for all none register variables. This is
  768. required because we can't store an asmsymbol in the localloc because
  769. the asmsymbol is invalid after an unit is compiled. This gives
  770. problems when this procedure is inlined in another unit (PFV) }
  771. if vs.is_regvar(false) then
  772. begin
  773. vs.initialloc.loc:=tvarregable2tcgloc[vs.varregable];
  774. vs.initialloc.size:=def_cgsize(vs.vardef);
  775. gen_alloc_regvar(list,vs,true);
  776. hlcg.varsym_set_localloc(list,vs);
  777. end;
  778. end;
  779. paravarsym :
  780. begin
  781. vs:=tabstractnormalvarsym(sym);
  782. { Parameters passed to assembler procedures need to be kept
  783. in the original location }
  784. if (po_assembler in pd.procoptions) then
  785. tparavarsym(vs).paraloc[calleeside].get_location(vs.initialloc)
  786. { exception filters receive their frame pointer as a parameter }
  787. else if (pd.proctypeoption=potype_exceptfilter) and
  788. (vo_is_parentfp in vs.varoptions) then
  789. begin
  790. location_reset(vs.initialloc,LOC_REGISTER,OS_ADDR);
  791. vs.initialloc.register:=NR_FRAME_POINTER_REG;
  792. end
  793. else
  794. begin
  795. { if an open array is used, also its high parameter is used,
  796. since the hidden high parameters are inserted after the corresponding symbols,
  797. we can increase the ref. count here }
  798. if is_open_array(vs.vardef) or is_array_of_const(vs.vardef) then
  799. begin
  800. highsym:=get_high_value_sym(tparavarsym(vs));
  801. if assigned(highsym) then
  802. inc(highsym.refs);
  803. end;
  804. isaddr:=paramanager.push_addr_param(vs.varspez,vs.vardef,pd.proccalloption);
  805. if isaddr then
  806. vs.initialloc.size:=def_cgsize(voidpointertype)
  807. else
  808. vs.initialloc.size:=def_cgsize(vs.vardef);
  809. if vs.is_regvar(isaddr) then
  810. vs.initialloc.loc:=tvarregable2tcgloc[vs.varregable]
  811. else
  812. begin
  813. vs.initialloc.loc:=LOC_REFERENCE;
  814. { Reuse the parameter location for values to are at a single location on the stack }
  815. if paramanager.param_use_paraloc(tparavarsym(vs).paraloc[calleeside]) then
  816. begin
  817. hlcg.paravarsym_set_initialloc_to_paraloc(tparavarsym(vs));
  818. end
  819. else
  820. begin
  821. if isaddr then
  822. begin
  823. ptrdef:=cpointerdef.getreusable(vs.vardef);
  824. tg.GetLocal(list,ptrdef.size,ptrdef,vs.initialloc.reference)
  825. end
  826. else
  827. tg.GetLocal(list,vs.getsize,tparavarsym(vs).paraloc[calleeside].alignment,vs.vardef,vs.initialloc.reference);
  828. end;
  829. end;
  830. end;
  831. hlcg.varsym_set_localloc(list,vs);
  832. end;
  833. localvarsym :
  834. begin
  835. vs:=tabstractnormalvarsym(sym);
  836. vs.initialloc.size:=def_cgsize(vs.vardef);
  837. if ([po_assembler,po_nostackframe] * pd.procoptions = [po_assembler,po_nostackframe]) and
  838. (vo_is_funcret in vs.varoptions) then
  839. begin
  840. paramanager.create_funcretloc_info(pd,calleeside);
  841. if assigned(pd.funcretloc[calleeside].location^.next) then
  842. begin
  843. { can't replace references to "result" with a complex
  844. location expression inside assembler code }
  845. location_reset(vs.initialloc,LOC_INVALID,OS_NO);
  846. end
  847. else
  848. pd.funcretloc[calleeside].get_location(vs.initialloc);
  849. end
  850. else if (m_delphi in current_settings.modeswitches) and
  851. (po_assembler in pd.procoptions) and
  852. (vo_is_funcret in vs.varoptions) and
  853. (vs.refs=0) then
  854. begin
  855. { not referenced, so don't allocate. Use dummy to }
  856. { avoid ie's later on because of LOC_INVALID }
  857. vs.initialloc.loc:=LOC_REGISTER;
  858. vs.initialloc.size:=OS_INT;
  859. vs.initialloc.register:=NR_FUNCTION_RESULT_REG;
  860. end
  861. else if vs.is_regvar(false) then
  862. begin
  863. vs.initialloc.loc:=tvarregable2tcgloc[vs.varregable];
  864. gen_alloc_regvar(list,vs,true);
  865. end
  866. else
  867. begin
  868. vs.initialloc.loc:=LOC_REFERENCE;
  869. tg.GetLocal(list,vs.getsize,vs.vardef,vs.initialloc.reference);
  870. end;
  871. hlcg.varsym_set_localloc(list,vs);
  872. end;
  873. else
  874. ;
  875. end;
  876. end;
  877. end;
  878. procedure add_regvars(var rv: tusedregvars; const location: tlocation);
  879. begin
  880. case location.loc of
  881. LOC_CREGISTER:
  882. {$if defined(cpu64bitalu)}
  883. if location.size in [OS_128,OS_S128] then
  884. begin
  885. rv.intregvars.addnodup(getsupreg(location.register128.reglo));
  886. rv.intregvars.addnodup(getsupreg(location.register128.reghi));
  887. end
  888. else
  889. {$elseif defined(cpu32bitalu)}
  890. if location.size in [OS_64,OS_S64] then
  891. begin
  892. rv.intregvars.addnodup(getsupreg(location.register64.reglo));
  893. rv.intregvars.addnodup(getsupreg(location.register64.reghi));
  894. end
  895. else
  896. {$elseif defined(cpu16bitalu)}
  897. if location.size in [OS_64,OS_S64] then
  898. begin
  899. rv.intregvars.addnodup(getsupreg(location.register64.reglo));
  900. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(location.register64.reglo)));
  901. rv.intregvars.addnodup(getsupreg(location.register64.reghi));
  902. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(location.register64.reghi)));
  903. end
  904. else
  905. if location.size in [OS_32,OS_S32] then
  906. begin
  907. rv.intregvars.addnodup(getsupreg(location.register));
  908. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(location.register)));
  909. end
  910. else
  911. {$elseif defined(cpu8bitalu)}
  912. if location.size in [OS_64,OS_S64] then
  913. begin
  914. rv.intregvars.addnodup(getsupreg(location.register64.reglo));
  915. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(location.register64.reglo)));
  916. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(cg.GetNextReg(location.register64.reglo))));
  917. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(location.register64.reglo)))));
  918. rv.intregvars.addnodup(getsupreg(location.register64.reghi));
  919. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(location.register64.reghi)));
  920. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(cg.GetNextReg(location.register64.reghi))));
  921. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(location.register64.reghi)))));
  922. end
  923. else
  924. if location.size in [OS_32,OS_S32] then
  925. begin
  926. rv.intregvars.addnodup(getsupreg(location.register));
  927. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(location.register)));
  928. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(cg.GetNextReg(location.register))));
  929. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(location.register)))));
  930. end
  931. else
  932. if location.size in [OS_16,OS_S16] then
  933. begin
  934. rv.intregvars.addnodup(getsupreg(location.register));
  935. rv.intregvars.addnodup(getsupreg(cg.GetNextReg(location.register)));
  936. end
  937. else
  938. {$endif}
  939. if getregtype(location.register)=R_INTREGISTER then
  940. rv.intregvars.addnodup(getsupreg(location.register))
  941. else
  942. rv.addrregvars.addnodup(getsupreg(location.register));
  943. LOC_CFPUREGISTER:
  944. rv.fpuregvars.addnodup(getsupreg(location.register));
  945. LOC_CMMREGISTER:
  946. rv.mmregvars.addnodup(getsupreg(location.register));
  947. else
  948. ;
  949. end;
  950. end;
  951. function do_get_used_regvars(var n: tnode; arg: pointer): foreachnoderesult;
  952. var
  953. rv: pusedregvars absolute arg;
  954. begin
  955. case (n.nodetype) of
  956. temprefn:
  957. { We only have to synchronise a tempnode before a loop if it is }
  958. { not created inside the loop, and only synchronise after the }
  959. { loop if it's not destroyed inside the loop. If it's created }
  960. { before the loop and not yet destroyed, then before the loop }
  961. { is secondpassed tempinfo^.valid will be true, and we get the }
  962. { correct registers. If it's not destroyed inside the loop, }
  963. { then after the loop has been secondpassed tempinfo^.valid }
  964. { be true and we also get the right registers. In other cases, }
  965. { tempinfo^.valid will be false and so we do not add }
  966. { unnecessary registers. This way, we don't have to look at }
  967. { tempcreate and tempdestroy nodes to get this info (JM) }
  968. if (ti_valid in ttemprefnode(n).tempflags) then
  969. add_regvars(rv^,ttemprefnode(n).tempinfo^.location);
  970. loadn:
  971. if (tloadnode(n).symtableentry.typ in [staticvarsym,localvarsym,paravarsym]) then
  972. add_regvars(rv^,tabstractnormalvarsym(tloadnode(n).symtableentry).localloc);
  973. vecn:
  974. begin
  975. { range checks sometimes need the high parameter }
  976. if (cs_check_range in current_settings.localswitches) and
  977. (is_open_array(tvecnode(n).left.resultdef) or
  978. is_array_of_const(tvecnode(n).left.resultdef)) and
  979. not(current_procinfo.procdef.proccalloption in cdecl_pocalls) then
  980. add_regvars(rv^,tabstractnormalvarsym(get_high_value_sym(tparavarsym(tloadnode(tvecnode(n).left).symtableentry))).localloc)
  981. end;
  982. else
  983. ;
  984. end;
  985. result := fen_true;
  986. end;
  987. procedure get_used_regvars(n: tnode; var rv: tusedregvars);
  988. begin
  989. foreachnodestatic(n,@do_get_used_regvars,@rv);
  990. end;
  991. (*
  992. See comments at declaration of pusedregvarscommon
  993. function do_get_used_regvars_common(var n: tnode; arg: pointer): foreachnoderesult;
  994. var
  995. rv: pusedregvarscommon absolute arg;
  996. begin
  997. if (n.nodetype = loadn) and
  998. (tloadnode(n).symtableentry.typ in [staticvarsym,localvarsym,paravarsym]) then
  999. with tabstractnormalvarsym(tloadnode(n).symtableentry).localloc do
  1000. case loc of
  1001. LOC_CREGISTER:
  1002. { if not yet encountered in this node tree }
  1003. if (rv^.myregvars.intregvars.addnodup(getsupreg(register))) and
  1004. { but nevertheless already encountered somewhere }
  1005. not(rv^.allregvars.intregvars.addnodup(getsupreg(register))) then
  1006. { then it's a regvar used in two or more node trees }
  1007. rv^.commonregvars.intregvars.addnodup(getsupreg(register));
  1008. LOC_CFPUREGISTER:
  1009. if (rv^.myregvars.intregvars.addnodup(getsupreg(register))) and
  1010. not(rv^.allregvars.intregvars.addnodup(getsupreg(register))) then
  1011. rv^.commonregvars.intregvars.addnodup(getsupreg(register));
  1012. LOC_CMMREGISTER:
  1013. if (rv^.myregvars.intregvars.addnodup(getsupreg(register))) and
  1014. not(rv^.allregvars.intregvars.addnodup(getsupreg(register))) then
  1015. rv^.commonregvars.intregvars.addnodup(getsupreg(register));
  1016. end;
  1017. result := fen_true;
  1018. end;
  1019. procedure get_used_regvars_common(n: tnode; var rv: tusedregvarscommon);
  1020. begin
  1021. rv.myregvars.intregvars.clear;
  1022. rv.myregvars.fpuregvars.clear;
  1023. rv.myregvars.mmregvars.clear;
  1024. foreachnodestatic(n,@do_get_used_regvars_common,@rv);
  1025. end;
  1026. *)
  1027. procedure gen_sync_regvars(list:TAsmList; var rv: tusedregvars);
  1028. var
  1029. count: longint;
  1030. begin
  1031. for count := 1 to rv.intregvars.length do
  1032. cg.a_reg_sync(list,newreg(R_INTREGISTER,rv.intregvars.readidx(count-1),R_SUBWHOLE));
  1033. for count := 1 to rv.addrregvars.length do
  1034. cg.a_reg_sync(list,newreg(R_ADDRESSREGISTER,rv.addrregvars.readidx(count-1),R_SUBWHOLE));
  1035. for count := 1 to rv.fpuregvars.length do
  1036. cg.a_reg_sync(list,newreg(R_FPUREGISTER,rv.fpuregvars.readidx(count-1),R_SUBWHOLE));
  1037. for count := 1 to rv.mmregvars.length do
  1038. cg.a_reg_sync(list,newreg(R_MMREGISTER,rv.mmregvars.readidx(count-1),R_SUBWHOLE));
  1039. end;
  1040. procedure gen_free_symtable(list:TAsmList;st:TSymtable);
  1041. var
  1042. i : longint;
  1043. sym : tsym;
  1044. begin
  1045. for i:=0 to st.SymList.Count-1 do
  1046. begin
  1047. sym:=tsym(st.SymList[i]);
  1048. if (sym.typ in [staticvarsym,localvarsym,paravarsym]) then
  1049. begin
  1050. with tabstractnormalvarsym(sym) do
  1051. begin
  1052. { Note: We need to keep the data available in memory
  1053. for the sub procedures that can access local data
  1054. in the parent procedures }
  1055. case localloc.loc of
  1056. LOC_CREGISTER :
  1057. if (pi_has_label in current_procinfo.flags) then
  1058. {$if defined(cpu64bitalu)}
  1059. if def_cgsize(vardef) in [OS_128,OS_S128] then
  1060. begin
  1061. cg.a_reg_sync(list,localloc.register128.reglo);
  1062. cg.a_reg_sync(list,localloc.register128.reghi);
  1063. end
  1064. else
  1065. {$elseif defined(cpu32bitalu)}
  1066. if def_cgsize(vardef) in [OS_64,OS_S64] then
  1067. begin
  1068. cg.a_reg_sync(list,localloc.register64.reglo);
  1069. cg.a_reg_sync(list,localloc.register64.reghi);
  1070. end
  1071. else
  1072. {$elseif defined(cpu16bitalu)}
  1073. if def_cgsize(vardef) in [OS_64,OS_S64] then
  1074. begin
  1075. cg.a_reg_sync(list,localloc.register64.reglo);
  1076. cg.a_reg_sync(list,cg.GetNextReg(localloc.register64.reglo));
  1077. cg.a_reg_sync(list,localloc.register64.reghi);
  1078. cg.a_reg_sync(list,cg.GetNextReg(localloc.register64.reghi));
  1079. end
  1080. else
  1081. if def_cgsize(vardef) in [OS_32,OS_S32] then
  1082. begin
  1083. cg.a_reg_sync(list,localloc.register);
  1084. cg.a_reg_sync(list,cg.GetNextReg(localloc.register));
  1085. end
  1086. else
  1087. {$elseif defined(cpu8bitalu)}
  1088. if def_cgsize(vardef) in [OS_64,OS_S64] then
  1089. begin
  1090. cg.a_reg_sync(list,localloc.register64.reglo);
  1091. cg.a_reg_sync(list,cg.GetNextReg(localloc.register64.reglo));
  1092. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(localloc.register64.reglo)));
  1093. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(localloc.register64.reglo))));
  1094. cg.a_reg_sync(list,localloc.register64.reghi);
  1095. cg.a_reg_sync(list,cg.GetNextReg(localloc.register64.reghi));
  1096. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(localloc.register64.reghi)));
  1097. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(localloc.register64.reghi))));
  1098. end
  1099. else
  1100. if def_cgsize(vardef) in [OS_32,OS_S32] then
  1101. begin
  1102. cg.a_reg_sync(list,localloc.register);
  1103. cg.a_reg_sync(list,cg.GetNextReg(localloc.register));
  1104. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(localloc.register)));
  1105. cg.a_reg_sync(list,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(localloc.register))));
  1106. end
  1107. else
  1108. if def_cgsize(vardef) in [OS_16,OS_S16] then
  1109. begin
  1110. cg.a_reg_sync(list,localloc.register);
  1111. cg.a_reg_sync(list,cg.GetNextReg(localloc.register));
  1112. end
  1113. else
  1114. {$endif}
  1115. cg.a_reg_sync(list,localloc.register);
  1116. LOC_CFPUREGISTER,
  1117. LOC_CMMREGISTER,
  1118. LOC_CMMXREGISTER:
  1119. if (pi_has_label in current_procinfo.flags) then
  1120. cg.a_reg_sync(list,localloc.register);
  1121. LOC_REFERENCE :
  1122. begin
  1123. { can't free the result, because we load it after
  1124. this call into the function result location
  1125. (gets freed in thlcgobj.gen_load_return_value();) }
  1126. if (typ in [localvarsym,paravarsym]) and
  1127. (([vo_is_funcret,vo_is_result]*varoptions)=[]) and
  1128. ((current_procinfo.procdef.proctypeoption<>potype_constructor) or
  1129. not(vo_is_self in varoptions)) then
  1130. tg.Ungetlocal(list,localloc.reference);
  1131. end;
  1132. { function results in pure assembler routines }
  1133. LOC_REGISTER,
  1134. LOC_FPUREGISTER,
  1135. LOC_MMREGISTER,
  1136. { empty parameter }
  1137. LOC_VOID,
  1138. { global variables in memory and typed constants don't get a location assigned,
  1139. and neither does an unused $result variable in pure assembler routines }
  1140. LOC_INVALID:
  1141. ;
  1142. else
  1143. internalerror(2019050538);
  1144. end;
  1145. end;
  1146. end;
  1147. end;
  1148. end;
  1149. function getprocalign : shortint;
  1150. begin
  1151. { gprof uses 16 byte granularity }
  1152. if (cs_profile in current_settings.moduleswitches) then
  1153. result:=16
  1154. else
  1155. result:=current_settings.alignment.procalign;
  1156. end;
  1157. procedure gen_load_frame_for_exceptfilter(list : TAsmList);
  1158. var
  1159. para: tparavarsym;
  1160. begin
  1161. para:=tparavarsym(current_procinfo.procdef.paras[0]);
  1162. if not (vo_is_parentfp in para.varoptions) then
  1163. InternalError(201201142);
  1164. if (para.paraloc[calleeside].location^.loc<>LOC_REGISTER) or
  1165. (para.paraloc[calleeside].location^.next<>nil) then
  1166. InternalError(201201143);
  1167. cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,para.paraloc[calleeside].location^.register,
  1168. NR_FRAME_POINTER_REG);
  1169. end;
  1170. end.