ncgcal.pas 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate i386 assembler for in call nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgcal;
  19. {$i fpcdefs.inc}
  20. interface
  21. { $define AnsiStrRef}
  22. uses
  23. cpubase,
  24. globtype,
  25. symdef,node,ncal;
  26. type
  27. tcgcallparanode = class(tcallparanode)
  28. procedure secondcallparan(push_from_left_to_right:boolean;calloption:tproccalloption;
  29. para_alignment,para_offset : longint);override;
  30. end;
  31. tcgcallnode = class(tcallnode)
  32. private
  33. procedure release_para_temps;
  34. procedure normal_pass_2;
  35. procedure inlined_pass_2;
  36. protected
  37. refcountedtemp : treference;
  38. procedure handle_return_value;
  39. {# This routine is used to push the current frame pointer
  40. on the stack. This is used in nested routines where the
  41. value of the frame pointer is always pushed as an extra
  42. parameter.
  43. The default handling is the standard handling used on
  44. most stack based machines, where the frame pointer is
  45. the first invisible parameter.
  46. }
  47. function align_parasize:longint;virtual;
  48. procedure pop_parasize(pop_size:longint);virtual;
  49. procedure push_framepointer;virtual;
  50. procedure extra_interrupt_code;virtual;
  51. public
  52. procedure pass_2;override;
  53. end;
  54. implementation
  55. uses
  56. systems,
  57. cutils,verbose,globals,
  58. symconst,symbase,symsym,symtable,defutil,paramgr,
  59. {$ifdef GDB}
  60. {$ifdef delphi}
  61. sysutils,
  62. {$else}
  63. strings,
  64. {$endif}
  65. gdb,
  66. {$endif GDB}
  67. cginfo,cgbase,pass_2,
  68. cpuinfo,aasmbase,aasmtai,aasmcpu,
  69. nbas,nmem,nld,ncnv,
  70. {$ifdef x86}
  71. cga,
  72. {$endif x86}
  73. {$ifdef cpu64bit}
  74. cg64f64,
  75. {$else cpu64bit}
  76. cg64f32,
  77. {$endif cpu64bit}
  78. {$ifdef powerpc}
  79. cpupi,
  80. {$endif powerpc}
  81. ncgutil,cgobj,tgobj,regvars,rgobj,rgcpu;
  82. var
  83. { Current callnode, this is needed for having a link
  84. between the callparanodes and the callnode they belong to }
  85. aktcallnode : tcallnode;
  86. {*****************************************************************************
  87. TCGCALLPARANODE
  88. *****************************************************************************}
  89. procedure tcgcallparanode.secondcallparan(push_from_left_to_right:boolean;calloption:tproccalloption;para_alignment,para_offset : longint);
  90. var
  91. otlabel,
  92. oflabel : tasmlabel;
  93. tmpreg : tregister;
  94. href : treference;
  95. begin
  96. if not(assigned(paraitem.paratype.def) or
  97. assigned(paraitem.parasym)) then
  98. internalerror(200304242);
  99. { set default para_alignment to target_info.stackalignment }
  100. if para_alignment=0 then
  101. para_alignment:=aktalignment.paraalign;
  102. { push from left to right if specified }
  103. if push_from_left_to_right and assigned(right) then
  104. begin
  105. tcallparanode(right).secondcallparan(push_from_left_to_right,
  106. calloption,para_alignment,para_offset);
  107. end;
  108. otlabel:=truelabel;
  109. oflabel:=falselabel;
  110. objectlibrary.getlabel(truelabel);
  111. objectlibrary.getlabel(falselabel);
  112. secondpass(left);
  113. { handle varargs first, because defcoll is not valid }
  114. if (nf_varargs_para in flags) then
  115. begin
  116. if paramanager.push_addr_param(left.resulttype.def,calloption) then
  117. begin
  118. inc(pushedparasize,POINTER_SIZE);
  119. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
  120. location_release(exprasmlist,left.location);
  121. end
  122. else
  123. push_value_para(exprasmlist,left,calloption,para_offset,para_alignment,paraitem.paraloc);
  124. end
  125. { hidden parameters }
  126. else if paraitem.is_hidden then
  127. begin
  128. { don't push a node that already generated a pointer type
  129. by address for implicit hidden parameters }
  130. if (vo_is_funcret in tvarsym(paraitem.parasym).varoptions) or
  131. (not(left.resulttype.def.deftype in [pointerdef,classrefdef]) and
  132. paramanager.push_addr_param(paraitem.paratype.def,calloption)) then
  133. begin
  134. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  135. internalerror(200305071);
  136. inc(pushedparasize,POINTER_SIZE);
  137. if calloption=pocall_inline then
  138. begin
  139. {$ifdef newra}
  140. tmpreg:=rg.getaddressregister(exprasmlist);
  141. {$else}
  142. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  143. {$endif}
  144. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
  145. reference_reset_base(href,current_procinfo.framepointer,para_offset-pushedparasize);
  146. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,tmpreg,href);
  147. {$ifdef newra}
  148. rg.ungetregisterint(exprasmlist,tmpreg);
  149. {$else}
  150. cg.free_scratch_reg(exprasmlist,tmpreg);
  151. {$endif}
  152. end
  153. else
  154. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
  155. location_release(exprasmlist,left.location);
  156. end
  157. else
  158. begin
  159. push_value_para(exprasmlist,left,calloption,
  160. para_offset,para_alignment,paraitem.paraloc);
  161. end;
  162. end
  163. { filter array of const c styled args }
  164. else if is_array_of_const(left.resulttype.def) and (nf_cargs in left.flags) then
  165. begin
  166. { nothing, everything is already pushed }
  167. end
  168. { in codegen.handleread.. paraitem.data is set to nil }
  169. else if assigned(paraitem.paratype.def) and
  170. (paraitem.paratype.def.deftype=formaldef) then
  171. begin
  172. { allow passing of a constant to a const formaldef }
  173. if (tvarsym(paraitem.parasym).varspez=vs_const) and
  174. (left.location.loc=LOC_CONSTANT) then
  175. location_force_mem(exprasmlist,left.location);
  176. { allow @var }
  177. inc(pushedparasize,POINTER_SIZE);
  178. if (left.nodetype=addrn) and
  179. (not(nf_procvarload in left.flags)) then
  180. begin
  181. if calloption=pocall_inline then
  182. begin
  183. reference_reset_base(href,current_procinfo.framepointer,para_offset-pushedparasize);
  184. cg.a_load_loc_ref(exprasmlist,OS_ADDR,left.location,href);
  185. end
  186. else
  187. cg.a_param_loc(exprasmlist,left.location,paraitem.paraloc);
  188. location_release(exprasmlist,left.location);
  189. end
  190. else
  191. begin
  192. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  193. internalerror(200304235);
  194. if calloption=pocall_inline then
  195. begin
  196. {$ifdef newra}
  197. tmpreg:=rg.getaddressregister(exprasmlist);
  198. {$else}
  199. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  200. {$endif newra}
  201. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
  202. reference_reset_base(href,current_procinfo.framepointer,para_offset-pushedparasize);
  203. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,tmpreg,href);
  204. {$ifdef newra}
  205. rg.ungetregisterint(exprasmlist,tmpreg);
  206. {$else}
  207. cg.free_scratch_reg(exprasmlist,tmpreg);
  208. {$endif}
  209. end
  210. else
  211. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
  212. location_release(exprasmlist,left.location);
  213. end;
  214. end
  215. { handle call by reference parameter }
  216. else if (paraitem.paratyp in [vs_var,vs_out]) then
  217. begin
  218. if (left.location.loc<>LOC_REFERENCE) then
  219. begin
  220. { passing self to a var parameter is allowed in
  221. TP and delphi }
  222. if not((left.location.loc=LOC_CREFERENCE) and
  223. is_self_node(left)) then
  224. internalerror(200106041);
  225. end;
  226. if (paraitem.paratyp=vs_out) and
  227. assigned(paraitem.paratype.def) and
  228. not is_class(paraitem.paratype.def) and
  229. paraitem.paratype.def.needs_inittable then
  230. cg.g_finalize(exprasmlist,paraitem.paratype.def,left.location.reference,false);
  231. inc(pushedparasize,POINTER_SIZE);
  232. if calloption=pocall_inline then
  233. begin
  234. {$ifdef newra}
  235. tmpreg:=rg.getaddressregister(exprasmlist);
  236. {$else}
  237. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  238. {$endif}
  239. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
  240. reference_reset_base(href,current_procinfo.framepointer,para_offset-pushedparasize);
  241. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,tmpreg,href);
  242. {$ifdef newra}
  243. rg.ungetregisterint(exprasmlist,tmpreg);
  244. {$else}
  245. cg.free_scratch_reg(exprasmlist,tmpreg);
  246. {$endif}
  247. end
  248. else
  249. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
  250. location_release(exprasmlist,left.location);
  251. end
  252. else
  253. begin
  254. { don't push a node that already generated a pointer type
  255. by address for implicit hidden parameters }
  256. if (not(
  257. paraitem.is_hidden and
  258. (left.resulttype.def.deftype in [pointerdef,classrefdef])
  259. ) and
  260. paramanager.push_addr_param(paraitem.paratype.def,calloption)) then
  261. begin
  262. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  263. begin
  264. { allow passing nil to a procvardef (methodpointer) }
  265. if (left.nodetype=typeconvn) and
  266. (left.resulttype.def.deftype=procvardef) and
  267. (ttypeconvnode(left).left.nodetype=niln) then
  268. begin
  269. tg.GetTemp(exprasmlist,tcgsize2size[left.location.size],tt_normal,href);
  270. if not (left.location.size in [OS_64,OS_S64]) then
  271. cg.a_load_loc_ref(exprasmlist,left.location.size,left.location,href)
  272. else
  273. cg64.a_load64_loc_ref(exprasmlist,left.location,href);
  274. location_reset(left.location,LOC_REFERENCE,left.location.size);
  275. left.location.reference:=href;
  276. end
  277. else
  278. internalerror(200204011);
  279. end;
  280. inc(pushedparasize,POINTER_SIZE);
  281. if calloption=pocall_inline then
  282. begin
  283. {$ifdef newra}
  284. tmpreg:=rg.getaddressregister(exprasmlist);
  285. {$else}
  286. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  287. {$endif}
  288. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
  289. reference_reset_base(href,current_procinfo.framepointer,para_offset-pushedparasize);
  290. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,tmpreg,href);
  291. {$ifdef newra}
  292. rg.ungetregisterint(exprasmlist,tmpreg);
  293. {$else}
  294. cg.free_scratch_reg(exprasmlist,tmpreg);
  295. {$endif}
  296. end
  297. else
  298. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
  299. location_release(exprasmlist,left.location);
  300. end
  301. else
  302. begin
  303. push_value_para(exprasmlist,left,calloption,
  304. para_offset,para_alignment,paraitem.paraloc);
  305. end;
  306. end;
  307. truelabel:=otlabel;
  308. falselabel:=oflabel;
  309. { update return location in callnode when this is the function
  310. result }
  311. if (vo_is_funcret in tvarsym(paraitem.parasym).varoptions) then
  312. begin
  313. location_copy(aktcallnode.location,left.location);
  314. end;
  315. { push from right to left }
  316. if not push_from_left_to_right and assigned(right) then
  317. begin
  318. tcallparanode(right).secondcallparan(push_from_left_to_right,
  319. calloption,para_alignment,para_offset);
  320. end;
  321. end;
  322. {*****************************************************************************
  323. TCGCALLNODE
  324. *****************************************************************************}
  325. procedure tcgcallnode.extra_interrupt_code;
  326. begin
  327. end;
  328. function tcgcallnode.align_parasize:longint;
  329. begin
  330. result:=0;
  331. end;
  332. procedure tcgcallnode.pop_parasize(pop_size:longint);
  333. begin
  334. end;
  335. procedure tcgcallnode.push_framepointer;
  336. var
  337. href : treference;
  338. hregister : tregister;
  339. i : integer;
  340. begin
  341. { this routine is itself not nested }
  342. if current_procdef.parast.symtablelevel=(tprocdef(procdefinition).parast.symtablelevel) then
  343. begin
  344. reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset);
  345. cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(exprasmlist,1));
  346. end
  347. { one nesting level }
  348. else if (current_procdef.parast.symtablelevel=(tprocdef(procdefinition).parast.symtablelevel)-1) then
  349. begin
  350. cg.a_param_reg(exprasmlist,OS_ADDR,current_procinfo.framepointer,paramanager.getintparaloc(exprasmlist,1));
  351. end
  352. { very complex nesting level ... }
  353. else if (current_procdef.parast.symtablelevel>(tprocdef(procdefinition).parast.symtablelevel)) then
  354. begin
  355. hregister:=rg.getaddressregister(exprasmlist);
  356. reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset);
  357. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  358. i:=current_procdef.parast.symtablelevel;
  359. while (i>tprocdef(procdefinition).parast.symtablelevel) do
  360. begin
  361. reference_reset_base(href,hregister,current_procinfo.framepointer_offset);
  362. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  363. dec(i);
  364. end;
  365. cg.a_param_reg(exprasmlist,OS_ADDR,hregister,paramanager.getintparaloc(exprasmlist,1));
  366. rg.ungetaddressregister(exprasmlist,hregister);
  367. end;
  368. end;
  369. procedure tcgcallnode.handle_return_value;
  370. var
  371. cgsize : tcgsize;
  372. r,hregister : tregister;
  373. href: treference;
  374. tempnode: tnode;
  375. begin
  376. { structured results are easy to handle.... }
  377. { needed also when result_no_used !! }
  378. if paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
  379. begin
  380. { Location should be setup by the funcret para }
  381. if location.loc<>LOC_REFERENCE then
  382. internalerror(200304241);
  383. end
  384. else
  385. { ansi/widestrings must be registered, so we can dispose them }
  386. if is_ansistring(resulttype.def) or
  387. is_widestring(resulttype.def) then
  388. begin
  389. r.enum:=R_INTREGISTER;
  390. r.number:=NR_FUNCTION_RETURN_REG;
  391. cg.a_reg_alloc(exprasmlist,r);
  392. if not assigned(funcretnode) then
  393. begin
  394. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  395. location.reference:=refcountedtemp;
  396. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,r,location.reference);
  397. cg.a_reg_dealloc(exprasmlist,r);
  398. end
  399. else
  400. begin
  401. tg.gettemp(exprasmlist,pointer_size,tt_normal,href);
  402. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,r,href);
  403. cg.a_reg_dealloc(exprasmlist,r);
  404. { in case of a regular funcretnode with ret_in_param, the }
  405. { original funcretnode isn't touched -> make sure it's }
  406. { the same here (not sure if it's necessary) }
  407. tempnode := funcretnode.getcopy;
  408. tempnode.pass_2;
  409. location := tempnode.location;
  410. tempnode.free;
  411. cg.g_decrrefcount(exprasmlist,resulttype.def,location.reference, false);
  412. cg.a_load_ref_ref(exprasmlist,OS_ADDR,OS_ADDR,href,location.reference);
  413. { since we used a normal temp, it won't be finalized or }
  414. { decref'd later -> no need to zero it }
  415. tg.ungettemp(exprasmlist,href);
  416. end;
  417. end
  418. else
  419. { we have only to handle the result if it is used }
  420. if (nf_return_value_used in flags) then
  421. begin
  422. if (resulttype.def.deftype=floatdef) then
  423. begin
  424. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  425. {$ifdef cpufpemu}
  426. if cs_fp_emulation in aktmoduleswitches then
  427. location.register.enum := FUNCTION_RESULT_REG
  428. else
  429. {$endif cpufpemu}
  430. location.register.enum:=FPU_RESULT_REG;
  431. {$ifdef x86}
  432. inc(trgcpu(rg).fpuvaroffset);
  433. {$else x86}
  434. hregister := rg.getregisterfpu(exprasmlist,location.size);
  435. cg.a_loadfpu_reg_reg(exprasmlist,location.register,hregister);
  436. location.register := hregister;
  437. {$endif x86}
  438. end
  439. else
  440. begin
  441. cgsize:=def_cgsize(resulttype.def);
  442. { an object constructor is a function with pointer result }
  443. if (procdefinition.proctypeoption=potype_constructor) then
  444. cgsize:=OS_ADDR;
  445. if cgsize<>OS_NO then
  446. begin
  447. location_reset(location,LOC_REGISTER,cgsize);
  448. {$ifndef cpu64bit}
  449. if cgsize in [OS_64,OS_S64] then
  450. begin
  451. { Move the function result to free registers, preferably the
  452. FUNCTION_RESULT_REG/FUNCTION_RESULTHIGH_REG, so no move is necessary.}
  453. r.enum:=R_INTREGISTER;
  454. r.number:=NR_FUNCTION_RESULT64_LOW_REG;
  455. hregister.enum:=R_INTREGISTER;
  456. hregister.number:=NR_FUNCTION_RESULT64_HIGH_REG;
  457. {$ifdef newra}
  458. rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RESULT64_LOW_REG);
  459. rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RESULT64_HIGH_REG);
  460. rg.ungetregisterint(exprasmlist,r);
  461. rg.ungetregisterint(exprasmlist,hregister);
  462. location.registerlow:=rg.getregisterint(exprasmlist,OS_INT);
  463. location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
  464. {$else newra}
  465. if RS_FUNCTION_RESULT64_LOW_REG in rg.unusedregsint then
  466. location.registerlow:=rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RESULT64_LOW_REG)
  467. else
  468. cg.a_reg_alloc(exprasmlist,r);
  469. if RS_FUNCTION_RESULT64_HIGH_REG in rg.unusedregsint then
  470. location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RESULT64_HIGH_REG)
  471. else
  472. cg.a_reg_alloc(exprasmlist,hregister);
  473. { do this after both low,high are allocated, else it is possible that
  474. low will be loaded in the register that still contains high }
  475. if location.registerlow.number=NR_NO then
  476. location.registerlow:=rg.getregisterint(exprasmlist,OS_INT);
  477. if location.registerhigh.number=NR_NO then
  478. location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
  479. {$endif newra}
  480. cg64.a_load64_reg_reg(exprasmlist,joinreg64(r,hregister),
  481. location.register64{$ifdef newra},false{$endif});
  482. end
  483. else
  484. {$endif cpu64bit}
  485. begin
  486. {Move the function result to a free register, preferably the
  487. FUNCTION_RESULT_REG, so no move is necessary.}
  488. r.enum:=R_INTREGISTER;
  489. r.number:=NR_FUNCTION_RESULT_REG;
  490. r:=rg.makeregsize(r,cgsize);
  491. {$ifdef newra}
  492. { rg.getexplicitregisterint(exprasmlist,nr);}
  493. rg.ungetregisterint(exprasmlist,r);
  494. location.register:=rg.getregisterint(exprasmlist,cgsize);
  495. {$else newra}
  496. cg.a_reg_alloc(exprasmlist,r);
  497. if RS_FUNCTION_RESULT_REG in rg.unusedregsint then
  498. begin
  499. location.register:=rg.makeregsize(rg.getexplicitregisterint(
  500. exprasmlist,NR_FUNCTION_RESULT_REG),cgsize);
  501. end
  502. else
  503. location.register:=rg.getregisterint(exprasmlist,cgsize);
  504. {$endif newra}
  505. cg.a_load_reg_reg(exprasmlist,cgsize,cgsize,r,location.register);
  506. end;
  507. end
  508. else
  509. begin
  510. if resulttype.def.size>0 then
  511. internalerror(200305131);
  512. end;
  513. end;
  514. end
  515. else
  516. location_reset(location,LOC_VOID,OS_NO);
  517. end;
  518. procedure tcgcallnode.release_para_temps;
  519. var
  520. hp : tnode;
  521. ppn : tcallparanode;
  522. begin
  523. { Release temps from parameters }
  524. ppn:=tcallparanode(left);
  525. while assigned(ppn) do
  526. begin
  527. if assigned(ppn.left) then
  528. begin
  529. { don't release the funcret temp }
  530. if not(vo_is_funcret in tvarsym(ppn.paraitem.parasym).varoptions) then
  531. begin
  532. {$ifdef callparatemp}
  533. { free call-by-reference temps }
  534. if (ppn.left.nodetype = typeconvn) and
  535. (ttypeconvnode(ppn.left).left.nodetype = derefn) and
  536. (tderefnode(ttypeconvnode(ppn.left).left).left.nodetype = temprefn) then
  537. location_freetemp(exprasmlist,tderefnode(ttypeconvnode(ppn.left).left).left.location)
  538. else
  539. {$endif callparatemp}
  540. location_freetemp(exprasmlist,ppn.left.location);
  541. end;
  542. { process also all nodes of an array of const }
  543. if ppn.left.nodetype=arrayconstructorn then
  544. begin
  545. if assigned(tarrayconstructornode(ppn.left).left) then
  546. begin
  547. hp:=ppn.left;
  548. while assigned(hp) do
  549. begin
  550. location_freetemp(exprasmlist,tarrayconstructornode(hp).left.location);
  551. hp:=tarrayconstructornode(hp).right;
  552. end;
  553. end;
  554. end;
  555. end;
  556. ppn:=tcallparanode(ppn.right);
  557. end;
  558. end;
  559. procedure tcgcallnode.normal_pass_2;
  560. var
  561. regs_to_push_other : tregisterset;
  562. unusedstate: pointer;
  563. {$ifdef newra}
  564. i:Tsuperregister;
  565. regs_to_alloc,regs_to_free:Tsupregset;
  566. {$else}
  567. regs_to_push_int : Tsupregset;
  568. pushedint : tpushedsavedint;
  569. pushedregs : tmaybesave;
  570. {$endif}
  571. pushedother : tpushedsavedother;
  572. oldpushedparasize : longint;
  573. { adress returned from an I/O-error }
  574. iolabel : tasmlabel;
  575. { help reference pointer }
  576. href,helpref : treference;
  577. hp : tnode;
  578. pp : tcallparanode;
  579. store_parast_fixup,
  580. para_alignment,
  581. pop_size : longint;
  582. r,accreg,
  583. vmtreg,vmtreg2 : tregister;
  584. oldaktcallnode : tcallnode;
  585. begin
  586. if not assigned(procdefinition) then
  587. internalerror(200305264);
  588. iolabel:=nil;
  589. rg.saveunusedstate(unusedstate);
  590. if not assigned(funcretnode) then
  591. begin
  592. { if we allocate the temp. location for ansi- or widestrings }
  593. { already here, we avoid later a push/pop }
  594. if is_widestring(resulttype.def) then
  595. begin
  596. tg.gettemp(exprasmlist,pointer_size,tt_widestring,refcountedtemp);
  597. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
  598. end
  599. else if is_ansistring(resulttype.def) then
  600. begin
  601. tg.GetTemp(exprasmlist,pointer_size,tt_ansistring,refcountedtemp);
  602. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
  603. end;
  604. end;
  605. if (procdefinition.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_stdcall]) then
  606. para_alignment:=4
  607. else
  608. para_alignment:=aktalignment.paraalign;
  609. { proc variables destroy all registers }
  610. if (right=nil) and
  611. { virtual methods too }
  612. not(po_virtualmethod in procdefinition.procoptions) then
  613. begin
  614. if (cs_check_io in aktlocalswitches) and
  615. (po_iocheck in procdefinition.procoptions) and
  616. not(po_iocheck in current_procdef.procoptions) then
  617. begin
  618. objectlibrary.getaddrlabel(iolabel);
  619. cg.a_label(exprasmlist,iolabel);
  620. end
  621. else
  622. iolabel:=nil;
  623. {$ifdef newra}
  624. regs_to_alloc:=Tprocdef(procdefinition).usedintregisters;
  625. {$else}
  626. { save all used registers and possible registers
  627. used for the return value }
  628. regs_to_push_int := tprocdef(procdefinition).usedintregisters;
  629. if (not is_void(resulttype.def)) and
  630. (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
  631. begin
  632. {$ifndef cpu64bit}
  633. if resulttype.def.size>sizeof(aword) then
  634. begin
  635. include(regs_to_push_int,RS_FUNCTION_RESULT64_LOW_REG);
  636. include(regs_to_push_int,RS_FUNCTION_RESULT64_HIGH_REG);
  637. end
  638. else
  639. {$endif cpu64bit}
  640. include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
  641. end;
  642. rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
  643. {$endif}
  644. regs_to_push_other := tprocdef(procdefinition).usedotherregisters;
  645. rg.saveusedotherregisters(exprasmlist,pushedother,regs_to_push_other);
  646. { on the ppc, ever procedure saves the non-volatile registers it uses itself }
  647. { and must make sure it saves its volatile registers before doing a call }
  648. {$ifdef i386}
  649. { give used registers through }
  650. {$ifndef newra}
  651. rg.usedintinproc:=rg.usedintinproc + tprocdef(procdefinition).usedintregisters;
  652. {$endif}
  653. rg.usedinproc:=rg.usedinproc + tprocdef(procdefinition).usedotherregisters;
  654. {$endif i386}
  655. end
  656. else
  657. begin
  658. {No procedure is allowed to destroy ebp.}
  659. {$ifdef newra}
  660. regs_to_alloc:=ALL_INTREGISTERS-[RS_FRAME_POINTER_REG];
  661. {$else}
  662. regs_to_push_int := all_intregisters-[RS_FRAME_POINTER_REG];
  663. rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
  664. {$endif}
  665. regs_to_push_other := all_registers;
  666. rg.saveusedotherregisters(exprasmlist,pushedother,regs_to_push_other);
  667. {$ifndef newra}
  668. rg.usedinproc:=all_registers;
  669. {$endif}
  670. { no IO check for methods and procedure variables }
  671. iolabel:=nil;
  672. end;
  673. { Initialize for pushing the parameters }
  674. oldpushedparasize:=pushedparasize;
  675. pushedparasize:=0;
  676. { Align stack if required }
  677. pop_size:=align_parasize;
  678. { Push parameters }
  679. oldaktcallnode:=aktcallnode;
  680. aktcallnode:=self;
  681. {$ifndef newra}
  682. { process procvar. Done here already, because otherwise it may }
  683. { destroy registers containing a parameter for the actual }
  684. { function call (e.g. if it's a function, its result will }
  685. { overwrite r3, which contains the first parameter) (JM) }
  686. if assigned(right) then
  687. secondpass(right);
  688. if (po_virtualmethod in procdefinition.procoptions) and
  689. assigned(methodpointer) then
  690. begin
  691. secondpass(methodpointer);
  692. location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
  693. { virtual methods require an index }
  694. if tprocdef(procdefinition).extnumber=-1 then
  695. internalerror(200304021);
  696. { VMT should already be loaded in a register }
  697. if methodpointer.location.register.number=NR_NO then
  698. internalerror(200304022);
  699. { test validity of VMT }
  700. if not(is_interface(tprocdef(procdefinition)._class)) and
  701. not(is_cppclass(tprocdef(procdefinition)._class)) then
  702. cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
  703. end;
  704. {$endif newra}
  705. if assigned(left) then
  706. begin
  707. {$ifndef newra}
  708. if assigned(right) then
  709. maybe_save(exprasmlist,left.registers32,right.location,pushedregs)
  710. else
  711. if assigned(methodpointer) then
  712. maybe_save(exprasmlist,left.registers32,methodpointer.location,pushedregs);
  713. {$endif}
  714. tcallparanode(left).secondcallparan(
  715. (po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
  716. para_alignment,0);
  717. {$ifndef newra}
  718. if assigned(right) then
  719. maybe_restore(exprasmlist,right.location,pushedregs)
  720. else
  721. if assigned(methodpointer) then
  722. maybe_restore(exprasmlist,methodpointer.location,pushedregs);
  723. {$endif newra}
  724. end;
  725. aktcallnode:=oldaktcallnode;
  726. { procedure variable or normal function call ? }
  727. if (right=nil) then
  728. begin
  729. { push base pointer ?}
  730. if (current_procdef.parast.symtablelevel>=normal_function_level) and
  731. assigned(tprocdef(procdefinition).parast) and
  732. ((tprocdef(procdefinition).parast.symtablelevel)>normal_function_level) then
  733. push_framepointer;
  734. {$ifndef newra}
  735. rg.saveintregvars(exprasmlist,regs_to_push_int);
  736. {$endif}
  737. rg.saveotherregvars(exprasmlist,regs_to_push_other);
  738. if (po_virtualmethod in procdefinition.procoptions) and
  739. assigned(methodpointer) then
  740. begin
  741. {$ifdef newra}
  742. secondpass(methodpointer);
  743. location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
  744. vmtreg:=methodpointer.location.register;
  745. { virtual methods require an index }
  746. if tprocdef(procdefinition).extnumber=-1 then
  747. internalerror(200304021);
  748. { VMT should already be loaded in a register }
  749. if vmtreg.number=NR_NO then
  750. internalerror(200304022);
  751. { test validity of VMT }
  752. if not(is_interface(tprocdef(procdefinition)._class)) and
  753. not(is_cppclass(tprocdef(procdefinition)._class)) then
  754. cg.g_maybe_testvmt(exprasmlist,vmtreg,tprocdef(procdefinition)._class);
  755. {$else}
  756. vmtreg:=methodpointer.location.register;
  757. {$endif}
  758. {$ifdef newra}
  759. { release self }
  760. rg.ungetaddressregister(exprasmlist,vmtreg);
  761. vmtreg2:=rg.getabtregisterint(exprasmlist,OS_ADDR);
  762. rg.ungetregisterint(exprasmlist,vmtreg2);
  763. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,vmtreg,vmtreg2);
  764. for i:=first_supreg to last_supreg do
  765. if i in regs_to_alloc then
  766. begin
  767. r.number:=i shl 8 or R_SUBWHOLE;
  768. rg.getexplicitregisterint(exprasmlist,r.number);
  769. end;
  770. {$endif}
  771. { call method }
  772. reference_reset_base(href,{$ifdef newra}vmtreg2{$else}vmtreg{$endif},
  773. tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
  774. cg.a_call_ref(exprasmlist,href);
  775. {$ifndef newra}
  776. { release self }
  777. rg.ungetaddressregister(exprasmlist,vmtreg);
  778. {$endif}
  779. end
  780. else
  781. begin
  782. {$ifdef newra}
  783. for i:=first_supreg to last_supreg do
  784. if i in regs_to_alloc then
  785. begin
  786. r.number:=i shl 8 or R_SUBWHOLE;
  787. rg.getexplicitregisterint(exprasmlist,r.number);
  788. end;
  789. {$endif}
  790. { Calling interrupt from the same code requires some
  791. extra code }
  792. if (po_interrupt in procdefinition.procoptions) then
  793. extra_interrupt_code;
  794. cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
  795. end;
  796. end
  797. else
  798. { now procedure variable case }
  799. begin
  800. {$ifdef newra}
  801. secondpass(right);
  802. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  803. begin
  804. helpref:=right.location.reference;
  805. if helpref.index.number<>NR_NO then
  806. begin
  807. rg.ungetregisterint(exprasmlist,helpref.index);
  808. helpref.index:=rg.getabtregisterint(exprasmlist,OS_ADDR);
  809. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
  810. right.location.reference.index,helpref.index);
  811. end;
  812. if helpref.base.number<>NR_NO then
  813. begin
  814. rg.ungetregisterint(exprasmlist,helpref.base);
  815. helpref.base:=rg.getabtregisterint(exprasmlist,OS_ADDR);
  816. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
  817. right.location.reference.base,helpref.base);
  818. end;
  819. end
  820. else
  821. rg.ungetregisterint(exprasmlist,right.location.register);
  822. reference_release(exprasmlist,helpref);
  823. location_freetemp(exprasmlist,right.location);
  824. for i:=first_supreg to last_supreg do
  825. if i in regs_to_alloc then
  826. begin
  827. r.number:=i shl 8 or R_SUBWHOLE;
  828. rg.getexplicitregisterint(exprasmlist,r.number);
  829. end;
  830. {$endif}
  831. { Calling interrupt from the same code requires some
  832. extra code }
  833. if (po_interrupt in procdefinition.procoptions) then
  834. extra_interrupt_code;
  835. {$ifndef newra}
  836. helpref:=right.location.reference;
  837. rg.saveintregvars(exprasmlist,ALL_INTREGISTERS);
  838. {$endif}
  839. rg.saveotherregvars(exprasmlist,ALL_REGISTERS);
  840. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  841. cg.a_call_ref(exprasmlist,helpref)
  842. else
  843. cg.a_call_reg(exprasmlist,right.location.register);
  844. { cg.a_call_loc(exprasmlist,right.location);}
  845. {$ifndef newra}
  846. location_release(exprasmlist,right.location);
  847. location_freetemp(exprasmlist,right.location);
  848. {$endif newra}
  849. end;
  850. { Need to remove the parameters from the stack? }
  851. if (po_clearstack in procdefinition.procoptions) then
  852. begin
  853. { the old pop_size was already included in pushedparasize }
  854. pop_size:=pushedparasize;
  855. { for Cdecl functions we don't need to pop the funcret when it
  856. was pushed by para }
  857. if paramanager.ret_in_param(procdefinition.rettype.def,procdefinition.proccalloption) then
  858. dec(pop_size,POINTER_SIZE);
  859. end;
  860. { Remove parameters/alignment from the stack }
  861. if pop_size>0 then
  862. pop_parasize(pop_size);
  863. {$ifdef powerpc}
  864. { this calculation must be done in pass_1 anyway, so don't worry }
  865. if tppcprocinfo(current_procinfo).maxpushedparasize<pushedparasize then
  866. tppcprocinfo(current_procinfo).maxpushedparasize:=pushedparasize;
  867. {$endif powerpc}
  868. { Restore }
  869. pushedparasize:=oldpushedparasize;
  870. rg.restoreunusedstate(unusedstate);
  871. {$ifdef TEMPREGDEBUG}
  872. testregisters32;
  873. {$endif TEMPREGDEBUG}
  874. {$ifdef newra}
  875. regs_to_free:=regs_to_alloc;
  876. exclude(regs_to_alloc,RS_STACK_POINTER_REG);
  877. if (not is_void(resulttype.def)) and
  878. (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
  879. begin
  880. exclude(regs_to_free,RS_FUNCTION_RESULT_REG);
  881. {$ifndef cpu64bit}
  882. if resulttype.def.size>sizeof(aword) then
  883. exclude(regs_to_free,RS_FUNCTION_RESULT64_HIGH_REG);
  884. {$endif cpu64bit}
  885. end;
  886. r.enum:=R_INTREGISTER;
  887. for i:=first_supreg to last_supreg do
  888. if i in regs_to_free then
  889. begin
  890. r.number:=i shl 8 or R_SUBWHOLE;
  891. rg.ungetregisterint(exprasmlist,r);
  892. end;
  893. {$endif}
  894. { handle function results }
  895. if (not is_void(resulttype.def)) then
  896. handle_return_value
  897. else
  898. location_reset(location,LOC_VOID,OS_NO);
  899. { perhaps i/o check ? }
  900. if iolabel<>nil then
  901. begin
  902. reference_reset_symbol(href,iolabel,0);
  903. cg.a_paramaddr_ref(exprasmlist,href,paramanager.getintparaloc(exprasmlist,1));
  904. cg.a_call_name(exprasmlist,'FPC_IOCHECK');
  905. paramanager.freeintparaloc(exprasmlist,1);
  906. end;
  907. { restore registers }
  908. rg.restoreusedotherregisters(exprasmlist,pushedother);
  909. {$ifndef newra}
  910. rg.restoreusedintregisters(exprasmlist,pushedint);
  911. {$endif}
  912. { release temps of paras }
  913. release_para_temps;
  914. { if return value is not used }
  915. if (not(nf_return_value_used in flags)) and (not is_void(resulttype.def)) then
  916. begin
  917. if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
  918. begin
  919. { data which must be finalized ? }
  920. if (resulttype.def.needs_inittable) then
  921. cg.g_finalize(exprasmlist,resulttype.def,location.reference,false);
  922. { release unused temp }
  923. tg.ungetiftemp(exprasmlist,location.reference)
  924. end
  925. else if location.loc=LOC_FPUREGISTER then
  926. begin
  927. {$ifdef x86}
  928. { release FPU stack }
  929. accreg.enum:=FPU_RESULT_REG;
  930. emit_reg(A_FSTP,S_NO,accreg);
  931. {
  932. dec(trgcpu(rg).fpuvaroffset);
  933. do NOT decrement as the increment before
  934. is not called for unused results PM }
  935. {$endif x86}
  936. end;
  937. end;
  938. end;
  939. procedure tcgcallnode.inlined_pass_2;
  940. var
  941. regs_to_push_int : Tsupregset;
  942. regs_to_push_other : tregisterset;
  943. unusedstate: pointer;
  944. pushedother : tpushedsavedother;
  945. {$ifndef newra}
  946. pushedint : tpushedsavedint;
  947. {$endif}
  948. oldpushedparasize : longint;
  949. { adress returned from an I/O-error }
  950. iolabel : tasmlabel;
  951. { help reference pointer }
  952. href : treference;
  953. pushedregs : tmaybesave;
  954. accreg : tregister;
  955. oldaktcallnode : tcallnode;
  956. oldprocdef : tprocdef;
  957. i : longint;
  958. oldprocinfo : tprocinfo;
  959. oldinlining_procedure : boolean;
  960. inlineentrycode,inlineexitcode : TAAsmoutput;
  961. oldexitlabel:tasmlabel;
  962. oldregstate: pointer;
  963. old_local_fixup,
  964. old_para_fixup : longint;
  965. pararef,
  966. localsref : treference;
  967. {$ifdef GDB}
  968. startlabel,endlabel : tasmlabel;
  969. pp : pchar;
  970. mangled_length : longint;
  971. {$endif GDB}
  972. begin
  973. if not(assigned(procdefinition) and (procdefinition.deftype=procdef)) then
  974. internalerror(200305262);
  975. oldinlining_procedure:=inlining_procedure;
  976. oldexitlabel:=aktexitlabel;
  977. oldprocdef:=current_procdef;
  978. oldprocinfo:=current_procinfo;
  979. objectlibrary.getlabel(aktexitlabel);
  980. { we're inlining a procedure }
  981. inlining_procedure:=true;
  982. { deallocate the registers used for the current procedure's regvars }
  983. if assigned(current_procdef.regvarinfo) then
  984. begin
  985. with pregvarinfo(current_procdef.regvarinfo)^ do
  986. for i := 1 to maxvarregs do
  987. if assigned(regvars[i]) then
  988. store_regvar(exprasmlist,regvars[i].reg);
  989. rg.saveStateForInline(oldregstate);
  990. { make sure the register allocator knows what the regvars in the }
  991. { inlined code block are (JM) }
  992. rg.resetusableregisters;
  993. rg.clearregistercount;
  994. {$ifndef newra}
  995. rg.cleartempgen;
  996. {$endif}
  997. if assigned(tprocdef(procdefinition).regvarinfo) then
  998. with pregvarinfo(tprocdef(procdefinition).regvarinfo)^ do
  999. for i := 1 to maxvarregs do
  1000. if assigned(regvars[i]) then
  1001. begin
  1002. {Fix me!!}
  1003. {tmpreg:=rg.makeregsize(regvars[i].reg,OS_INT);
  1004. rg.makeregvar(tmpreg);}
  1005. internalerror(200301232);
  1006. end;
  1007. end;
  1008. { create temp procinfo }
  1009. current_procinfo:=cprocinfo.create(nil);
  1010. current_procinfo.procdef:=tprocdef(procdefinition);
  1011. current_procdef:=current_procinfo.procdef;
  1012. { Localsymtable }
  1013. current_procdef.localst.symtablelevel:=oldprocdef.localst.symtablelevel;
  1014. if current_procdef.localst.datasize>0 then
  1015. begin
  1016. old_local_fixup:=current_procdef.localst.address_fixup;
  1017. tg.GetTemp(exprasmlist,current_procdef.localst.datasize,tt_persistent,localsref);
  1018. if tg.direction>0 then
  1019. current_procdef.localst.address_fixup:=localsref.offset
  1020. else
  1021. current_procdef.localst.address_fixup:=localsref.offset+current_procdef.localst.datasize;
  1022. {$ifdef extdebug}
  1023. Comment(V_debug,'inlined local symtable ('+tostr(current_procdef.localst.datasize)+' bytes) is at offset '+tostr(current_procdef.localst.address_fixup));
  1024. exprasmList.concat(tai_comment.Create(strpnew(
  1025. 'inlined local symtable ('+tostr(current_procdef.localst.datasize)+' bytes) is at offset '+tostr(current_procdef.localst.address_fixup))));
  1026. {$endif extdebug}
  1027. end;
  1028. { Parasymtable }
  1029. current_procdef.parast.symtablelevel:=oldprocdef.localst.symtablelevel;
  1030. if current_procdef.parast.datasize>0 then
  1031. begin
  1032. old_para_fixup:=current_procdef.parast.address_fixup;
  1033. tg.GetTemp(exprasmlist,current_procdef.parast.datasize,tt_persistent,pararef);
  1034. current_procdef.parast.address_fixup:=pararef.offset;
  1035. {$ifdef extdebug}
  1036. Comment(V_debug,'inlined para symtable ('+tostr(current_procdef.parast.datasize)+' bytes) is at offset '+tostr(current_procdef.parast.address_fixup));
  1037. exprasmList.concat(tai_comment.Create(strpnew(
  1038. 'inlined para symtable ('+tostr(current_procdef.parast.datasize)+' bytes) is at offset '+tostr(current_procdef.parast.address_fixup))));
  1039. {$endif extdebug}
  1040. end;
  1041. { Calculate offsets }
  1042. current_procinfo.after_header;
  1043. exprasmList.concat(Tai_Marker.Create(InlineStart));
  1044. {$ifdef extdebug}
  1045. exprasmList.concat(tai_comment.Create(strpnew('Start of inlined proc')));
  1046. {$endif extdebug}
  1047. {$ifdef GDB}
  1048. if (cs_debuginfo in aktmoduleswitches) then
  1049. begin
  1050. objectlibrary.getaddrlabel(startlabel);
  1051. objectlibrary.getaddrlabel(endlabel);
  1052. cg.a_label(exprasmlist,startlabel);
  1053. tprocdef(procdefinition).localst.symtabletype:=inlinelocalsymtable;
  1054. procdefinition.parast.symtabletype:=inlineparasymtable;
  1055. { Here we must include the para and local symtable info }
  1056. procdefinition.concatstabto(withdebuglist);
  1057. { set it back for safety }
  1058. tprocdef(procdefinition).localst.symtabletype:=localsymtable;
  1059. procdefinition.parast.symtabletype:=parasymtable;
  1060. mangled_length:=length(oldprocdef.mangledname);
  1061. getmem(pp,mangled_length+50);
  1062. strpcopy(pp,'192,0,0,'+startlabel.name);
  1063. if (target_info.use_function_relative_addresses) then
  1064. begin
  1065. strpcopy(strend(pp),'-');
  1066. strpcopy(strend(pp),oldprocdef.mangledname);
  1067. end;
  1068. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  1069. end;
  1070. {$endif GDB}
  1071. iolabel:=nil;
  1072. rg.saveunusedstate(unusedstate);
  1073. { if we allocate the temp. location for ansi- or widestrings }
  1074. { already here, we avoid later a push/pop }
  1075. if is_widestring(resulttype.def) then
  1076. begin
  1077. tg.GetTemp(exprasmlist,pointer_size,tt_widestring,refcountedtemp);
  1078. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
  1079. end
  1080. else if is_ansistring(resulttype.def) then
  1081. begin
  1082. tg.GetTemp(exprasmlist,pointer_size,tt_ansistring,refcountedtemp);
  1083. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
  1084. end;
  1085. if (cs_check_io in aktlocalswitches) and
  1086. (po_iocheck in procdefinition.procoptions) and
  1087. not(po_iocheck in current_procdef.procoptions) then
  1088. begin
  1089. objectlibrary.getaddrlabel(iolabel);
  1090. cg.a_label(exprasmlist,iolabel);
  1091. end
  1092. else
  1093. iolabel:=nil;
  1094. { save all used registers and possible registers
  1095. used for the return value }
  1096. regs_to_push_int := tprocdef(procdefinition).usedintregisters;
  1097. regs_to_push_other := tprocdef(procdefinition).usedotherregisters;
  1098. if (not is_void(resulttype.def)) and
  1099. (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
  1100. begin
  1101. include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
  1102. {$ifndef cpu64bit}
  1103. if resulttype.def.size>sizeof(aword) then
  1104. begin
  1105. include(regs_to_push_int,RS_FUNCTION_RESULT64_LOW_REG);
  1106. include(regs_to_push_int,RS_FUNCTION_RESULT64_HIGH_REG);
  1107. end
  1108. else
  1109. {$endif cpu64bit}
  1110. include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
  1111. end;
  1112. {$ifndef newra}
  1113. rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
  1114. {$endif}
  1115. rg.saveusedotherregisters(exprasmlist,pushedother,regs_to_push_other);
  1116. {$ifdef i386}
  1117. { give used registers through }
  1118. rg.usedintinproc:=rg.usedintinproc + tprocdef(procdefinition).usedintregisters;
  1119. rg.usedinproc:=rg.usedinproc + tprocdef(procdefinition).usedotherregisters;
  1120. {$endif i386}
  1121. { Initialize for pushing the parameters }
  1122. oldpushedparasize:=pushedparasize;
  1123. pushedparasize:=0;
  1124. { Push parameters }
  1125. oldaktcallnode:=aktcallnode;
  1126. aktcallnode:=self;
  1127. if assigned(left) then
  1128. begin
  1129. {$ifndef newra}
  1130. if assigned(right) then
  1131. maybe_save(exprasmlist,left.registers32,right.location,pushedregs)
  1132. else
  1133. if assigned(methodpointer) then
  1134. maybe_save(exprasmlist,left.registers32,methodpointer.location,pushedregs);
  1135. {$endif}
  1136. { we push from right to left, so start with parameters at the end of
  1137. the parameter block }
  1138. tcallparanode(left).secondcallparan(
  1139. (po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
  1140. 0,procdefinition.parast.address_fixup+procdefinition.parast.datasize);
  1141. {$ifndef newra}
  1142. if assigned(right) then
  1143. maybe_restore(exprasmlist,right.location,pushedregs)
  1144. else
  1145. if assigned(methodpointer) then
  1146. maybe_restore(exprasmlist,methodpointer.location,pushedregs);
  1147. {$endif newra}
  1148. end;
  1149. aktcallnode:=oldaktcallnode;
  1150. {$ifndef newra}
  1151. rg.saveintregvars(exprasmlist,regs_to_push_int);
  1152. {$endif}
  1153. rg.saveotherregvars(exprasmlist,regs_to_push_other);
  1154. { takes care of local data initialization }
  1155. inlineentrycode:=TAAsmoutput.Create;
  1156. inlineexitcode:=TAAsmoutput.Create;
  1157. geninlineentrycode(inlineentrycode,0);
  1158. if po_assembler in current_procdef.procoptions then
  1159. inlineentrycode.insert(Tai_marker.Create(asmblockstart));
  1160. exprasmList.concatlist(inlineentrycode);
  1161. { process the inline code }
  1162. secondpass(inlinecode);
  1163. {$ifdef powerpc}
  1164. { this calculation must be done in pass_1 anyway, so don't worry }
  1165. if tppcprocinfo(current_procinfo).maxpushedparasize<pushedparasize then
  1166. tppcprocinfo(current_procinfo).maxpushedparasize:=pushedparasize;
  1167. {$endif powerpc}
  1168. { Restore }
  1169. pushedparasize:=oldpushedparasize;
  1170. rg.restoreunusedstate(unusedstate);
  1171. {$ifdef TEMPREGDEBUG}
  1172. testregisters32;
  1173. {$endif TEMPREGDEBUG}
  1174. geninlineexitcode(inlineexitcode,true);
  1175. if po_assembler in current_procdef.procoptions then
  1176. inlineexitcode.concat(Tai_marker.Create(asmblockend));
  1177. exprasmList.concatlist(inlineexitcode);
  1178. inlineentrycode.free;
  1179. inlineexitcode.free;
  1180. {$ifdef extdebug}
  1181. exprasmList.concat(tai_comment.Create(strpnew('End of inlined proc')));
  1182. {$endif extdebug}
  1183. exprasmList.concat(Tai_Marker.Create(InlineEnd));
  1184. {we can free the local data now, reset also the fixup address }
  1185. if current_procdef.localst.datasize>0 then
  1186. begin
  1187. tg.UnGetTemp(exprasmlist,localsref);
  1188. current_procdef.localst.address_fixup:=old_local_fixup;
  1189. end;
  1190. {we can free the para data now, reset also the fixup address }
  1191. if current_procdef.parast.datasize>0 then
  1192. begin
  1193. tg.UnGetTemp(exprasmlist,pararef);
  1194. current_procdef.parast.address_fixup:=old_para_fixup;
  1195. end;
  1196. { free return reference }
  1197. if (resulttype.def.size>0) then
  1198. begin
  1199. { from now on the result can be freed normally }
  1200. // if assigned(funcretnode) and
  1201. // paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
  1202. // tg.ChangeTempType(exprasmlist,funcretnode.location.reference,tt_normal);
  1203. end;
  1204. { handle function results }
  1205. if (not is_void(resulttype.def)) then
  1206. handle_return_value
  1207. else
  1208. location_reset(location,LOC_VOID,OS_NO);
  1209. { perhaps i/o check ? }
  1210. if iolabel<>nil then
  1211. begin
  1212. reference_reset_symbol(href,iolabel,0);
  1213. cg.a_paramaddr_ref(exprasmlist,href,paramanager.getintparaloc(exprasmlist,1));
  1214. cg.a_call_name(exprasmlist,'FPC_IOCHECK');
  1215. paramanager.freeintparaloc(exprasmlist,1);
  1216. end;
  1217. { restore registers }
  1218. rg.restoreusedotherregisters(exprasmlist,pushedother);
  1219. {$ifndef newra}
  1220. rg.restoreusedintregisters(exprasmlist,pushedint);
  1221. {$endif}
  1222. { release temps of paras }
  1223. release_para_temps;
  1224. { if return value is not used }
  1225. if (not is_void(resulttype.def)) and
  1226. (not(nf_return_value_used in flags)) then
  1227. begin
  1228. if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
  1229. begin
  1230. { data which must be finalized ? }
  1231. if (resulttype.def.needs_inittable) then
  1232. cg.g_finalize(exprasmlist,resulttype.def,location.reference,false);
  1233. { release unused temp }
  1234. tg.ungetiftemp(exprasmlist,location.reference)
  1235. end
  1236. else if location.loc=LOC_FPUREGISTER then
  1237. begin
  1238. {$ifdef x86}
  1239. { release FPU stack }
  1240. accreg.enum:=FPU_RESULT_REG;
  1241. emit_reg(A_FSTP,S_NO,accreg);
  1242. {
  1243. dec(trgcpu(rg).fpuvaroffset);
  1244. do NOT decrement as the increment before
  1245. is not called for unused results PM }
  1246. {$endif x86}
  1247. end;
  1248. end;
  1249. { release procinfo }
  1250. current_procinfo.free;
  1251. current_procinfo:=oldprocinfo;
  1252. {$ifdef GDB}
  1253. if (cs_debuginfo in aktmoduleswitches) then
  1254. begin
  1255. cg.a_label(exprasmlist,endlabel);
  1256. strpcopy(pp,'224,0,0,'+endlabel.name);
  1257. if (target_info.use_function_relative_addresses) then
  1258. begin
  1259. strpcopy(strend(pp),'-');
  1260. strpcopy(strend(pp),oldprocdef.mangledname);
  1261. end;
  1262. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  1263. freemem(pp,mangled_length+50);
  1264. end;
  1265. {$endif GDB}
  1266. { restore }
  1267. current_procdef:=oldprocdef;
  1268. aktexitlabel:=oldexitlabel;
  1269. inlining_procedure:=oldinlining_procedure;
  1270. { reallocate the registers used for the current procedure's regvars, }
  1271. { since they may have been used and then deallocated in the inlined }
  1272. { procedure (JM) }
  1273. if assigned(current_procdef.regvarinfo) then
  1274. rg.restoreStateAfterInline(oldregstate);
  1275. end;
  1276. procedure tcgcallnode.pass_2;
  1277. begin
  1278. if assigned(inlinecode) then
  1279. inlined_pass_2
  1280. else
  1281. normal_pass_2;
  1282. end;
  1283. begin
  1284. ccallparanode:=tcgcallparanode;
  1285. ccallnode:=tcgcallnode;
  1286. end.
  1287. {
  1288. $Log$
  1289. Revision 1.88 2003-06-08 20:01:53 jonas
  1290. * optimized assignments with on the right side a function that returns
  1291. an ansi- or widestring
  1292. Revision 1.87 2003/06/08 18:21:47 jonas
  1293. * fixed weird error in the copyleft statement :)
  1294. Revision 1.86 2003/06/07 18:57:04 jonas
  1295. + added freeintparaloc
  1296. * ppc get/freeintparaloc now check whether the parameter regs are
  1297. properly allocated/deallocated (and get an extra list para)
  1298. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  1299. * fixed lot of missing pi_do_call's
  1300. Revision 1.85 2003/06/04 06:43:36 jonas
  1301. * fixed double secondpassing of procvar loads
  1302. Revision 1.84 2003/06/03 21:11:09 peter
  1303. * cg.a_load_* get a from and to size specifier
  1304. * makeregsize only accepts newregister
  1305. * i386 uses generic tcgnotnode,tcgunaryminus
  1306. Revision 1.83 2003/06/03 20:27:02 daniel
  1307. * Restored original methodpointer code for non newra case
  1308. Revision 1.82 2003/06/03 13:01:59 daniel
  1309. * Register allocator finished
  1310. Revision 1.81 2003/06/01 21:38:06 peter
  1311. * getregisterfpu size parameter added
  1312. * op_const_reg size parameter added
  1313. * sparc updates
  1314. Revision 1.80 2003/05/31 15:05:28 peter
  1315. * FUNCTION_RESULT64_LOW/HIGH_REG added for int64 results
  1316. Revision 1.79 2003/05/31 00:59:44 peter
  1317. * typo in FUNCTION_RESULT_REG
  1318. Revision 1.78 2003/05/30 23:57:08 peter
  1319. * more sparc cleanup
  1320. * accumulator removed, splitted in function_return_reg (called) and
  1321. function_result_reg (caller)
  1322. Revision 1.77 2003/05/29 10:05:40 jonas
  1323. * free callparatemps created for call-by-reference parameters
  1324. Revision 1.76 2003/05/28 23:58:18 jonas
  1325. * added missing initialization of rg.usedintin,byproc
  1326. * ppc now also saves/restores used fpu registers
  1327. * ncgcal doesn't add used registers to usedby/inproc anymore, except for
  1328. i386
  1329. Revision 1.75 2003/05/26 21:17:17 peter
  1330. * procinlinenode removed
  1331. * aktexit2label removed, fast exit removed
  1332. + tcallnode.inlined_pass_2 added
  1333. Revision 1.74 2003/05/25 11:34:17 peter
  1334. * methodpointer self pushing fixed
  1335. Revision 1.73 2003/05/25 08:59:16 peter
  1336. * inline fixes
  1337. Revision 1.72 2003/05/24 13:36:54 jonas
  1338. * save fpu results in a normal fpu register on non-x86 processors
  1339. Revision 1.71 2003/05/23 19:35:50 jonas
  1340. - undid previous commit, it was wrong
  1341. Revision 1.70 2003/05/23 19:11:58 jonas
  1342. * fixed tests for whether a certain int register is unused
  1343. Revision 1.69 2003/05/23 18:01:56 jonas
  1344. * fixed ppc compiler
  1345. Revision 1.68 2003/05/23 14:27:35 peter
  1346. * remove some unit dependencies
  1347. * current_procinfo changes to store more info
  1348. Revision 1.67 2003/05/17 13:30:08 jonas
  1349. * changed tt_persistant to tt_persistent :)
  1350. * tempcreatenode now doesn't accept a boolean anymore for persistent
  1351. temps, but a ttemptype, so you can also create ansistring temps etc
  1352. Revision 1.66 2003/05/16 14:33:31 peter
  1353. * regvar fixes
  1354. Revision 1.65 2003/05/15 18:58:53 peter
  1355. * removed selfpointer_offset, vmtpointer_offset
  1356. * tvarsym.adjusted_address
  1357. * address in localsymtable is now in the real direction
  1358. * removed some obsolete globals
  1359. Revision 1.64 2003/05/14 19:36:54 jonas
  1360. * patch from Peter for int64 function results
  1361. Revision 1.63 2003/05/13 19:14:41 peter
  1362. * failn removed
  1363. * inherited result code check moven to pexpr
  1364. Revision 1.62 2003/05/13 15:18:18 peter
  1365. * generate code for procvar first before pushing parameters. Made
  1366. the already existing code for powerpc available for all platforms
  1367. Revision 1.61 2003/05/12 18:17:55 jonas
  1368. * moved fpc_check_object call earlier for the ppc, so it can't destroy
  1369. already-loaded parameter registers
  1370. Revision 1.60 2003/05/11 21:48:38 jonas
  1371. * fixed procvar bug on the ppc (load procvar before loading para's,
  1372. because the procvar may otherwise destroy the already loaded paras)
  1373. Revision 1.59 2003/05/09 17:47:02 peter
  1374. * self moved to hidden parameter
  1375. * removed hdisposen,hnewn,selfn
  1376. Revision 1.58 2003/05/05 14:53:16 peter
  1377. * vs_hidden replaced by is_hidden boolean
  1378. Revision 1.57 2003/04/30 20:53:32 florian
  1379. * error when address of an abstract method is taken
  1380. * fixed some x86-64 problems
  1381. * merged some more x86-64 and i386 code
  1382. Revision 1.56 2003/04/29 07:28:52 michael
  1383. + Patch from peter to fix wrong pushing of ansistring function results in open array
  1384. Revision 1.55 2003/04/27 11:21:33 peter
  1385. * aktprocdef renamed to current_procdef
  1386. * procinfo renamed to current_procinfo
  1387. * procinfo will now be stored in current_module so it can be
  1388. cleaned up properly
  1389. * gen_main_procsym changed to create_main_proc and release_main_proc
  1390. to also generate a tprocinfo structure
  1391. * fixed unit implicit initfinal
  1392. Revision 1.54 2003/04/27 07:29:50 peter
  1393. * current_procdef cleanup, current_procdef is now always nil when parsing
  1394. a new procdef declaration
  1395. * aktprocsym removed
  1396. * lexlevel removed, use symtable.symtablelevel instead
  1397. * implicit init/final code uses the normal genentry/genexit
  1398. * funcret state checking updated for new funcret handling
  1399. Revision 1.53 2003/04/25 20:59:33 peter
  1400. * removed funcretn,funcretsym, function result is now in varsym
  1401. and aliases for result and function name are added using absolutesym
  1402. * vs_hidden parameter for funcret passed in parameter
  1403. * vs_hidden fixes
  1404. * writenode changed to printnode and released from extdebug
  1405. * -vp option added to generate a tree.log with the nodetree
  1406. * nicer printnode for statements, callnode
  1407. Revision 1.52 2003/04/25 08:25:26 daniel
  1408. * Ifdefs around a lot of calls to cleartempgen
  1409. * Fixed registers that are allocated but not freed in several nodes
  1410. * Tweak to register allocator to cause less spills
  1411. * 8-bit registers now interfere with esi,edi and ebp
  1412. Compiler can now compile rtl successfully when using new register
  1413. allocator
  1414. Revision 1.51 2003/04/22 23:50:22 peter
  1415. * firstpass uses expectloc
  1416. * checks if there are differences between the expectloc and
  1417. location.loc from secondpass in EXTDEBUG
  1418. Revision 1.50 2003/04/22 14:33:38 peter
  1419. * removed some notes/hints
  1420. Revision 1.49 2003/04/22 13:47:08 peter
  1421. * fixed C style array of const
  1422. * fixed C array passing
  1423. * fixed left to right with high parameters
  1424. Revision 1.48 2003/04/22 10:09:34 daniel
  1425. + Implemented the actual register allocator
  1426. + Scratch registers unavailable when new register allocator used
  1427. + maybe_save/maybe_restore unavailable when new register allocator used
  1428. Revision 1.47 2003/04/22 09:49:44 peter
  1429. * do not load self when calling a non-inherited class constructor
  1430. Revision 1.46 2003/04/21 20:03:32 peter
  1431. * forgot to copy vmtrefaddr to selfrefaddr when self=vmt
  1432. Revision 1.45 2003/04/21 13:53:16 jonas
  1433. - removed copying of all paras when secondpassing a callnode (this used
  1434. to be necessary for inlinign support, but currently the whole inlined
  1435. procedure is already copied in advance). Note that the compiler crashes
  1436. when compiling ucomplex with -dTEST_INLINE (also after fixing the
  1437. syntax errors), but that was also the case before this change.
  1438. Revision 1.44 2003/04/10 17:57:52 peter
  1439. * vs_hidden released
  1440. Revision 1.43 2003/04/06 21:11:23 olle
  1441. * changed newasmsymbol to newasmsymboldata for data symbols
  1442. Revision 1.42 2003/04/04 15:38:56 peter
  1443. * moved generic code from n386cal to ncgcal, i386 now also
  1444. uses the generic ncgcal
  1445. Revision 1.41 2003/03/28 19:16:56 peter
  1446. * generic constructor working for i386
  1447. * remove fixed self register
  1448. * esi added as address register for i386
  1449. Revision 1.40 2003/03/06 11:35:50 daniel
  1450. * Fixed internalerror 7843 issue
  1451. Revision 1.39 2003/02/19 22:00:14 daniel
  1452. * Code generator converted to new register notation
  1453. - Horribily outdated todo.txt removed
  1454. Revision 1.38 2003/02/15 22:17:38 carl
  1455. * bugfix of FPU emulation code
  1456. Revision 1.37 2003/02/12 22:10:07 carl
  1457. * load_frame_pointer is now generic
  1458. * change fpu emulation routine names
  1459. Revision 1.36 2003/01/30 21:46:57 peter
  1460. * self fixes for static methods (merged)
  1461. Revision 1.35 2003/01/22 20:45:15 mazen
  1462. * making math code in RTL compiling.
  1463. *NB : This does NOT mean necessary that it will generate correct code!
  1464. Revision 1.34 2003/01/17 12:03:45 daniel
  1465. * Optalign conditional code adapted to record Tregister
  1466. Revision 1.33 2003/01/08 18:43:56 daniel
  1467. * Tregister changed into a record
  1468. Revision 1.32 2002/12/15 22:50:00 florian
  1469. + some stuff for the new hidden parameter handling added
  1470. Revision 1.31 2002/12/15 21:30:12 florian
  1471. * tcallnode.paraitem introduced, all references to defcoll removed
  1472. Revision 1.30 2002/11/27 20:04:39 peter
  1473. * cdecl array of const fixes
  1474. Revision 1.29 2002/11/25 17:43:17 peter
  1475. * splitted defbase in defutil,symutil,defcmp
  1476. * merged isconvertable and is_equal into compare_defs(_ext)
  1477. * made operator search faster by walking the list only once
  1478. Revision 1.28 2002/11/18 17:31:54 peter
  1479. * pass proccalloption to ret_in_xxx and push_xxx functions
  1480. Revision 1.27 2002/11/16 15:34:30 florian
  1481. * generic location for float results
  1482. Revision 1.26 2002/11/15 01:58:51 peter
  1483. * merged changes from 1.0.7 up to 04-11
  1484. - -V option for generating bug report tracing
  1485. - more tracing for option parsing
  1486. - errors for cdecl and high()
  1487. - win32 import stabs
  1488. - win32 records<=8 are returned in eax:edx (turned off by default)
  1489. - heaptrc update
  1490. - more info for temp management in .s file with EXTDEBUG
  1491. Revision 1.25 2002/10/05 12:43:25 carl
  1492. * fixes for Delphi 6 compilation
  1493. (warning : Some features do not work under Delphi)
  1494. Revision 1.24 2002/09/30 07:00:45 florian
  1495. * fixes to common code to get the alpha compiler compiled applied
  1496. Revision 1.23 2002/09/17 18:54:02 jonas
  1497. * a_load_reg_reg() now has two size parameters: source and dest. This
  1498. allows some optimizations on architectures that don't encode the
  1499. register size in the register name.
  1500. Revision 1.22 2002/09/07 15:25:02 peter
  1501. * old logs removed and tabs fixed
  1502. Revision 1.21 2002/09/07 11:50:02 jonas
  1503. * fixed small regalloction info bug
  1504. Revision 1.20 2002/09/02 11:25:20 florian
  1505. * fixed generic procedure variable calling
  1506. Revision 1.19 2002/09/01 21:04:48 florian
  1507. * several powerpc related stuff fixed
  1508. Revision 1.18 2002/09/01 18:43:27 peter
  1509. * include FUNCTION_RETURN_REG in regs_to_push list
  1510. Revision 1.17 2002/09/01 12:13:00 peter
  1511. * use a_call_reg
  1512. * ungetiftemp for procvar of object temp
  1513. Revision 1.16 2002/08/25 19:25:18 peter
  1514. * sym.insert_in_data removed
  1515. * symtable.insertvardata/insertconstdata added
  1516. * removed insert_in_data call from symtable.insert, it needs to be
  1517. called separatly. This allows to deref the address calculation
  1518. * procedures now calculate the parast addresses after the procedure
  1519. directives are parsed. This fixes the cdecl parast problem
  1520. * push_addr_param has an extra argument that specifies if cdecl is used
  1521. or not
  1522. Revision 1.15 2002/08/23 16:14:48 peter
  1523. * tempgen cleanup
  1524. * tt_noreuse temp type added that will be used in genentrycode
  1525. Revision 1.14 2002/08/20 16:55:38 peter
  1526. * don't write (stabs)line info when inlining a procedure
  1527. Revision 1.13 2002/08/19 19:36:42 peter
  1528. * More fixes for cross unit inlining, all tnodes are now implemented
  1529. * Moved pocall_internconst to po_internconst because it is not a
  1530. calling type at all and it conflicted when inlining of these small
  1531. functions was requested
  1532. Revision 1.12 2002/08/18 20:06:23 peter
  1533. * inlining is now also allowed in interface
  1534. * renamed write/load to ppuwrite/ppuload
  1535. * tnode storing in ppu
  1536. * nld,ncon,nbas are already updated for storing in ppu
  1537. Revision 1.11 2002/08/17 22:09:44 florian
  1538. * result type handling in tcgcal.pass_2 overhauled
  1539. * better tnode.dowrite
  1540. * some ppc stuff fixed
  1541. Revision 1.10 2002/08/17 09:23:35 florian
  1542. * first part of procinfo rewrite
  1543. Revision 1.9 2002/08/13 21:40:55 florian
  1544. * more fixes for ppc calling conventions
  1545. Revision 1.8 2002/08/13 18:01:51 carl
  1546. * rename swatoperands to swapoperands
  1547. + m68k first compilable version (still needs a lot of testing):
  1548. assembler generator, system information , inline
  1549. assembler reader.
  1550. Revision 1.7 2002/08/12 15:08:39 carl
  1551. + stab register indexes for powerpc (moved from gdb to cpubase)
  1552. + tprocessor enumeration moved to cpuinfo
  1553. + linker in target_info is now a class
  1554. * many many updates for m68k (will soon start to compile)
  1555. - removed some ifdef or correct them for correct cpu
  1556. Revision 1.6 2002/08/11 14:32:26 peter
  1557. * renamed current_library to objectlibrary
  1558. Revision 1.5 2002/08/11 13:24:11 peter
  1559. * saving of asmsymbols in ppu supported
  1560. * asmsymbollist global is removed and moved into a new class
  1561. tasmlibrarydata that will hold the info of a .a file which
  1562. corresponds with a single module. Added librarydata to tmodule
  1563. to keep the library info stored for the module. In the future the
  1564. objectfiles will also be stored to the tasmlibrarydata class
  1565. * all getlabel/newasmsymbol and friends are moved to the new class
  1566. Revision 1.4 2002/08/06 20:55:20 florian
  1567. * first part of ppc calling conventions fix
  1568. Revision 1.3 2002/07/20 11:57:53 florian
  1569. * types.pas renamed to defbase.pas because D6 contains a types
  1570. unit so this would conflicts if D6 programms are compiled
  1571. + Willamette/SSE2 instructions to assembler added
  1572. Revision 1.2 2002/07/13 19:38:43 florian
  1573. * some more generic calling stuff fixed
  1574. }