ncgcal.pas 80 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826
  1. {
  2. Id: ncgcal.pas,v 1.10 2002/08/17 09:23:35 florian Exp $
  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 bymethodpointer
  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. protected
  33. funcretref : treference;
  34. refcountedtemp : treference;
  35. procedure handle_return_value(inlined,extended_new:boolean);
  36. {# This routine is used to push the current frame pointer
  37. on the stack. This is used in nested routines where the
  38. value of the frame pointer is always pushed as an extra
  39. parameter.
  40. The default handling is the standard handling used on
  41. most stack based machines, where the frame pointer is
  42. the first invisible parameter.
  43. }
  44. procedure load_framepointer;virtual;
  45. procedure extra_interrupt_code;virtual;
  46. public
  47. procedure pass_2;override;
  48. end;
  49. tcgprocinlinenode = class(tprocinlinenode)
  50. procedure pass_2;override;
  51. end;
  52. implementation
  53. uses
  54. systems,
  55. cutils,verbose,globals,
  56. symconst,symbase,symsym,symtable,defutil,paramgr,
  57. {$ifdef GDB}
  58. {$ifdef delphi}
  59. sysutils,
  60. {$else}
  61. strings,
  62. {$endif}
  63. gdb,
  64. {$endif GDB}
  65. cginfo,cgbase,pass_2,
  66. cpuinfo,cpupi,aasmbase,aasmtai,aasmcpu,
  67. nmem,nld,ncnv,
  68. {$ifdef i386}
  69. cga,
  70. {$endif i386}
  71. cg64f32,ncgutil,cgobj,tgobj,regvars,rgobj,rgcpu,cgcpu;
  72. {*****************************************************************************
  73. TCGCALLPARANODE
  74. *****************************************************************************}
  75. procedure tcgcallparanode.secondcallparan(push_from_left_to_right:boolean;calloption:tproccalloption;para_alignment,para_offset : longint);
  76. {$ifndef VS_HIDDEN}
  77. { goes to pass 1 }
  78. procedure maybe_push_high;
  79. begin
  80. { open array ? }
  81. { defcoll.data can be nil for read/write }
  82. if assigned(paraitem.paratype.def) and
  83. assigned(hightree) then
  84. begin
  85. secondpass(hightree);
  86. { this is a longint anyway ! }
  87. push_value_para(hightree,calloption,para_offset,4,paraitem.paraloc);
  88. end;
  89. end;
  90. {$endif VS_HIDDEN}
  91. var
  92. otlabel,oflabel : tasmlabel;
  93. { temporary variables: }
  94. tempdeftype : tdeftype;
  95. tmpreg : tregister;
  96. href : treference;
  97. begin
  98. { push from left to right if specified }
  99. if push_from_left_to_right and assigned(right) then
  100. begin
  101. if (nf_varargs_para in flags) then
  102. tcallparanode(right).secondcallparan(push_from_left_to_right,
  103. calloption,para_alignment,para_offset)
  104. else
  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,4);
  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(left,calloption,para_offset,para_alignment,paraitem.paraloc);
  124. end
  125. { filter array constructor with c styled args }
  126. else if is_array_constructor(left.resulttype.def) and (nf_cargs in left.flags) then
  127. begin
  128. { nothing, everything is already pushed }
  129. end
  130. { in codegen.handleread.. paraitem.data is set to nil }
  131. else if assigned(paraitem.paratype.def) and
  132. (paraitem.paratype.def.deftype=formaldef) then
  133. begin
  134. { allow passing of a constant to a const formaldef }
  135. if (paraitem.paratyp=vs_const) and
  136. (left.location.loc=LOC_CONSTANT) then
  137. location_force_mem(exprasmlist,left.location);
  138. { allow @var }
  139. inc(pushedparasize,4);
  140. if (left.nodetype=addrn) and
  141. (not(nf_procvarload in left.flags)) then
  142. begin
  143. if calloption=pocall_inline then
  144. begin
  145. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  146. cg.a_load_loc_ref(exprasmlist,left.location,href);
  147. end
  148. else
  149. cg.a_param_loc(exprasmlist,left.location,paraitem.paraloc);
  150. location_release(exprasmlist,left.location);
  151. end
  152. else
  153. begin
  154. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  155. begin
  156. CGMessage(type_e_mismatch)
  157. end
  158. else
  159. begin
  160. if calloption=pocall_inline then
  161. begin
  162. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  163. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
  164. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  165. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
  166. cg.free_scratch_reg(exprasmlist,tmpreg);
  167. end
  168. else
  169. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
  170. location_release(exprasmlist,left.location);
  171. end;
  172. end;
  173. end
  174. { handle call by reference parameter }
  175. else if (paraitem.paratyp in [vs_var,vs_out]) then
  176. begin
  177. if (left.location.loc<>LOC_REFERENCE) then
  178. begin
  179. { passing self to a var parameter is allowed in
  180. TP and delphi }
  181. if not((left.location.loc=LOC_CREFERENCE) and
  182. (left.nodetype=selfn)) then
  183. internalerror(200106041);
  184. end;
  185. {$ifdef unused}
  186. if not push_from_left_to_right then
  187. {$endif unused}
  188. {$ifndef VS_HIDDEN}
  189. maybe_push_high;
  190. {$endif VS_HIDDEN}
  191. if (paraitem.paratyp=vs_out) and
  192. assigned(paraitem.paratype.def) and
  193. not is_class(paraitem.paratype.def) and
  194. paraitem.paratype.def.needs_inittable then
  195. cg.g_finalize(exprasmlist,paraitem.paratype.def,left.location.reference,false);
  196. inc(pushedparasize,4);
  197. if calloption=pocall_inline then
  198. begin
  199. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  200. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
  201. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  202. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
  203. cg.free_scratch_reg(exprasmlist,tmpreg);
  204. end
  205. else
  206. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
  207. location_release(exprasmlist,left.location);
  208. {$ifdef unused}
  209. if push_from_left_to_right then
  210. maybe_push_high;
  211. {$endif unused}
  212. end
  213. else
  214. begin
  215. tempdeftype:=resulttype.def.deftype;
  216. if tempdeftype=filedef then
  217. CGMessage(cg_e_file_must_call_by_reference);
  218. { open array must always push the address, this is needed to
  219. also push addr of small open arrays and with cdecl functions (PFV) }
  220. if (
  221. assigned(paraitem.paratype.def) and
  222. (is_open_array(paraitem.paratype.def) or
  223. is_array_of_const(paraitem.paratype.def))
  224. ) or
  225. (
  226. paramanager.push_addr_param(resulttype.def,calloption)
  227. ) then
  228. begin
  229. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  230. begin
  231. { allow passing nil to a procvardef (methodpointer) }
  232. (* if (left.nodetype=typeconvn) and
  233. (left.resulttype.def.deftype=procvardef) and
  234. (ttypeconvnode(left).left.nodetype=niln) then
  235. *)
  236. if (left.location.size <> OS_NO) then
  237. begin
  238. tg.GetTemp(exprasmlist,tcgsize2size[left.location.size],tt_normal,href);
  239. if not (left.location.size in [OS_64,OS_S64]) then
  240. cg.a_load_loc_ref(exprasmlist,left.location,href)
  241. else
  242. cg64.a_load64_loc_ref(exprasmlist,left.location,href);
  243. location_reset(left.location,LOC_REFERENCE,left.location.size);
  244. left.location.reference:=href;
  245. end
  246. else
  247. internalerror(200204011);
  248. end;
  249. {$ifdef unused}
  250. if not push_from_left_to_right then
  251. {$endif unused}
  252. {$ifndef VS_HIDDEN}
  253. maybe_push_high;
  254. {$endif VS_HIDDEN}
  255. inc(pushedparasize,4);
  256. if calloption=pocall_inline then
  257. begin
  258. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  259. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
  260. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  261. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
  262. cg.free_scratch_reg(exprasmlist,tmpreg);
  263. end
  264. else
  265. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
  266. location_release(exprasmlist,left.location);
  267. {$ifdef unused}
  268. if push_from_left_to_right then
  269. maybe_push_high;
  270. {$endif unused}
  271. end
  272. else
  273. begin
  274. push_value_para(left,calloption,
  275. para_offset,para_alignment,paraitem.paraloc);
  276. end;
  277. end;
  278. truelabel:=otlabel;
  279. falselabel:=oflabel;
  280. { push from right to left }
  281. if not push_from_left_to_right and assigned(right) then
  282. begin
  283. if (nf_varargs_para in flags) then
  284. tcallparanode(right).secondcallparan(push_from_left_to_right,
  285. calloption,para_alignment,para_offset)
  286. else
  287. tcallparanode(right).secondcallparan(push_from_left_to_right,
  288. calloption,para_alignment,para_offset);
  289. end;
  290. end;
  291. {*****************************************************************************
  292. TCGCALLNODE
  293. *****************************************************************************}
  294. procedure tcgcallnode.extra_interrupt_code;
  295. var r:Tregister;
  296. begin
  297. {$ifdef i386}
  298. { if the i386 ever uses tcgcal, we've to move this into an overriden method }
  299. emit_none(A_PUSHF,S_L);
  300. r.enum:=R_CS;
  301. emit_reg(A_PUSH,S_L,r);
  302. {$endif i386}
  303. end;
  304. procedure tcgcallnode.load_framepointer;
  305. var href : treference;
  306. hregister : tregister;
  307. i: integer;
  308. begin
  309. { this routine is itself not nested }
  310. if lexlevel=(tprocdef(procdefinition).parast.symtablelevel) then
  311. begin
  312. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  313. cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1));
  314. end
  315. { one nesting level }
  316. else if (lexlevel=(tprocdef(procdefinition).parast.symtablelevel)-1) then
  317. begin
  318. cg.a_param_reg(exprasmlist,OS_ADDR,procinfo.framepointer,paramanager.getintparaloc(1));
  319. end
  320. { very complex nesting level ... }
  321. else if (lexlevel>(tprocdef(procdefinition).parast.symtablelevel)) then
  322. begin
  323. hregister:=rg.getaddressregister(exprasmlist);
  324. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  325. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  326. for i:=(tprocdef(procdefinition).parast.symtablelevel) to lexlevel-1 do
  327. begin
  328. reference_reset_base(href,hregister,procinfo.framepointer_offset);
  329. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  330. end;
  331. cg.a_param_reg(exprasmlist,OS_ADDR,hregister,paramanager.getintparaloc(1));
  332. rg.ungetaddressregister(exprasmlist,hregister);
  333. end;
  334. end;
  335. procedure tcgcallnode.handle_return_value(inlined,extended_new:boolean);
  336. var
  337. cgsize : tcgsize;
  338. r,hregister : tregister;
  339. nr:Tnewregister;
  340. begin
  341. { structured results are easy to handle.... }
  342. { needed also when result_no_used !! }
  343. if paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
  344. begin
  345. location_reset(location,LOC_CREFERENCE,def_cgsize(resulttype.def));
  346. location.reference.symbol:=nil;
  347. location.reference:=funcretref;
  348. end
  349. else
  350. { ansi/widestrings must be registered, so we can dispose them }
  351. if is_ansistring(resulttype.def) or
  352. is_widestring(resulttype.def) then
  353. begin
  354. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  355. location.reference:=refcountedtemp;
  356. r.enum:=accumulator;
  357. cg.a_reg_alloc(exprasmlist,r);
  358. cg.a_load_reg_ref(exprasmlist,OS_ADDR,r,location.reference);
  359. cg.a_reg_dealloc(exprasmlist,r);
  360. end
  361. else
  362. { we have only to handle the result if it is used }
  363. if (nf_return_value_used in flags) then
  364. begin
  365. case resulttype.def.deftype of
  366. enumdef,
  367. orddef :
  368. begin
  369. cgsize:=def_cgsize(resulttype.def);
  370. { an object constructor is a function with boolean result }
  371. if (inlined or (right=nil)) and
  372. (procdefinition.proctypeoption=potype_constructor) then
  373. begin
  374. {$ifdef x86}
  375. if extended_new then
  376. cgsize:=OS_INT
  377. else
  378. begin
  379. cgsize:=OS_NO;
  380. { this fails if popsize > 0 PM }
  381. location_reset(location,LOC_FLAGS,OS_NO);
  382. location.resflags:=F_NE;
  383. end;
  384. {$else x86}
  385. cgsize:=OS_INT
  386. {$endif x86}
  387. end;
  388. if cgsize<>OS_NO then
  389. begin
  390. location_reset(location,LOC_REGISTER,cgsize);
  391. {$ifndef cpu64bit}
  392. if cgsize in [OS_64,OS_S64] then
  393. begin
  394. {Move the function result to free registers, preferably the
  395. accumulator/accumulatorhigh, so no move is necessary.}
  396. r.enum:=R_INTREGISTER;
  397. r.number:=NR_ACCUMULATOR;
  398. hregister.enum:=R_INTREGISTER;
  399. hregister.number:=NR_ACCUMULATORHIGH;
  400. cg.a_reg_alloc(exprasmlist,r);
  401. cg.a_reg_alloc(exprasmlist,hregister);
  402. if RS_ACCUMULATOR in rg.unusedregsint then
  403. location.registerlow:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR)
  404. else
  405. location.registerlow:=rg.getregisterint(exprasmlist,OS_INT);
  406. if RS_ACCUMULATORHIGH in rg.unusedregsint then
  407. location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH)
  408. else
  409. location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
  410. cg64.a_load64_reg_reg(exprasmlist,joinreg64(r,hregister),
  411. location.register64);
  412. end
  413. else
  414. {$endif cpu64bit}
  415. begin
  416. {Move the function result to a free register, preferably the
  417. accumulator, so no move is necessary.}
  418. nr:=RS_ACCUMULATOR shl 8 or cgsize2subreg(cgsize);
  419. r.enum:=R_INTREGISTER;
  420. r.number:=nr;
  421. cg.a_reg_alloc(exprasmlist,r);
  422. if RS_ACCUMULATOR in rg.unusedregsint then
  423. location.register:=rg.getexplicitregisterint(exprasmlist,nr)
  424. else
  425. location.register:=rg.getregisterint(exprasmlist,cgsize);
  426. cg.a_load_reg_reg(exprasmlist,cgsize,cgsize,r,location.register);
  427. end;
  428. end;
  429. end;
  430. floatdef :
  431. begin
  432. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  433. {$ifdef cpufpemu}
  434. if cs_fp_emulation in aktmoduleswitches then
  435. location.register.enum := accumulator
  436. else
  437. {$endif cpufpemu}
  438. location.register.enum:=fpu_result_reg;
  439. {$ifdef x86}
  440. inc(trgcpu(rg).fpuvaroffset);
  441. {$endif x86}
  442. end;
  443. {$ifdef TEST_WIN32_RECORDS}
  444. recorddef :
  445. begin
  446. if (target_info.system=system_i386_win32) then
  447. begin
  448. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  449. tg.GetTemp(exprasmlist,resulttype.size,tt_normal,location);
  450. {$ifndef cpu64bit}
  451. if cgsize in [OS_64,OS_S64] then
  452. cg64.a_load64_reg_loc(exprasmlist,joinreg64(accumulator,accumulatorhigh),location)
  453. else
  454. {$endif cpu64bit}
  455. cg.a_load_reg_loc(exprasmlist,accumulator,location);
  456. end
  457. else
  458. internalerror(200211141);
  459. end;
  460. {$endif TEST_WIN32_RECORDS}
  461. else
  462. begin
  463. location_reset(location,LOC_REGISTER,OS_INT);
  464. if RS_ACCUMULATOR in rg.unusedregsint then
  465. location.register:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR)
  466. else
  467. location.register:=rg.getregisterint(exprasmlist,OS_INT);
  468. r.enum:=R_INTREGISTER;
  469. r.number:=NR_ACCUMULATOR;
  470. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,r,location.register);
  471. end;
  472. end;
  473. end;
  474. end;
  475. procedure tcgcallnode.pass_2;
  476. var
  477. regs_to_push_int : Tsupregset;
  478. regs_to_push_other : tregisterset;
  479. unusedstate: pointer;
  480. pushed : tpushedsaved;
  481. pushedint : tpushedsavedint;
  482. tmpreg : tregister;
  483. hregister : tregister;
  484. hregister64 : tregister64;
  485. oldpushedparasize : longint;
  486. { true if ESI must be loaded again after the subroutine }
  487. loadesi : boolean;
  488. { true if a virtual method must be called directly }
  489. no_virtual_call : boolean;
  490. { true if we produce a con- or destrutor in a call }
  491. is_con_or_destructor : boolean;
  492. { true if a constructor is called again }
  493. extended_new : boolean;
  494. { adress returned from an I/O-error }
  495. iolabel : tasmlabel;
  496. { lexlevel count }
  497. i : longint;
  498. { help reference pointer }
  499. href : treference;
  500. hrefvmt : treference;
  501. hp : tnode;
  502. pp : tbinarynode;
  503. params : tnode;
  504. inlined : boolean;
  505. inlinecode : tprocinlinenode;
  506. store_parast_fixup,
  507. para_alignment,
  508. para_offset : longint;
  509. cgsize : tcgsize;
  510. { instruction for alignement correction }
  511. { corr : paicpu;}
  512. { we must pop this size also after !! }
  513. { must_pop : boolean; }
  514. pop_size : longint;
  515. {$ifdef OPTALIGN}
  516. pop_esp : boolean;
  517. push_size : longint;
  518. {$endif OPTALIGN}
  519. pop_allowed : boolean;
  520. release_tmpreg : boolean;
  521. constructorfailed : tasmlabel;
  522. resultloc : tparalocation;
  523. returnref,
  524. pararef : treference;
  525. r,r2:Tregister;
  526. label
  527. dont_call;
  528. begin
  529. extended_new:=false;
  530. iolabel:=nil;
  531. inlinecode:=nil;
  532. inlined:=false;
  533. loadesi:=true;
  534. no_virtual_call:=false;
  535. rg.saveunusedstate(unusedstate);
  536. { if we allocate the temp. location for ansi- or widestrings }
  537. { already here, we avoid later a push/pop }
  538. if is_widestring(resulttype.def) then
  539. begin
  540. tg.GetTemp(exprasmlist,pointer_size,tt_widestring,refcountedtemp);
  541. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp);
  542. end
  543. else if is_ansistring(resulttype.def) then
  544. begin
  545. tg.GetTemp(exprasmlist,pointer_size,tt_ansistring,refcountedtemp);
  546. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp);
  547. end;
  548. if (procdefinition.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_stdcall]) then
  549. para_alignment:=4
  550. else
  551. para_alignment:=aktalignment.paraalign;
  552. if not assigned(procdefinition) then
  553. exit;
  554. { Deciding whether we may still need the parameters happens next (JM) }
  555. if assigned(left) then
  556. params:=left.getcopy
  557. else
  558. params := nil;
  559. if (procdefinition.proccalloption=pocall_inline) then
  560. begin
  561. inlined:=true;
  562. inlinecode:=tprocinlinenode(right);
  563. right:=nil;
  564. { set it to the same lexical level as the local symtable, becuase
  565. the para's are stored there }
  566. tprocdef(procdefinition).parast.symtablelevel:=aktprocdef.localst.symtablelevel;
  567. if assigned(params) then
  568. begin
  569. inlinecode.para_size:=tprocdef(procdefinition).para_size(para_alignment);
  570. tg.GetTemp(exprasmlist,inlinecode.para_size,tt_persistant,pararef);
  571. inlinecode.para_offset:=pararef.offset;
  572. end;
  573. store_parast_fixup:=tprocdef(procdefinition).parast.address_fixup;
  574. tprocdef(procdefinition).parast.address_fixup:=inlinecode.para_offset;
  575. {$ifdef extdebug}
  576. Comment(V_debug,
  577. 'inlined parasymtable is at offset '
  578. +tostr(tprocdef(procdefinition).parast.address_fixup));
  579. exprasmList.concat(tai_comment.Create(
  580. strpnew('inlined parasymtable is at offset '
  581. +tostr(tprocdef(procdefinition).parast.address_fixup))));
  582. {$endif extdebug}
  583. end;
  584. { only if no proc var }
  585. if inlined or
  586. not(assigned(right)) then
  587. is_con_or_destructor:=(procdefinition.proctypeoption in [potype_constructor,potype_destructor]);
  588. { proc variables destroy all registers }
  589. if (inlined or
  590. (right=nil)) and
  591. { virtual methods too }
  592. not(po_virtualmethod in procdefinition.procoptions) then
  593. begin
  594. if (cs_check_io in aktlocalswitches) and
  595. (po_iocheck in procdefinition.procoptions) and
  596. not(po_iocheck in aktprocdef.procoptions) then
  597. begin
  598. objectlibrary.getaddrlabel(iolabel);
  599. cg.a_label(exprasmlist,iolabel);
  600. end
  601. else
  602. iolabel:=nil;
  603. { save all used registers and possible registers
  604. used for the return value }
  605. regs_to_push_int := tprocdef(procdefinition).usedintregisters;
  606. regs_to_push_other := tprocdef(procdefinition).usedotherregisters;
  607. if (not is_void(resulttype.def)) and
  608. (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
  609. begin
  610. include(regs_to_push_int,RS_ACCUMULATOR);
  611. {$ifndef cpu64bit}
  612. if resulttype.def.size>sizeof(aword) then
  613. include(regs_to_push_int,RS_ACCUMULATORHIGH);
  614. {$endif cpu64bit}
  615. end;
  616. rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
  617. rg.saveusedotherregisters(exprasmlist,pushed,regs_to_push_other);
  618. { give used registers through }
  619. rg.usedintinproc:=rg.usedintinproc + tprocdef(procdefinition).usedintregisters;
  620. rg.usedinproc:=rg.usedinproc + tprocdef(procdefinition).usedotherregisters;
  621. end
  622. else
  623. begin
  624. regs_to_push_int := all_intregisters;
  625. regs_to_push_other := all_registers;
  626. rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
  627. rg.saveusedotherregisters(exprasmlist,pushed,regs_to_push_other);
  628. rg.usedinproc:=all_registers;
  629. { no IO check for methods and procedure variables }
  630. iolabel:=nil;
  631. end;
  632. { generate the code for the parameter and push them }
  633. oldpushedparasize:=pushedparasize;
  634. pushedparasize:=0;
  635. pop_size:=0;
  636. {$ifdef dummy}
  637. { no inc esp for inlined procedure
  638. and for objects constructors PM }
  639. if inlined or
  640. ((procdefinition.proctypeoption=potype_constructor) and
  641. { quick'n'dirty check if it is a class or an object }
  642. (resulttype.def.deftype=orddef)) then
  643. pop_allowed:=false
  644. else
  645. pop_allowed:=true;
  646. if pop_allowed then
  647. begin
  648. { Old pushedsize aligned on 4 ? }
  649. i:=oldpushedparasize and 3;
  650. if i>0 then
  651. inc(pop_size,4-i);
  652. { This parasize aligned on 4 ? }
  653. i:=procdefinition.para_size(para_alignment) and 3;
  654. if i>0 then
  655. inc(pop_size,4-i);
  656. { insert the opcode and update pushedparasize }
  657. { never push 4 or more !! }
  658. pop_size:=pop_size mod 4;
  659. if pop_size>0 then
  660. begin
  661. inc(pushedparasize,pop_size);
  662. cg.a_const_reg(A_SUB,S_L,pop_size,R_ESP);
  663. {$ifdef GDB}
  664. if (cs_debuginfo in aktmoduleswitches) and
  665. (exprasmList.first=exprasmList.last) then
  666. exprasmList.concat(Tai_force_line.Create);
  667. {$endif GDB}
  668. end;
  669. end;
  670. {$endif dummy}
  671. {$ifdef OPTALIGN}
  672. if pop_allowed and (cs_align in aktglobalswitches) then
  673. begin
  674. pop_esp:=true;
  675. push_size:=procdefinition.para_size(para_alignment);
  676. { !!!! here we have to take care of return type, self
  677. and nested procedures
  678. }
  679. inc(push_size,12);
  680. r.enum:=R_ESP:
  681. r2.enum:=R_EDI;
  682. emit_reg_reg(A_MOV,S_L,r,r2);
  683. if (push_size mod 8)=0 then
  684. emit_const_reg(A_AND,S_L,$fffffff8,r)
  685. else
  686. begin
  687. emit_const_reg(A_SUB,S_L,push_size,r);
  688. emit_const_reg(A_AND,S_L,$fffffff8,r);
  689. emit_const_reg(A_SUB,S_L,push_size,r);
  690. end;
  691. emit_reg(A_PUSH,S_L,r2);
  692. end
  693. else
  694. pop_esp:=false;
  695. {$endif OPTALIGN}
  696. { Push parameters }
  697. if assigned(params) then
  698. begin
  699. { be found elsewhere }
  700. if inlined then
  701. para_offset:=tprocdef(procdefinition).parast.address_fixup+
  702. tprocdef(procdefinition).parast.datasize
  703. else
  704. para_offset:=0;
  705. if not(inlined) and
  706. assigned(right) then
  707. tcallparanode(params).secondcallparan(
  708. { TParaItem(tabstractprocdef(right.resulttype.def).Para.first), }
  709. (po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
  710. para_alignment,para_offset)
  711. else
  712. tcallparanode(params).secondcallparan(
  713. { TParaItem(procdefinition.Para.first), }
  714. (po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
  715. para_alignment,para_offset);
  716. end;
  717. { Allocate return value for inlined routines }
  718. if inlined and
  719. (resulttype.def.size>0) then
  720. begin
  721. tg.GetTemp(exprasmlist,Align(resulttype.def.size,aktalignment.paraalign),tt_persistant,returnref);
  722. inlinecode.retoffset:=returnref.offset;
  723. end;
  724. { Allocate return value when returned in argument }
  725. if paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
  726. begin
  727. if assigned(funcretrefnode) then
  728. begin
  729. secondpass(funcretrefnode);
  730. if codegenerror then
  731. exit;
  732. if (funcretrefnode.location.loc<>LOC_REFERENCE) then
  733. internalerror(200204246);
  734. funcretref:=funcretrefnode.location.reference;
  735. end
  736. else
  737. begin
  738. if inlined then
  739. begin
  740. tg.GetTemp(exprasmlist,resulttype.def.size,tt_persistant,funcretref);
  741. {$ifdef extdebug}
  742. Comment(V_debug,'function return value is at offset '
  743. +tostr(funcretref.offset));
  744. exprasmlist.concat(tai_comment.create(
  745. strpnew('function return value is at offset '
  746. +tostr(funcretref.offset))));
  747. {$endif extdebug}
  748. end
  749. else
  750. tg.GetTemp(exprasmlist,resulttype.def.size,tt_normal,funcretref);
  751. end;
  752. { This must not be counted for C code
  753. complex return address is removed from stack
  754. by function itself ! }
  755. {$ifdef OLD_C_STACK}
  756. inc(pushedparasize,4); { lets try without it PM }
  757. {$endif not OLD_C_STACK}
  758. if inlined then
  759. begin
  760. hregister:=cg.get_scratch_reg_address(exprasmlist);
  761. cg.a_loadaddr_ref_reg(exprasmlist,funcretref,hregister);
  762. reference_reset_base(href,procinfo.framepointer,inlinecode.retoffset);
  763. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
  764. cg.free_scratch_reg(exprasmlist,hregister);
  765. end
  766. else
  767. cg.a_paramaddr_ref(exprasmlist,funcretref,
  768. paramanager.getfuncretparaloc(procdefinition));
  769. end;
  770. { procedure variable or normal function call ? }
  771. if inlined or
  772. (right=nil) then
  773. begin
  774. { Normal function call }
  775. {$ifdef dummy}
  776. { overloaded operator has no symtable }
  777. { push self }
  778. if assigned(symtableproc) and
  779. (symtableproc.symtabletype=withsymtable) then
  780. begin
  781. { dirty trick to avoid the secondcall below }
  782. methodpointer:=ccallparanode.create(nil,nil);
  783. location_reset(methodpointer.location,LOC_REGISTER,OS_ADDR);
  784. rg.getexplicitregisterint(exprasmlist,R_ESI);
  785. methodpointer.location.register:=R_ESI;
  786. { ARGHHH this is wrong !!!
  787. if we can init from base class for a child
  788. class that the wrong VMT will be
  789. transfered to constructor !! }
  790. methodpointer.resulttype:=
  791. twithnode(twithsymtable(symtableproc).withnode).left.resulttype;
  792. { make a reference }
  793. href:=twithnode(twithsymtable(symtableproc).withnode).withreference;
  794. if ((not(nf_islocal in twithnode(twithsymtable(symtableproc).withnode).flags)) and
  795. (not twithsymtable(symtableproc).direct_with)) or
  796. is_class_or_interface(methodpointer.resulttype.def) then
  797. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,self_pointer_reg)
  798. else
  799. cg.a_loadaddr_ref_reg(exprasmlist,href,self_pointer_reg);
  800. end;
  801. { push self }
  802. if assigned(symtableproc) and
  803. ((symtableproc.symtabletype=objectsymtable) or
  804. (symtableproc.symtabletype=withsymtable)) then
  805. begin
  806. if assigned(methodpointer) then
  807. begin
  808. {
  809. if methodpointer^.resulttype.def=classrefdef then
  810. begin
  811. two possibilities:
  812. 1. constructor
  813. 2. class method
  814. end
  815. else }
  816. begin
  817. case methodpointer.nodetype of
  818. typen:
  819. begin
  820. { direct call to inherited method }
  821. if (po_abstractmethod in procdefinition.procoptions) then
  822. begin
  823. CGMessage(cg_e_cant_call_abstract_method);
  824. goto dont_call;
  825. end;
  826. { generate no virtual call }
  827. no_virtual_call:=true;
  828. if (sp_static in symtableprocentry.symoptions) then
  829. begin
  830. { well lets put the VMT address directly into ESI }
  831. { it is kind of dirty but that is the simplest }
  832. { way to accept virtual static functions (PM) }
  833. loadesi:=true;
  834. { if no VMT just use $0 bug0214 PM }
  835. rg.getexplicitregisterint(exprasmlist,R_ESI);
  836. if not(oo_has_vmt in tobjectdef(methodpointer.resulttype.def).objectoptions) then
  837. cg.a_load_const_reg(exprasmlist,OS_ADDR,0,self_pointer_reg)
  838. else
  839. begin
  840. reference_reset_symbol(href,objectlibrary.newasmsymbol(tobjectdef(methodpointer.resulttype.def).vmt_mangledname),0);
  841. cg.a_loadaddr_ref_reg(exprasmlist,href,self_pointer_reg);
  842. end;
  843. { emit_reg(A_PUSH,S_L,R_ESI);
  844. this is done below !! }
  845. end
  846. else
  847. { this is a member call, so ESI isn't modfied }
  848. loadesi:=false;
  849. { a class destructor needs a flag }
  850. if is_class(tobjectdef(methodpointer.resulttype.def)) and
  851. (procdefinition.proctypeoption=potype_destructor) then
  852. begin
  853. cg.a_param_const(exprasmlist,OS_ADDR,0,2);
  854. cg.a_param_reg(exprasmlist,OS_ADDR,self_pointer_reg,1);
  855. end;
  856. if not(is_con_or_destructor and
  857. is_class(methodpointer.resulttype.def) and
  858. (procdefinition.proctypeoption in [potype_constructor,potype_destructor])
  859. ) then
  860. cg.a_param_reg(exprasmlist,OS_ADDR,self_pointer_reg,1);
  861. { if an inherited con- or destructor should be }
  862. { called in a con- or destructor then a warning }
  863. { will be made }
  864. { con- and destructors need a pointer to the vmt }
  865. if is_con_or_destructor and
  866. is_object(methodpointer.resulttype.def) and
  867. assigned(aktprocdef) then
  868. begin
  869. if not(aktprocdef.proctypeoption in
  870. [potype_constructor,potype_destructor]) then
  871. CGMessage(cg_w_member_cd_call_from_method);
  872. end;
  873. { class destructors get there flag above }
  874. { constructor flags ? }
  875. if is_con_or_destructor and
  876. not(
  877. is_class(methodpointer.resulttype.def) and
  878. assigned(aktprocdef) and
  879. (aktprocdef.proctypeoption=potype_destructor)) then
  880. begin
  881. { a constructor needs also a flag }
  882. if is_class(methodpointer.resulttype.def) then
  883. cg.a_param_const(exprasmlist,OS_ADDR,0,2);
  884. cg.a_param_const(exprasmlist,OS_ADDR,0,1);
  885. end;
  886. end;
  887. hnewn:
  888. begin
  889. { extended syntax of new }
  890. { ESI must be zero }
  891. rg.getexplicitregisterint(exprasmlist,R_ESI);
  892. cg.a_load_const_reg(exprasmlist,OS_ADDR,0,self_pointer_reg);
  893. cg.a_param_reg(exprasmlist,OS_ADDR,self_pointer_reg,2);
  894. { insert the vmt }
  895. reference_reset_symbol(href,objectlibrary.newasmsymbol(tobjectdef(methodpointer.resulttype.def).vmt_mangledname),0);
  896. cg.a_paramaddr_ref(exprasmlist,href,1);
  897. extended_new:=true;
  898. end;
  899. hdisposen:
  900. begin
  901. secondpass(methodpointer);
  902. { destructor with extended syntax called from dispose }
  903. { hdisposen always deliver LOC_REFERENCE }
  904. rg.getexplicitregisterint(exprasmlist,R_ESI);
  905. emit_ref_reg(A_LEA,S_L,methodpointer.location.reference,R_ESI);
  906. reference_release(exprasmlist,methodpointer.location.reference);
  907. cg.a_param_reg(exprasmlist,OS_ADDR,self_pointer_reg,2);
  908. reference_reset_symbol(href,objectlibrary.newasmsymbol(tobjectdef(methodpointer.resulttype.def).vmt_mangledname),0);
  909. cg.a_paramaddr_ref(exprasmlist,href,1);
  910. end;
  911. else
  912. begin
  913. { call to an instance member }
  914. if (symtableproc.symtabletype<>withsymtable) then
  915. begin
  916. secondpass(methodpointer);
  917. rg.getexplicitregisterint(exprasmlist,R_ESI);
  918. case methodpointer.location.loc of
  919. LOC_CREGISTER,
  920. LOC_REGISTER:
  921. begin
  922. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,methodpointer.location.register,R_ESI);
  923. rg.ungetregisterint(exprasmlist,methodpointer.location.register);
  924. end;
  925. else
  926. begin
  927. if (methodpointer.resulttype.def.deftype=classrefdef) or
  928. is_class_or_interface(methodpointer.resulttype.def) then
  929. cg.a_load_ref_reg(exprasmlist,OS_ADDR,methodpointer.location.reference,R_ESI)
  930. else
  931. cg.a_loadaddr_ref_reg(exprasmlist,methodpointer.location.reference,R_ESI);
  932. reference_release(exprasmlist,methodpointer.location.reference);
  933. end;
  934. end;
  935. end;
  936. { when calling a class method, we have to load ESI with the VMT !
  937. But, not for a class method via self }
  938. if not(po_containsself in procdefinition.procoptions) then
  939. begin
  940. if (po_staticmethod in procdefinition.procoptions) or
  941. ((po_classmethod in procdefinition.procoptions) and
  942. not(methodpointer.resulttype.def.deftype=classrefdef)) then
  943. begin
  944. r.enum:=self_pointer_reg;
  945. rg.getexplicitregisterint(exprasmlist,r.enum);
  946. if not(oo_has_vmt in tprocdef(procdefinition)._class.objectoptions) then
  947. cg.a_load_const_reg(exprasmlist,OS_ADDR,0,r)
  948. else
  949. begin
  950. { class method and static methods needs current VMT }
  951. cg.g_maybe_testself(exprasmlist,r);
  952. reference_reset_base(href,r,tprocdef(procdefinition)._class.vmt_offset);
  953. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,r);
  954. cg.g_maybe_testvmt(exprasmlist,r,tprocdef(procdefinition)._class);
  955. end;
  956. end;
  957. { direct call to destructor: remove data }
  958. if (procdefinition.proctypeoption=potype_destructor) and
  959. is_class(methodpointer.resulttype.def) then
  960. cg.a_param_const(exprasmlist,OS_INT,1,1);
  961. { direct call to class constructor, don't allocate memory }
  962. if (procdefinition.proctypeoption=potype_constructor) and
  963. is_class(methodpointer.resulttype.def) then
  964. begin
  965. cg.a_param_const(exprasmlist,OS_INT,0,2);
  966. cg.a_param_const(exprasmlist,OS_INT,0,1);
  967. end
  968. else
  969. begin
  970. { constructor call via classreference => allocate memory }
  971. if (procdefinition.proctypeoption=potype_constructor) and
  972. (methodpointer.resulttype.def.deftype=classrefdef) and
  973. is_class(tclassrefdef(methodpointer.resulttype.def).pointertype.def) then
  974. cg.a_param_const(exprasmlist,OS_INT,1,1);
  975. cg.a_param_reg(exprasmlist,OS_ADDR,self_pointer_reg,1);
  976. end;
  977. end;
  978. if is_con_or_destructor then
  979. begin
  980. { classes don't get a VMT pointer pushed }
  981. if is_object(methodpointer.resulttype.def) then
  982. begin
  983. if (procdefinition.proctypeoption=potype_constructor) then
  984. begin
  985. { it's no bad idea, to insert the VMT }
  986. reference_reset_symbol(href,objectlibrary.newasmsymbol(
  987. tobjectdef(methodpointer.resulttype.def).vmt_mangledname),0);
  988. cg.a_paramaddr_ref(exprasmlist,href,1);
  989. end
  990. { destructors haven't to dispose the instance, if this is }
  991. { a direct call }
  992. else
  993. cg.a_param_const(exprasmlist,OS_INT,0,1);
  994. end;
  995. end;
  996. end;
  997. end;
  998. end;
  999. end
  1000. else
  1001. begin
  1002. if (
  1003. (po_classmethod in procdefinition.procoptions) and
  1004. not(assigned(aktprocdef) and
  1005. (po_classmethod in aktprocdef.procoptions))
  1006. ) or
  1007. (
  1008. (po_staticmethod in procdefinition.procoptions) and
  1009. not(assigned(aktprocdef) and
  1010. (po_staticmethod in aktprocdef.procoptions))
  1011. ) then
  1012. begin
  1013. r.enum:=self_pointer_reg;
  1014. rg.getexplicitregisterint(exprasmlist,r.enum);
  1015. if not(oo_has_vmt in tprocdef(procdefinition)._class.objectoptions) then
  1016. cg.a_load_const_reg(exprasmlist,OS_ADDR,0,r)
  1017. else
  1018. begin
  1019. { class method and static methods needs current VMT }
  1020. cg.g_maybe_testself(exprasmlist,r);
  1021. reference_reset_base(href,r,tprocdef(procdefinition)._class.vmt_offset);
  1022. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,r);
  1023. cg.g_maybe_testvmt(exprasmlist,r,tprocdef(procdefinition)._class);
  1024. end;
  1025. end
  1026. else
  1027. begin
  1028. { member call, ESI isn't modified }
  1029. loadesi:=false;
  1030. end;
  1031. { direct call to destructor: don't remove data! }
  1032. if is_class(procinfo._class) then
  1033. begin
  1034. if (procdefinition.proctypeoption=potype_destructor) then
  1035. begin
  1036. cg.a_param_const(exprasmlist,OS_INT,0,2);
  1037. cg.a_param_reg(exprasmlist,OS_ADDR,R_ESI,1);
  1038. end
  1039. else if (procdefinition.proctypeoption=potype_constructor) then
  1040. begin
  1041. cg.a_param_const(exprasmlist,OS_INT,0,2);
  1042. cg.a_param_const(exprasmlist,OS_INT,0,1);
  1043. end
  1044. else
  1045. cg.a_param_reg(exprasmlist,OS_ADDR,R_ESI,1);
  1046. end
  1047. else if is_object(procinfo._class) then
  1048. begin
  1049. cg.a_param_reg(exprasmlist,OS_ADDR,R_ESI,1);
  1050. if is_con_or_destructor then
  1051. begin
  1052. if (procdefinition.proctypeoption=potype_constructor) then
  1053. begin
  1054. { it's no bad idea, to insert the VMT }
  1055. reference_reset_symbol(href,objectlibrary.newasmsymbol(procinfo._class.vmt_mangledname),0);
  1056. cg.a_paramaddr_ref(exprasmlist,href,1);
  1057. end
  1058. { destructors haven't to dispose the instance, if this is }
  1059. { a direct call }
  1060. else
  1061. cg.a_param_const(exprasmlist,OS_INT,0,1);
  1062. end;
  1063. end
  1064. else
  1065. Internalerror(200006165);
  1066. end;
  1067. end;
  1068. {$endif dummy}
  1069. { call to BeforeDestruction? }
  1070. if (procdefinition.proctypeoption=potype_destructor) and
  1071. assigned(methodpointer) and
  1072. (methodpointer.nodetype<>typen) and
  1073. is_class(tobjectdef(methodpointer.resulttype.def)) and
  1074. (inlined or
  1075. (right=nil)) then
  1076. begin
  1077. r.enum:=self_pointer_reg;
  1078. cg.a_param_reg(exprasmlist,OS_ADDR,r,paramanager.getintparaloc(1));
  1079. reference_reset_base(href,r,0);
  1080. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  1081. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,tmpreg);
  1082. reference_reset_base(href,tmpreg,72);
  1083. cg.a_call_ref(exprasmlist,href);
  1084. cg.free_scratch_reg(exprasmlist,tmpreg);
  1085. end;
  1086. {$ifndef SPARC}{We don't need that on SPARC arch!}
  1087. { push base pointer ?}
  1088. { never when inlining, since if necessary, the base pointer }
  1089. { can/will be gottten from the current procedure's symtable }
  1090. { (JM)}
  1091. if not inlined then
  1092. if (lexlevel>=normal_function_level) and assigned(tprocdef(procdefinition).parast) and
  1093. ((tprocdef(procdefinition).parast.symtablelevel)>normal_function_level) then
  1094. load_framepointer;
  1095. rg.saveintregvars(exprasmlist,regs_to_push_int);
  1096. rg.saveotherregvars(exprasmlist,regs_to_push_other);
  1097. {$endif SPARC}
  1098. {$ifdef dummy}
  1099. if (po_virtualmethod in procdefinition.procoptions) and
  1100. not(no_virtual_call) then
  1101. begin
  1102. { static functions contain the vmt_address in ESI }
  1103. { also class methods }
  1104. { Here it is quite tricky because it also depends }
  1105. { on the methodpointer PM }
  1106. release_tmpreg:=false;
  1107. rg.getexplicitregisterint(exprasmlist,R_ESI);
  1108. if assigned(aktprocdef) then
  1109. begin
  1110. if (((sp_static in aktprocdef.procsym.symoptions) or
  1111. (po_classmethod in aktprocdef.procoptions)) and
  1112. ((methodpointer=nil) or (methodpointer.nodetype=typen)))
  1113. or
  1114. (po_staticmethod in procdefinition.procoptions) or
  1115. ((procdefinition.proctypeoption=potype_constructor) and
  1116. { esi contains the vmt if we call a constructor via a class ref }
  1117. assigned(methodpointer) and
  1118. (methodpointer.resulttype.def.deftype=classrefdef)
  1119. ) or
  1120. { is_interface(tprocdef(procdefinition)._class) or }
  1121. { ESI is loaded earlier }
  1122. (po_classmethod in procdefinition.procoptions) then
  1123. begin
  1124. reference_reset_base(href,R_ESI,0);
  1125. end
  1126. else
  1127. begin
  1128. { this is one point where we need vmt_offset (PM) }
  1129. reference_reset_base(href,R_ESI,tprocdef(procdefinition)._class.vmt_offset);
  1130. cg.a_maybe_testself(exprasmlist);
  1131. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  1132. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,tmpreg);
  1133. reference_reset_base(href,tmpreg,0);
  1134. release_tmpreg:=true;
  1135. end;
  1136. end
  1137. else
  1138. { aktprocdef should be assigned, also in main program }
  1139. internalerror(12345);
  1140. if tprocdef(procdefinition).extnumber=-1 then
  1141. internalerror(44584);
  1142. href.offset:=tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber);
  1143. if not(is_interface(tprocdef(procdefinition)._class)) and
  1144. not(is_cppclass(tprocdef(procdefinition)._class)) then
  1145. cg.g_maybe_testvmt(exprasmlist,href.base,tprocdef(procdefinition)._class);
  1146. cg.a_call_ref(exprasmlist,href);
  1147. if release_tmpreg then
  1148. cg.free_scratch_reg(exprasmlist,tmpreg);
  1149. end
  1150. else
  1151. {$endif dummy}
  1152. if not inlined then
  1153. begin
  1154. { We can call interrupts from within the smae code
  1155. by just pushing the flags and CS PM }
  1156. if (po_interrupt in procdefinition.procoptions) then
  1157. extra_interrupt_code;
  1158. cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
  1159. end
  1160. else { inlined proc }
  1161. { inlined code is in inlinecode }
  1162. begin
  1163. { process the inlinecode }
  1164. secondpass(tnode(inlinecode));
  1165. { free the args }
  1166. if tprocdef(procdefinition).parast.datasize>0 then
  1167. tg.UnGetTemp(exprasmlist,pararef);
  1168. end;
  1169. end
  1170. else
  1171. { now procedure variable case }
  1172. begin
  1173. secondpass(right);
  1174. if (po_interrupt in procdefinition.procoptions) then
  1175. extra_interrupt_code;
  1176. { procedure of object? }
  1177. if (po_methodpointer in procdefinition.procoptions) then
  1178. begin
  1179. {$ifdef dummy}
  1180. { method pointer can't be in a register }
  1181. hregister:=R_NO;
  1182. { do some hacking if we call a method pointer }
  1183. { which is a class member }
  1184. { else ESI is overwritten ! }
  1185. if (right.location.reference.base=R_ESI) or
  1186. (right.location.reference.index=R_ESI) then
  1187. begin
  1188. reference_release(exprasmlist,right.location.reference);
  1189. hregister:=cg.get_scratch_reg_address(exprasmlist);
  1190. cg.a_load_ref_reg(exprasmlist,OS_ADDR,right.location.reference,hregister);
  1191. end;
  1192. { load self, but not if it's already explicitly pushed }
  1193. if not(po_containsself in procdefinition.procoptions) then
  1194. begin
  1195. { load ESI }
  1196. href:=right.location.reference;
  1197. inc(href.offset,4);
  1198. rg.getexplicitregisterint(exprasmlist,R_ESI);
  1199. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,self_pointer_reg);
  1200. { push self pointer }
  1201. cg.a_param_reg(exprasmlist,OS_ADDR,self_pointer_reg,-1);
  1202. end;
  1203. rg.saveregvars(exprasmlist,ALL_REGISTERS);
  1204. if hregister<>R_NO then
  1205. cg.a_call_reg(exprasmlist,hregister)
  1206. else
  1207. cg.a_call_ref(exprasmlist,right.location.reference);
  1208. if hregister<>R_NO then
  1209. cg.free_scratch_reg(exprasmlist,hregister);
  1210. reference_release(exprasmlist,right.location.reference);
  1211. tg.Ungetiftemp(exprasmlist,right.location.reference);
  1212. {$endif dummy}
  1213. end
  1214. else
  1215. begin
  1216. rg.saveintregvars(exprasmlist,ALL_INTREGISTERS);
  1217. rg.saveotherregvars(exprasmlist,ALL_REGISTERS);
  1218. cg.a_call_loc(exprasmlist,right.location);
  1219. location_release(exprasmlist,right.location);
  1220. location_freetemp(exprasmlist,right.location);
  1221. end;
  1222. end;
  1223. {$ifdef dummy}
  1224. { this was only for normal functions
  1225. displaced here so we also get
  1226. it to work for procvars PM }
  1227. if (not inlined) and (po_clearstack in procdefinition.procoptions) then
  1228. begin
  1229. { we also add the pop_size which is included in pushedparasize }
  1230. pop_size:=0;
  1231. { better than an add on all processors }
  1232. if pushedparasize=4 then
  1233. begin
  1234. rg.getexplicitregisterint(exprasmlist,R_EDI);
  1235. emit_reg(A_POP,S_L,R_EDI);
  1236. rg.ungetregisterint(exprasmlist,R_EDI);
  1237. end
  1238. { the pentium has two pipes and pop reg is pairable }
  1239. { but the registers must be different! }
  1240. else if (pushedparasize=8) and
  1241. not(cs_littlesize in aktglobalswitches) and
  1242. {$ifdef i386}
  1243. (aktoptprocessor=ClassP5) and
  1244. {$endif}
  1245. (procinfo._class=nil) then
  1246. begin
  1247. rg.getexplicitregisterint(exprasmlist,R_EDI);
  1248. emit_reg(A_POP,S_L,R_EDI);
  1249. rg.ungetregisterint(exprasmlist,R_EDI);
  1250. exprasmList.concat(tai_regalloc.Alloc(R_ESI));
  1251. emit_reg(A_POP,S_L,R_ESI);
  1252. exprasmList.concat(tai_regalloc.DeAlloc(R_ESI));
  1253. end
  1254. else if pushedparasize<>0 then
  1255. emit_const_reg(A_ADD,S_L,pushedparasize,R_ESP);
  1256. end;
  1257. {$endif dummy}
  1258. {$ifdef powerpc}
  1259. { this calculation must be done in pass_1 anyway, so don't worry }
  1260. if tppcprocinfo(procinfo).maxpushedparasize<pushedparasize then
  1261. tppcprocinfo(procinfo).maxpushedparasize:=pushedparasize;
  1262. {$endif powerpc}
  1263. {$ifdef OPTALIGN}
  1264. r.enum:=R_ESP;
  1265. if pop_esp then
  1266. emit_reg(A_POP,S_L,r);
  1267. {$endif OPTALIGN}
  1268. dont_call:
  1269. pushedparasize:=oldpushedparasize;
  1270. rg.restoreunusedstate(unusedstate);
  1271. {$ifdef TEMPREGDEBUG}
  1272. testregisters32;
  1273. {$endif TEMPREGDEBUG}
  1274. { a constructor could be a function with boolean result }
  1275. { if calling constructor called fail we
  1276. must jump directly to quickexitlabel PM
  1277. but only if it is a call of an inherited constructor }
  1278. if (inlined or
  1279. (right=nil)) and
  1280. (procdefinition.proctypeoption=potype_constructor) and
  1281. assigned(methodpointer) and
  1282. (methodpointer.nodetype=typen) and
  1283. (aktprocdef.proctypeoption=potype_constructor) then
  1284. begin
  1285. r.enum:=accumulator;
  1286. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,r,faillabel);
  1287. end;
  1288. { call to AfterConstruction? }
  1289. if is_class(resulttype.def) and
  1290. (inlined or
  1291. (right=nil)) and
  1292. (procdefinition.proctypeoption=potype_constructor) and
  1293. assigned(methodpointer) and
  1294. (methodpointer.nodetype<>typen) then
  1295. begin
  1296. objectlibrary.getlabel(constructorfailed);
  1297. r.enum:=self_pointer_reg;
  1298. r2.enum:=accumulator;
  1299. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,r,constructorfailed);
  1300. cg.a_param_reg(exprasmlist,OS_ADDR,r2,paramanager.getintparaloc(1));
  1301. reference_reset_base(href,r,0);
  1302. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  1303. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,tmpreg);
  1304. reference_reset_base(href,tmpreg,17*pointer_size);
  1305. cg.a_call_ref(exprasmlist,href);
  1306. cg.free_scratch_reg(exprasmlist,tmpreg);
  1307. exprasmList.concat(tai_regalloc.Alloc(r2));
  1308. cg.a_label(exprasmlist,constructorfailed);
  1309. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,r,r2);
  1310. end;
  1311. { handle function results }
  1312. if (not is_void(resulttype.def)) then
  1313. handle_return_value(inlined,extended_new);
  1314. { perhaps i/o check ? }
  1315. if iolabel<>nil then
  1316. begin
  1317. reference_reset_symbol(href,iolabel,0);
  1318. cg.a_paramaddr_ref(exprasmlist,href,paramanager.getintparaloc(1));
  1319. cg.a_call_name(exprasmlist,'FPC_IOCHECK');
  1320. end;
  1321. {$ifdef i386}
  1322. r.enum:=R_ESP;
  1323. if pop_size>0 then
  1324. emit_const_reg(A_ADD,S_L,pop_size,r);
  1325. {$endif i386}
  1326. { restore registers }
  1327. rg.restoreusedotherregisters(exprasmlist,pushed);
  1328. rg.restoreusedintregisters(exprasmlist,pushedint);
  1329. { at last, restore instance pointer (SELF) }
  1330. if loadesi then
  1331. cg.g_maybe_loadself(exprasmlist);
  1332. pp:=tbinarynode(params);
  1333. while assigned(pp) do
  1334. begin
  1335. if assigned(pp.left) then
  1336. begin
  1337. location_freetemp(exprasmlist,pp.left.location);
  1338. { process also all nodes of an array of const }
  1339. if pp.left.nodetype=arrayconstructorn then
  1340. begin
  1341. if assigned(tarrayconstructornode(pp.left).left) then
  1342. begin
  1343. hp:=pp.left;
  1344. while assigned(hp) do
  1345. begin
  1346. location_freetemp(exprasmlist,tarrayconstructornode(hp).left.location);
  1347. hp:=tarrayconstructornode(hp).right;
  1348. end;
  1349. end;
  1350. end;
  1351. end;
  1352. pp:=tbinarynode(pp.right);
  1353. end;
  1354. if inlined then
  1355. begin
  1356. if (resulttype.def.size>0) then
  1357. tg.UnGetTemp(exprasmlist,returnref);
  1358. tprocdef(procdefinition).parast.address_fixup:=store_parast_fixup;
  1359. right:=inlinecode;
  1360. end;
  1361. if assigned(params) then
  1362. params.free;
  1363. { from now on the result can be freed normally }
  1364. if inlined and paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
  1365. tg.ChangeTempType(exprasmlist,funcretref,tt_normal);
  1366. { if return value is not used }
  1367. if (not(nf_return_value_used in flags)) and (not is_void(resulttype.def)) then
  1368. begin
  1369. if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
  1370. begin
  1371. { data which must be finalized ? }
  1372. if (resulttype.def.needs_inittable) then
  1373. cg.g_finalize(exprasmlist,resulttype.def,location.reference,false);
  1374. { release unused temp }
  1375. tg.ungetiftemp(exprasmlist,location.reference)
  1376. end
  1377. else if location.loc=LOC_FPUREGISTER then
  1378. begin
  1379. {$ifdef i386}
  1380. { release FPU stack }
  1381. r.enum:=R_ST;
  1382. emit_reg(A_FSTP,S_NO,r);
  1383. {
  1384. dec(trgcpu(rg).fpuvaroffset);
  1385. do NOT decrement as the increment before
  1386. is not called for unused results PM }
  1387. {$endif i386}
  1388. end;
  1389. end;
  1390. end;
  1391. {*****************************************************************************
  1392. TCGPROCINLINENODE
  1393. *****************************************************************************}
  1394. procedure tcgprocinlinenode.pass_2;
  1395. var st : tsymtable;
  1396. oldprocdef : tprocdef;
  1397. ps, i : longint;
  1398. tmpreg: tregister;
  1399. oldprocinfo : tprocinfo;
  1400. oldinlining_procedure,
  1401. nostackframe,make_global : boolean;
  1402. inlineentrycode,inlineexitcode : TAAsmoutput;
  1403. oldexitlabel,oldexit2label,oldquickexitlabel:tasmlabel;
  1404. oldregstate: pointer;
  1405. localsref : treference;
  1406. {$ifdef GDB}
  1407. startlabel,endlabel : tasmlabel;
  1408. pp : pchar;
  1409. mangled_length : longint;
  1410. {$endif GDB}
  1411. begin
  1412. { deallocate the registers used for the current procedure's regvars }
  1413. if assigned(aktprocdef.regvarinfo) then
  1414. begin
  1415. with pregvarinfo(aktprocdef.regvarinfo)^ do
  1416. for i := 1 to maxvarregs do
  1417. if assigned(regvars[i]) then
  1418. store_regvar(exprasmlist,regvars[i].reg);
  1419. rg.saveStateForInline(oldregstate);
  1420. { make sure the register allocator knows what the regvars in the }
  1421. { inlined code block are (JM) }
  1422. rg.resetusableregisters;
  1423. rg.clearregistercount;
  1424. rg.cleartempgen;
  1425. if assigned(inlineprocdef.regvarinfo) then
  1426. with pregvarinfo(inlineprocdef.regvarinfo)^ do
  1427. for i := 1 to maxvarregs do
  1428. if assigned(regvars[i]) then
  1429. begin
  1430. tmpreg:=rg.makeregsize(regvars[i].reg,OS_INT);
  1431. {Fix me!!}
  1432. { rg.makeregvar(tmpreg);}
  1433. internalerror(200301232);
  1434. end;
  1435. end;
  1436. oldinlining_procedure:=inlining_procedure;
  1437. oldexitlabel:=aktexitlabel;
  1438. oldexit2label:=aktexit2label;
  1439. oldquickexitlabel:=quickexitlabel;
  1440. oldprocdef:=aktprocdef;
  1441. oldprocinfo:=procinfo;
  1442. objectlibrary.getlabel(aktexitlabel);
  1443. objectlibrary.getlabel(aktexit2label);
  1444. { we're inlining a procedure }
  1445. inlining_procedure:=true;
  1446. aktprocdef:=inlineprocdef;
  1447. { clone procinfo, but not the asmlists }
  1448. procinfo:=tprocinfo(cprocinfo.newinstance);
  1449. move(pointer(oldprocinfo)^,pointer(procinfo)^,cprocinfo.InstanceSize);
  1450. procinfo.aktentrycode:=nil;
  1451. procinfo.aktexitcode:=nil;
  1452. procinfo.aktproccode:=nil;
  1453. procinfo.aktlocaldata:=nil;
  1454. { set new procinfo }
  1455. procinfo.return_offset:=retoffset;
  1456. procinfo.para_offset:=para_offset;
  1457. procinfo.no_fast_exit:=false;
  1458. { arg space has been filled by the parent secondcall }
  1459. st:=aktprocdef.localst;
  1460. { set it to the same lexical level }
  1461. st.symtablelevel:=oldprocdef.localst.symtablelevel;
  1462. if st.datasize>0 then
  1463. begin
  1464. tg.GetTemp(exprasmlist,st.datasize,tt_persistant,localsref);
  1465. st.address_fixup:=localsref.offset+st.datasize;
  1466. {$ifdef extdebug}
  1467. Comment(V_debug,'local symtable is at offset '+tostr(st.address_fixup));
  1468. exprasmList.concat(tai_comment.Create(strpnew(
  1469. 'local symtable is at offset '+tostr(st.address_fixup))));
  1470. {$endif extdebug}
  1471. end;
  1472. exprasmList.concat(Tai_Marker.Create(InlineStart));
  1473. {$ifdef extdebug}
  1474. exprasmList.concat(tai_comment.Create(strpnew('Start of inlined proc')));
  1475. {$endif extdebug}
  1476. {$ifdef GDB}
  1477. if (cs_debuginfo in aktmoduleswitches) then
  1478. begin
  1479. objectlibrary.getaddrlabel(startlabel);
  1480. objectlibrary.getaddrlabel(endlabel);
  1481. cg.a_label(exprasmlist,startlabel);
  1482. inlineprocdef.localst.symtabletype:=inlinelocalsymtable;
  1483. inlineprocdef.parast.symtabletype:=inlineparasymtable;
  1484. { Here we must include the para and local symtable info }
  1485. inlineprocdef.concatstabto(withdebuglist);
  1486. { set it back for safety }
  1487. inlineprocdef.localst.symtabletype:=localsymtable;
  1488. inlineprocdef.parast.symtabletype:=parasymtable;
  1489. mangled_length:=length(oldprocdef.mangledname);
  1490. getmem(pp,mangled_length+50);
  1491. strpcopy(pp,'192,0,0,'+startlabel.name);
  1492. if (target_info.use_function_relative_addresses) then
  1493. begin
  1494. strpcopy(strend(pp),'-');
  1495. strpcopy(strend(pp),oldprocdef.mangledname);
  1496. end;
  1497. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  1498. end;
  1499. {$endif GDB}
  1500. { takes care of local data initialization }
  1501. inlineentrycode:=TAAsmoutput.Create;
  1502. inlineexitcode:=TAAsmoutput.Create;
  1503. ps:=para_size;
  1504. make_global:=false; { to avoid warning }
  1505. genentrycode(inlineentrycode,make_global,0,ps,nostackframe,true);
  1506. if po_assembler in aktprocdef.procoptions then
  1507. inlineentrycode.insert(Tai_marker.Create(asmblockstart));
  1508. exprasmList.concatlist(inlineentrycode);
  1509. secondpass(inlinetree);
  1510. genexitcode(inlineexitcode,0,false,true);
  1511. if po_assembler in aktprocdef.procoptions then
  1512. inlineexitcode.concat(Tai_marker.Create(asmblockend));
  1513. exprasmList.concatlist(inlineexitcode);
  1514. inlineentrycode.free;
  1515. inlineexitcode.free;
  1516. {$ifdef extdebug}
  1517. exprasmList.concat(tai_comment.Create(strpnew('End of inlined proc')));
  1518. {$endif extdebug}
  1519. exprasmList.concat(Tai_Marker.Create(InlineEnd));
  1520. {we can free the local data now, reset also the fixup address }
  1521. if st.datasize>0 then
  1522. begin
  1523. tg.UnGetTemp(exprasmlist,localsref);
  1524. st.address_fixup:=0;
  1525. end;
  1526. { restore procinfo }
  1527. procinfo.free;
  1528. procinfo:=oldprocinfo;
  1529. {$ifdef GDB}
  1530. if (cs_debuginfo in aktmoduleswitches) then
  1531. begin
  1532. cg.a_label(exprasmlist,endlabel);
  1533. strpcopy(pp,'224,0,0,'+endlabel.name);
  1534. if (target_info.use_function_relative_addresses) then
  1535. begin
  1536. strpcopy(strend(pp),'-');
  1537. strpcopy(strend(pp),oldprocdef.mangledname);
  1538. end;
  1539. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  1540. freemem(pp,mangled_length+50);
  1541. end;
  1542. {$endif GDB}
  1543. { restore }
  1544. aktprocdef:=oldprocdef;
  1545. aktexitlabel:=oldexitlabel;
  1546. aktexit2label:=oldexit2label;
  1547. quickexitlabel:=oldquickexitlabel;
  1548. inlining_procedure:=oldinlining_procedure;
  1549. { reallocate the registers used for the current procedure's regvars, }
  1550. { since they may have been used and then deallocated in the inlined }
  1551. { procedure (JM) }
  1552. if assigned(aktprocdef.regvarinfo) then
  1553. begin
  1554. rg.restoreStateAfterInline(oldregstate);
  1555. end;
  1556. end;
  1557. begin
  1558. ccallparanode:=tcgcallparanode;
  1559. ccallnode:=tcgcallnode;
  1560. cprocinlinenode:=tcgprocinlinenode;
  1561. end.
  1562. {
  1563. $Log$
  1564. Revision 1.39 2003-02-19 22:00:14 daniel
  1565. * Code generator converted to new register notation
  1566. - Horribily outdated todo.txt removed
  1567. Revision 1.38 2003/02/15 22:17:38 carl
  1568. * bugfix of FPU emulation code
  1569. Revision 1.37 2003/02/12 22:10:07 carl
  1570. * load_frame_pointer is now generic
  1571. * change fpu emulation routine names
  1572. Revision 1.36 2003/01/30 21:46:57 peter
  1573. * self fixes for static methods (merged)
  1574. Revision 1.35 2003/01/22 20:45:15 mazen
  1575. * making math code in RTL compiling.
  1576. *NB : This does NOT mean necessary that it will generate correct code!
  1577. Revision 1.34 2003/01/17 12:03:45 daniel
  1578. * Optalign conditional code adapted to record Tregister
  1579. Revision 1.33 2003/01/08 18:43:56 daniel
  1580. * Tregister changed into a record
  1581. Revision 1.32 2002/12/15 22:50:00 florian
  1582. + some stuff for the new hidden parameter handling added
  1583. Revision 1.31 2002/12/15 21:30:12 florian
  1584. * tcallnode.paraitem introduced, all references to defcoll removed
  1585. Revision 1.30 2002/11/27 20:04:39 peter
  1586. * cdecl array of const fixes
  1587. Revision 1.29 2002/11/25 17:43:17 peter
  1588. * splitted defbase in defutil,symutil,defcmp
  1589. * merged isconvertable and is_equal into compare_defs(_ext)
  1590. * made operator search faster by walking the list only once
  1591. Revision 1.28 2002/11/18 17:31:54 peter
  1592. * pass proccalloption to ret_in_xxx and push_xxx functions
  1593. Revision 1.27 2002/11/16 15:34:30 florian
  1594. * generic location for float results
  1595. Revision 1.26 2002/11/15 01:58:51 peter
  1596. * merged changes from 1.0.7 up to 04-11
  1597. - -V option for generating bug report tracing
  1598. - more tracing for option parsing
  1599. - errors for cdecl and high()
  1600. - win32 import stabs
  1601. - win32 records<=8 are returned in eax:edx (turned off by default)
  1602. - heaptrc update
  1603. - more info for temp management in .s file with EXTDEBUG
  1604. Revision 1.25 2002/10/05 12:43:25 carl
  1605. * fixes for Delphi 6 compilation
  1606. (warning : Some features do not work under Delphi)
  1607. Revision 1.24 2002/09/30 07:00:45 florian
  1608. * fixes to common code to get the alpha compiler compiled applied
  1609. Revision 1.23 2002/09/17 18:54:02 jonas
  1610. * a_load_reg_reg() now has two size parameters: source and dest. This
  1611. allows some optimizations on architectures that don't encode the
  1612. register size in the register name.
  1613. Revision 1.22 2002/09/07 15:25:02 peter
  1614. * old logs removed and tabs fixed
  1615. Revision 1.21 2002/09/07 11:50:02 jonas
  1616. * fixed small regalloction info bug
  1617. Revision 1.20 2002/09/02 11:25:20 florian
  1618. * fixed generic procedure variable calling
  1619. Revision 1.19 2002/09/01 21:04:48 florian
  1620. * several powerpc related stuff fixed
  1621. Revision 1.18 2002/09/01 18:43:27 peter
  1622. * include accumulator in regs_to_push list
  1623. Revision 1.17 2002/09/01 12:13:00 peter
  1624. * use a_call_reg
  1625. * ungetiftemp for procvar of object temp
  1626. Revision 1.16 2002/08/25 19:25:18 peter
  1627. * sym.insert_in_data removed
  1628. * symtable.insertvardata/insertconstdata added
  1629. * removed insert_in_data call from symtable.insert, it needs to be
  1630. called separatly. This allows to deref the address calculation
  1631. * procedures now calculate the parast addresses after the procedure
  1632. directives are parsed. This fixes the cdecl parast problem
  1633. * push_addr_param has an extra argument that specifies if cdecl is used
  1634. or not
  1635. Revision 1.15 2002/08/23 16:14:48 peter
  1636. * tempgen cleanup
  1637. * tt_noreuse temp type added that will be used in genentrycode
  1638. Revision 1.14 2002/08/20 16:55:38 peter
  1639. * don't write (stabs)line info when inlining a procedure
  1640. Revision 1.13 2002/08/19 19:36:42 peter
  1641. * More fixes for cross unit inlining, all tnodes are now implemented
  1642. * Moved pocall_internconst to po_internconst because it is not a
  1643. calling type at all and it conflicted when inlining of these small
  1644. functions was requested
  1645. Revision 1.12 2002/08/18 20:06:23 peter
  1646. * inlining is now also allowed in interface
  1647. * renamed write/load to ppuwrite/ppuload
  1648. * tnode storing in ppu
  1649. * nld,ncon,nbas are already updated for storing in ppu
  1650. Revision 1.11 2002/08/17 22:09:44 florian
  1651. * result type handling in tcgcal.pass_2 overhauled
  1652. * better tnode.dowrite
  1653. * some ppc stuff fixed
  1654. Revision 1.10 2002/08/17 09:23:35 florian
  1655. * first part of procinfo rewrite
  1656. Revision 1.9 2002/08/13 21:40:55 florian
  1657. * more fixes for ppc calling conventions
  1658. Revision 1.8 2002/08/13 18:01:51 carl
  1659. * rename swatoperands to swapoperands
  1660. + m68k first compilable version (still needs a lot of testing):
  1661. assembler generator, system information , inline
  1662. assembler reader.
  1663. Revision 1.7 2002/08/12 15:08:39 carl
  1664. + stab register indexes for powerpc (moved from gdb to cpubase)
  1665. + tprocessor enumeration moved to cpuinfo
  1666. + linker in target_info is now a class
  1667. * many many updates for m68k (will soon start to compile)
  1668. - removed some ifdef or correct them for correct cpu
  1669. Revision 1.6 2002/08/11 14:32:26 peter
  1670. * renamed current_library to objectlibrary
  1671. Revision 1.5 2002/08/11 13:24:11 peter
  1672. * saving of asmsymbols in ppu supported
  1673. * asmsymbollist global is removed and moved into a new class
  1674. tasmlibrarydata that will hold the info of a .a file which
  1675. corresponds with a single module. Added librarydata to tmodule
  1676. to keep the library info stored for the module. In the future the
  1677. objectfiles will also be stored to the tasmlibrarydata class
  1678. * all getlabel/newasmsymbol and friends are moved to the new class
  1679. Revision 1.4 2002/08/06 20:55:20 florian
  1680. * first part of ppc calling conventions fix
  1681. Revision 1.3 2002/07/20 11:57:53 florian
  1682. * types.pas renamed to defbase.pas because D6 contains a types
  1683. unit so this would conflicts if D6 programms are compiled
  1684. + Willamette/SSE2 instructions to assembler added
  1685. Revision 1.2 2002/07/13 19:38:43 florian
  1686. * some more generic calling stuff fixed
  1687. }