ncal.pas 121 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110
  1. {
  2. This file implements the node for sub procedure calling.
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ncal;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cutils,cclasses,
  22. globtype,
  23. paramgr,parabase,
  24. node,nbas,nutils,
  25. {$ifdef state_tracking}
  26. nstate,
  27. {$endif state_tracking}
  28. symbase,symtype,symsym,symdef,symtable;
  29. type
  30. tcallnodeflag = (
  31. cnf_typedefset,
  32. cnf_return_value_used,
  33. cnf_inherited,
  34. cnf_anon_inherited,
  35. cnf_new_call,
  36. cnf_dispose_call,
  37. cnf_member_call, { called with implicit methodpointer tree }
  38. cnf_uses_varargs, { varargs are used in the declaration }
  39. cnf_create_failed { exception thrown in constructor -> don't call beforedestruction }
  40. );
  41. tcallnodeflags = set of tcallnodeflag;
  42. tcallnode = class(tbinarynode)
  43. private
  44. { info for inlining }
  45. inlinelocals: TFPObjectList;
  46. { number of parameters passed from the source, this does not include the hidden parameters }
  47. paralength : smallint;
  48. function gen_self_tree_methodpointer:tnode;
  49. function gen_self_tree:tnode;
  50. function gen_vmt_tree:tnode;
  51. procedure bind_parasym;
  52. { function return node, this is used to pass the data for a
  53. ret_in_param return value }
  54. _funcretnode : tnode;
  55. procedure setfuncretnode(const returnnode: tnode);
  56. procedure convert_carg_array_of_const;
  57. procedure order_parameters;
  58. procedure createinlineparas(var createstatement, deletestatement: tstatementnode);
  59. function replaceparaload(var n: tnode; arg: pointer): foreachnoderesult;
  60. procedure createlocaltemps(p:TObject;arg:pointer);
  61. function pass1_inline:tnode;
  62. function getfuncretassignment(inlineblock: tblocknode): tnode;
  63. protected
  64. pushedparasize : longint;
  65. public
  66. { the symbol containing the definition of the procedure }
  67. { to call }
  68. symtableprocentry : tprocsym;
  69. symtableprocentryderef : tderef;
  70. { symtable where the entry was found, needed for with support }
  71. symtableproc : TSymtable;
  72. { the definition of the procedure to call }
  73. procdefinition : tabstractprocdef;
  74. procdefinitionderef : tderef;
  75. methodpointerinit,
  76. methodpointerdone : tblocknode;
  77. { tree that contains the pointer to the object for this method }
  78. methodpointer : tnode;
  79. { varargs parasyms }
  80. varargsparas : tvarargsparalist;
  81. { node that specifies where the result should be put for calls }
  82. { that return their result in a parameter }
  83. property funcretnode: tnode read _funcretnode write setfuncretnode;
  84. { separately specified resultdef for some compilerprocs (e.g. }
  85. { you can't have a function with an "array of char" resultdef }
  86. { the RTL) (JM) }
  87. typedef: tdef;
  88. callnodeflags : tcallnodeflags;
  89. { only the processor specific nodes need to override this }
  90. { constructor }
  91. constructor create(l:tnode; v : tprocsym;st : TSymtable; mp: tnode; callflags:tcallnodeflags);virtual;
  92. constructor create_procvar(l,r:tnode);
  93. constructor createintern(const name: string; params: tnode);
  94. constructor createinternres(const name: string; params: tnode; res:tdef);
  95. constructor createinternreturn(const name: string; params: tnode; returnnode : tnode);
  96. destructor destroy;override;
  97. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  98. procedure ppuwrite(ppufile:tcompilerppufile);override;
  99. procedure derefnode;override;
  100. procedure buildderefimpl;override;
  101. procedure derefimpl;override;
  102. function dogetcopy : tnode;override;
  103. { Goes through all symbols in a class and subclasses and calls
  104. verify abstract for each .
  105. }
  106. procedure verifyabstractcalls;
  107. { called for each definition in a class and verifies if a method
  108. is abstract or not, if it is abstract, give out a warning
  109. }
  110. procedure verifyabstract(sym:TObject;arg:pointer);
  111. procedure insertintolist(l : tnodelist);override;
  112. function pass_1 : tnode;override;
  113. function pass_typecheck:tnode;override;
  114. {$ifdef state_tracking}
  115. function track_state_pass(exec_known:boolean):boolean;override;
  116. {$endif state_tracking}
  117. function docompare(p: tnode): boolean; override;
  118. procedure printnodedata(var t:text);override;
  119. function para_count:longint;
  120. function get_load_methodpointer:tnode;
  121. { checks if there are any parameters which end up at the stack, i.e.
  122. which have LOC_REFERENCE and set pi_has_stackparameter if this applies }
  123. procedure check_stack_parameters;
  124. property parameters : tnode read left write left;
  125. private
  126. AbstractMethodsList : TFPHashList;
  127. end;
  128. tcallnodeclass = class of tcallnode;
  129. tcallparaflag = (
  130. cpf_is_colon_para,
  131. cpf_varargs_para { belongs this para to varargs }
  132. );
  133. tcallparaflags = set of tcallparaflag;
  134. tcallparanode = class(ttertiarynode)
  135. public
  136. callparaflags : tcallparaflags;
  137. parasym : tparavarsym;
  138. used_by_callnode : boolean;
  139. { only the processor specific nodes need to override this }
  140. { constructor }
  141. constructor create(expr,next : tnode);virtual;
  142. destructor destroy;override;
  143. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  144. procedure ppuwrite(ppufile:tcompilerppufile);override;
  145. function dogetcopy : tnode;override;
  146. procedure insertintolist(l : tnodelist);override;
  147. function pass_1 : tnode;override;
  148. procedure get_paratype;
  149. procedure insert_typeconv(do_count : boolean);
  150. procedure det_registers;
  151. procedure firstcallparan;
  152. procedure secondcallparan;virtual;abstract;
  153. function docompare(p: tnode): boolean; override;
  154. procedure printnodetree(var t:text);override;
  155. property value : tnode read left write left;
  156. property nextpara : tnode read right write right;
  157. property parametername : tnode read third write third;
  158. end;
  159. tcallparanodeclass = class of tcallparanode;
  160. function reverseparameters(p: tcallparanode): tcallparanode;
  161. function translate_disp_call(selfnode,parametersnode : tnode;methodname : ansistring = '';dispid : longint = 0) : tnode;
  162. var
  163. ccallnode : tcallnodeclass;
  164. ccallparanode : tcallparanodeclass;
  165. { Current callnode, this is needed for having a link
  166. between the callparanodes and the callnode they belong to }
  167. aktcallnode : tcallnode;
  168. implementation
  169. uses
  170. systems,
  171. verbose,globals,
  172. symconst,defutil,defcmp,
  173. htypechk,pass_1,
  174. ncnv,nld,ninl,nadd,ncon,nmem,nset,
  175. procinfo,
  176. cgbase
  177. ;
  178. type
  179. tobjectinfoitem = class(tlinkedlistitem)
  180. objinfo : tobjectdef;
  181. constructor create(def : tobjectdef);
  182. end;
  183. {****************************************************************************
  184. HELPERS
  185. ****************************************************************************}
  186. function reverseparameters(p: tcallparanode): tcallparanode;
  187. var
  188. hp1, hp2: tcallparanode;
  189. begin
  190. hp1:=nil;
  191. while assigned(p) do
  192. begin
  193. { pull out }
  194. hp2:=p;
  195. p:=tcallparanode(p.right);
  196. { pull in }
  197. hp2.right:=hp1;
  198. hp1:=hp2;
  199. end;
  200. reverseparameters:=hp1;
  201. end;
  202. function translate_disp_call(selfnode,parametersnode : tnode;methodname : ansistring = '';dispid : longint = 0) : tnode;
  203. const
  204. DISPATCH_METHOD = $1;
  205. DISPATCH_PROPERTYGET = $2;
  206. DISPATCH_PROPERTYPUT = $4;
  207. DISPATCH_PROPERTYPUTREF = $8;
  208. DISPATCH_CONSTRUCT = $4000;
  209. var
  210. statements : tstatementnode;
  211. result_data,
  212. params : ttempcreatenode;
  213. paramssize : longint;
  214. calldescnode : tdataconstnode;
  215. para : tcallparanode;
  216. currargpos,
  217. namedparacount,
  218. paracount : longint;
  219. vardatadef,
  220. pvardatadef : tdef;
  221. dispatchbyref : boolean;
  222. calldesc : packed record
  223. calltype,argcount,namedargcount : byte;
  224. { size of argtypes is unknown at compile time
  225. so this is basically a dummy }
  226. argtypes : array[0..255] of byte;
  227. { argtypes is followed by method name
  228. names of named parameters, each being
  229. a zero terminated string
  230. }
  231. end;
  232. names : ansistring;
  233. dispintfinvoke,
  234. variantdispatch : boolean;
  235. procedure increase_paramssize;
  236. begin
  237. { for now we pass everything by reference
  238. case para.value.resultdef.typ of
  239. variantdef:
  240. inc(paramssize,para.value.resultdef.size);
  241. else
  242. }
  243. inc(paramssize,sizeof(voidpointertype.size ));
  244. {
  245. end;
  246. }
  247. end;
  248. begin
  249. variantdispatch:=selfnode.resultdef.typ=variantdef;
  250. dispintfinvoke:=not(variantdispatch);
  251. result:=internalstatements(statements);
  252. fillchar(calldesc,sizeof(calldesc),0);
  253. { get temp for the result }
  254. result_data:=ctempcreatenode.create(colevarianttype,colevarianttype.size,tt_persistent,true);
  255. addstatement(statements,result_data);
  256. { build parameters }
  257. { first, count and check parameters }
  258. // p2:=reverseparameters(tcallparanode(p2));
  259. para:=tcallparanode(parametersnode);
  260. paracount:=0;
  261. namedparacount:=0;
  262. paramssize:=0;
  263. while assigned(para) do
  264. begin
  265. inc(paracount);
  266. typecheckpass(para.value);
  267. { insert some extra casts }
  268. if is_constintnode(para.value) and not(is_64bitint(para.value.resultdef)) then
  269. begin
  270. para.value:=ctypeconvnode.create_internal(para.value,s32inttype);
  271. typecheckpass(para.value);
  272. end
  273. else if para.value.nodetype=stringconstn then
  274. begin
  275. para.value:=ctypeconvnode.create_internal(para.value,cwidestringtype);
  276. typecheckpass(para.value);
  277. end
  278. { force automatable boolean type }
  279. else if is_boolean(para.value.resultdef) then
  280. begin
  281. para.value:=ctypeconvnode.create_internal(para.value,bool16type);
  282. typecheckpass(para.value);
  283. end;
  284. if assigned(para.parametername) then
  285. begin
  286. typecheckpass(para.value);
  287. inc(namedparacount);
  288. end;
  289. if para.value.nodetype<>nothingn then
  290. if not is_automatable(para.value.resultdef) then
  291. CGMessagePos1(para.value.fileinfo,type_e_not_automatable,para.value.resultdef.typename);
  292. { we've to know the parameter size to allocate the temp. space }
  293. increase_paramssize;
  294. para:=tcallparanode(para.nextpara);
  295. end;
  296. calldesc.calltype:=DISPATCH_METHOD;
  297. calldesc.argcount:=paracount;
  298. { allocate space }
  299. params:=ctempcreatenode.create(voidtype,paramssize,tt_persistent,true);
  300. addstatement(statements,params);
  301. calldescnode:=cdataconstnode.create;
  302. if dispintfinvoke then
  303. calldescnode.append(dispid,sizeof(dispid));
  304. { build up parameters and description }
  305. para:=tcallparanode(parametersnode);
  306. currargpos:=0;
  307. paramssize:=0;
  308. names := '';
  309. while assigned(para) do
  310. begin
  311. if assigned(para.parametername) then
  312. begin
  313. if para.parametername.nodetype=stringconstn then
  314. names:=names+tstringconstnode(para.parametername).value_str+#0
  315. else
  316. internalerror(200611041);
  317. end;
  318. dispatchbyref:=para.value.resultdef.typ in [variantdef];
  319. { assign the argument/parameter to the temporary location }
  320. if para.value.nodetype<>nothingn then
  321. if dispatchbyref then
  322. addstatement(statements,cassignmentnode.create(
  323. ctypeconvnode.create_internal(cderefnode.create(caddnode.create(addn,
  324. caddrnode.create(ctemprefnode.create(params)),
  325. cordconstnode.create(paramssize,ptruinttype,false)
  326. )),voidpointertype),
  327. ctypeconvnode.create_internal(caddrnode.create_internal(para.value),voidpointertype)))
  328. else
  329. addstatement(statements,cassignmentnode.create(
  330. ctypeconvnode.create_internal(cderefnode.create(caddnode.create(addn,
  331. caddrnode.create(ctemprefnode.create(params)),
  332. cordconstnode.create(paramssize,ptruinttype,false)
  333. )),voidpointertype),
  334. ctypeconvnode.create_internal(para.value,voidpointertype)));
  335. if is_ansistring(para.value.resultdef) then
  336. calldesc.argtypes[currargpos]:=varStrArg
  337. else
  338. calldesc.argtypes[currargpos]:=para.value.resultdef.getvardef;
  339. if dispatchbyref then
  340. calldesc.argtypes[currargpos]:=calldesc.argtypes[currargpos] or $80;
  341. increase_paramssize;
  342. para.value:=nil;
  343. inc(currargpos);
  344. para:=tcallparanode(para.nextpara);
  345. end;
  346. // typecheckpass(statements);
  347. // printnode(output,statements);
  348. { old argument list skeleton isn't needed anymore }
  349. parametersnode.free;
  350. calldescnode.append(calldesc,3+calldesc.argcount);
  351. pvardatadef:=tpointerdef(search_system_type('PVARDATA').typedef);
  352. if variantdispatch then
  353. begin
  354. methodname:=methodname+#0;
  355. calldescnode.append(pointer(methodname)^,length(methodname));
  356. calldescnode.append(pointer(names)^,length(names));
  357. { actual call }
  358. vardatadef:=trecorddef(search_system_type('TVARDATA').typedef);
  359. addstatement(statements,ccallnode.createintern('fpc_dispinvoke_variant',
  360. { parameters are passed always reverted, i.e. the last comes first }
  361. ccallparanode.create(caddrnode.create(ctemprefnode.create(params)),
  362. ccallparanode.create(caddrnode.create(calldescnode),
  363. ccallparanode.create(ctypeconvnode.create_internal(selfnode,vardatadef),
  364. ccallparanode.create(ctypeconvnode.create_internal(caddrnode.create(
  365. ctemprefnode.create(result_data)
  366. ),pvardatadef),nil)))))
  367. );
  368. end
  369. else
  370. begin
  371. addstatement(statements,ccallnode.createintern('fpc_dispatch_by_id',
  372. { parameters are passed always reverted, i.e. the last comes first }
  373. ccallparanode.create(caddrnode.create(ctemprefnode.create(params)),
  374. ccallparanode.create(caddrnode.create(calldescnode),
  375. ccallparanode.create(ctypeconvnode.create_internal(selfnode,voidpointertype),
  376. ccallparanode.create(ctypeconvnode.create_internal(caddrnode.create(
  377. ctemprefnode.create(result_data)
  378. ),pvardatadef),nil)))))
  379. );
  380. end;
  381. { clean up }
  382. addstatement(statements,ctempdeletenode.create_normal_temp(result_data));
  383. addstatement(statements,ctemprefnode.create(result_data));
  384. end;
  385. procedure maybe_load_para_in_temp(var p:tnode);
  386. function is_simple_node(hp:tnode):boolean;
  387. begin
  388. is_simple_node:=(hp.nodetype in [typen,loadvmtaddrn,loadn,arrayconstructorn]);
  389. end;
  390. var
  391. hp,
  392. loadp,
  393. refp : tnode;
  394. hdef : tdef;
  395. ptemp : ttempcreatenode;
  396. usederef : boolean;
  397. usevoidpointer : boolean;
  398. newinitstatement,
  399. newdonestatement : tstatementnode;
  400. begin
  401. if not assigned(aktcallnode) then
  402. internalerror(200410121);
  403. { Load all complex loads into a temp to prevent
  404. double calls to a function. We can't simply check for a hp.nodetype=calln
  405. }
  406. hp:=p;
  407. while assigned(hp) and
  408. (hp.nodetype=typeconvn) and
  409. (ttypeconvnode(hp).convtype=tc_equal) do
  410. hp:=tunarynode(hp).left;
  411. if assigned(hp) and
  412. not is_simple_node(hp) then
  413. begin
  414. if not assigned(aktcallnode.methodpointerinit) then
  415. begin
  416. aktcallnode.methodpointerinit:=internalstatements(newinitstatement);
  417. aktcallnode.methodpointerdone:=internalstatements(newdonestatement);
  418. end
  419. else
  420. begin
  421. newinitstatement:=laststatement(aktcallnode.methodpointerinit);
  422. newdonestatement:=laststatement(aktcallnode.methodpointerdone);
  423. end;
  424. { temp create }
  425. usederef:=(p.resultdef.typ in [arraydef,recorddef]) or
  426. is_shortstring(p.resultdef) or
  427. is_object(p.resultdef);
  428. { avoid refcount increase }
  429. usevoidpointer:=is_interface(p.resultdef);
  430. if usederef then
  431. hdef:=tpointerdef.create(p.resultdef)
  432. else
  433. hdef:=p.resultdef;
  434. if usevoidpointer then
  435. begin
  436. ptemp:=ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
  437. loadp := ctypeconvnode.create_internal(p,voidpointertype);
  438. refp:=ctypeconvnode.create_internal(ctemprefnode.create(ptemp),hdef);
  439. end
  440. else
  441. begin
  442. ptemp:=ctempcreatenode.create(hdef,hdef.size,tt_persistent,true);
  443. if usederef then
  444. begin
  445. loadp:=caddrnode.create_internal(p);
  446. refp:=cderefnode.create(ctemprefnode.create(ptemp));
  447. end
  448. else
  449. begin
  450. loadp:=p;
  451. refp:=ctemprefnode.create(ptemp)
  452. end
  453. end;
  454. addstatement(newinitstatement,ptemp);
  455. addstatement(newinitstatement,cassignmentnode.create(
  456. ctemprefnode.create(ptemp),
  457. loadp));
  458. { new tree is only a temp reference }
  459. p:=refp;
  460. { temp release. We need to return a reference to the methodpointer
  461. otherwise the conversion from callnode to loadnode can't be done
  462. for the methodpointer unless the loadnode will also get a methodpointerinit and
  463. methodpointerdone node. For the moment we use register as temp and therefor
  464. don't create a temp-leak in the stackframe (PFV) }
  465. { the last statement should return the value as
  466. location and type, this is done be referencing the
  467. temp and converting it first from a persistent temp to
  468. normal temp }
  469. addstatement(newdonestatement,ctempdeletenode.create_normal_temp(ptemp));
  470. if usevoidpointer then
  471. addstatement(newdonestatement,ctypeconvnode.create_internal(
  472. ctemprefnode.create(ptemp),hdef))
  473. else
  474. addstatement(newdonestatement,ctemprefnode.create(ptemp));
  475. { call typecheckpass for new nodes }
  476. typecheckpass(p);
  477. typecheckpass(aktcallnode.methodpointerinit);
  478. typecheckpass(aktcallnode.methodpointerdone);
  479. end;
  480. end;
  481. function gen_high_tree(var p:tnode;paradef:tdef):tnode;
  482. {When passing an array to an open array, or a string to an open string,
  483. some code is needed that generates the high bound of the array. This
  484. function returns a tree containing the nodes for it.}
  485. var
  486. temp: tnode;
  487. len : integer;
  488. loadconst : boolean;
  489. hightree,l,r : tnode;
  490. begin
  491. len:=-1;
  492. loadconst:=true;
  493. hightree:=nil;
  494. case p.resultdef.typ of
  495. arraydef :
  496. begin
  497. if (paradef.typ<>arraydef) then
  498. internalerror(200405241);
  499. { passing a string to an array of char }
  500. if (p.nodetype=stringconstn) then
  501. begin
  502. len:=tstringconstnode(p).len;
  503. if len>0 then
  504. dec(len);
  505. end
  506. else
  507. { handle special case of passing an single array to an array of array }
  508. if compare_defs(tarraydef(paradef).elementdef,p.resultdef,nothingn)>=te_equal then
  509. len:=0
  510. else
  511. begin
  512. { handle via a normal inline in_high_x node }
  513. loadconst:=false;
  514. { slice? }
  515. if (p.nodetype=inlinen) and (tinlinenode(p).inlinenumber=in_slice_x) then
  516. with Tcallparanode(Tinlinenode(p).left) do
  517. begin
  518. {Array slice using slice builtin function.}
  519. l:=Tcallparanode(right).left;
  520. hightree:=caddnode.create(subn,l,genintconstnode(1));
  521. Tcallparanode(right).left:=nil;
  522. {Remove the inline node.}
  523. temp:=p;
  524. p:=left;
  525. Tcallparanode(tinlinenode(temp).left).left:=nil;
  526. temp.free;
  527. typecheckpass(hightree);
  528. end
  529. else if (p.nodetype=vecn) and (Tvecnode(p).right.nodetype=rangen) then
  530. begin
  531. {Array slice using .. operator.}
  532. with Trangenode(Tvecnode(p).right) do
  533. begin
  534. l:=left; {Get lower bound.}
  535. r:=right; {Get upper bound.}
  536. end;
  537. {In the procedure the array range is 0..(upper_bound-lower_bound).}
  538. hightree:=caddnode.create(subn,r,l);
  539. {Replace the rangnode in the tree by its lower_bound, and
  540. dispose the rangenode.}
  541. temp:=Tvecnode(p).right;
  542. Tvecnode(p).right:=l.getcopy;
  543. {Typecheckpass can only be performed *after* the l.getcopy since it
  544. can modify the tree, and l is in the hightree.}
  545. typecheckpass(hightree);
  546. with Trangenode(temp) do
  547. begin
  548. left:=nil;
  549. right:=nil;
  550. end;
  551. temp.free;
  552. {Tree changed from p[l..h] to p[l], recalculate resultdef.}
  553. p.resultdef:=nil;
  554. typecheckpass(p);
  555. end
  556. else
  557. begin
  558. maybe_load_para_in_temp(p);
  559. hightree:=geninlinenode(in_high_x,false,p.getcopy);
  560. typecheckpass(hightree);
  561. { only substract low(array) if it's <> 0 }
  562. temp:=geninlinenode(in_low_x,false,p.getcopy);
  563. typecheckpass(temp);
  564. if (temp.nodetype <> ordconstn) or
  565. (tordconstnode(temp).value <> 0) then
  566. hightree := caddnode.create(subn,hightree,temp)
  567. else
  568. temp.free;
  569. end;
  570. end;
  571. end;
  572. stringdef :
  573. begin
  574. if is_open_string(paradef) then
  575. begin
  576. maybe_load_para_in_temp(p);
  577. { handle via a normal inline in_high_x node }
  578. loadconst := false;
  579. hightree := geninlinenode(in_high_x,false,p.getcopy);
  580. end
  581. else
  582. begin
  583. { passing a string to an array of char }
  584. if (p.nodetype=stringconstn) then
  585. begin
  586. len:=tstringconstnode(p).len;
  587. if len>0 then
  588. dec(len);
  589. end
  590. else
  591. begin
  592. maybe_load_para_in_temp(p);
  593. hightree:=caddnode.create(subn,geninlinenode(in_length_x,false,p.getcopy),
  594. cordconstnode.create(1,sinttype,false));
  595. loadconst:=false;
  596. end;
  597. end;
  598. end;
  599. else
  600. len:=0;
  601. end;
  602. if loadconst then
  603. hightree:=cordconstnode.create(len,sinttype,true)
  604. else
  605. begin
  606. if not assigned(hightree) then
  607. internalerror(200304071);
  608. { Need to use explicit, because it can also be a enum }
  609. hightree:=ctypeconvnode.create_internal(hightree,sinttype);
  610. end;
  611. result:=hightree;
  612. end;
  613. {****************************************************************************
  614. TOBJECTINFOITEM
  615. ****************************************************************************}
  616. constructor tobjectinfoitem.create(def : tobjectdef);
  617. begin
  618. inherited create;
  619. objinfo := def;
  620. end;
  621. {****************************************************************************
  622. TCALLPARANODE
  623. ****************************************************************************}
  624. constructor tcallparanode.create(expr,next : tnode);
  625. begin
  626. inherited create(callparan,expr,next,nil);
  627. if not assigned(expr) then
  628. internalerror(200305091);
  629. expr.fileinfo:=fileinfo;
  630. callparaflags:=[];
  631. end;
  632. destructor tcallparanode.destroy;
  633. begin
  634. { When the node is used by callnode then
  635. we don't destroy left, the callnode takes care of it }
  636. if used_by_callnode then
  637. left:=nil;
  638. inherited destroy;
  639. end;
  640. constructor tcallparanode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  641. begin
  642. inherited ppuload(t,ppufile);
  643. ppufile.getsmallset(callparaflags);
  644. end;
  645. procedure tcallparanode.ppuwrite(ppufile:tcompilerppufile);
  646. begin
  647. inherited ppuwrite(ppufile);
  648. ppufile.putsmallset(callparaflags);
  649. end;
  650. function tcallparanode.dogetcopy : tnode;
  651. var
  652. n : tcallparanode;
  653. begin
  654. n:=tcallparanode(inherited dogetcopy);
  655. n.callparaflags:=callparaflags;
  656. n.parasym:=parasym;
  657. result:=n;
  658. end;
  659. procedure tcallparanode.insertintolist(l : tnodelist);
  660. begin
  661. end;
  662. function tcallparanode.pass_1 : tnode;
  663. begin
  664. firstpass(left);
  665. if assigned(right) then
  666. firstpass(right);
  667. result:=nil;
  668. end;
  669. procedure tcallparanode.get_paratype;
  670. var
  671. old_array_constructor : boolean;
  672. begin
  673. inc(parsing_para_level);
  674. if assigned(right) then
  675. tcallparanode(right).get_paratype;
  676. old_array_constructor:=allow_array_constructor;
  677. allow_array_constructor:=true;
  678. typecheckpass(left);
  679. allow_array_constructor:=old_array_constructor;
  680. if codegenerror then
  681. resultdef:=generrordef
  682. else
  683. resultdef:=left.resultdef;
  684. dec(parsing_para_level);
  685. end;
  686. procedure tcallparanode.insert_typeconv(do_count : boolean);
  687. var
  688. olddef : tdef;
  689. hp : tnode;
  690. {$ifdef extdebug}
  691. store_count_ref : boolean;
  692. {$endif def extdebug}
  693. begin
  694. inc(parsing_para_level);
  695. {$ifdef extdebug}
  696. if do_count then
  697. begin
  698. store_count_ref:=count_ref;
  699. count_ref:=true;
  700. end;
  701. {$endif def extdebug}
  702. { Be sure to have the resultdef }
  703. if not assigned(left.resultdef) then
  704. typecheckpass(left);
  705. if (left.nodetype<>nothingn) then
  706. begin
  707. { Convert tp procvars, this is needs to be done
  708. here to make the change permanent. in the overload
  709. choosing the changes are only made temporary }
  710. if (left.resultdef.typ=procvardef) and
  711. (parasym.vardef.typ<>procvardef) then
  712. begin
  713. if maybe_call_procvar(left,true) then
  714. resultdef:=left.resultdef;
  715. end;
  716. { Remove implicitly inserted typecast to pointer for
  717. @procvar in macpas }
  718. if (m_mac_procvar in current_settings.modeswitches) and
  719. (parasym.vardef.typ=procvardef) and
  720. (left.nodetype=typeconvn) and
  721. is_voidpointer(left.resultdef) and
  722. (ttypeconvnode(left).left.nodetype=typeconvn) and
  723. (ttypeconvnode(ttypeconvnode(left).left).convtype=tc_proc_2_procvar) then
  724. begin
  725. hp:=left;
  726. left:=ttypeconvnode(left).left;
  727. ttypeconvnode(hp).left:=nil;
  728. hp.free;
  729. end;
  730. { Handle varargs and hidden paras directly, no typeconvs or }
  731. { pass_typechecking needed }
  732. if (cpf_varargs_para in callparaflags) then
  733. begin
  734. { this should only happen vor C varargs }
  735. { the necessary conversions have already been performed in }
  736. { tarrayconstructornode.insert_typeconvs }
  737. set_varstate(left,vs_read,[vsf_must_be_valid]);
  738. insert_varargstypeconv(left,true);
  739. resultdef:=left.resultdef;
  740. { also update parasym type to get the correct parameter location
  741. for the new types }
  742. parasym.vardef:=left.resultdef;
  743. end
  744. else
  745. if (vo_is_hidden_para in parasym.varoptions) then
  746. begin
  747. set_varstate(left,vs_read,[vsf_must_be_valid]);
  748. resultdef:=left.resultdef;
  749. end
  750. else
  751. begin
  752. { Do we need arrayconstructor -> set conversion, then insert
  753. it here before the arrayconstructor node breaks the tree
  754. with its conversions of enum->ord }
  755. if (left.nodetype=arrayconstructorn) and
  756. (parasym.vardef.typ=setdef) then
  757. inserttypeconv(left,parasym.vardef);
  758. { set some settings needed for arrayconstructor }
  759. if is_array_constructor(left.resultdef) then
  760. begin
  761. if left.nodetype<>arrayconstructorn then
  762. internalerror(200504041);
  763. if is_array_of_const(parasym.vardef) then
  764. begin
  765. { force variant array }
  766. include(left.flags,nf_forcevaria);
  767. end
  768. else
  769. begin
  770. include(left.flags,nf_novariaallowed);
  771. { now that the resultting type is know we can insert the required
  772. typeconvs for the array constructor }
  773. if parasym.vardef.typ=arraydef then
  774. tarrayconstructornode(left).force_type(tarraydef(parasym.vardef).elementdef);
  775. end;
  776. end;
  777. { check if local proc/func is assigned to procvar }
  778. if left.resultdef.typ=procvardef then
  779. test_local_to_procvar(tprocvardef(left.resultdef),parasym.vardef);
  780. { test conversions }
  781. if not(is_shortstring(left.resultdef) and
  782. is_shortstring(parasym.vardef)) and
  783. (parasym.vardef.typ<>formaldef) then
  784. begin
  785. { Process open parameters }
  786. if paramanager.push_high_param(parasym.varspez,parasym.vardef,aktcallnode.procdefinition.proccalloption) then
  787. begin
  788. { insert type conv but hold the ranges of the array }
  789. olddef:=left.resultdef;
  790. inserttypeconv(left,parasym.vardef);
  791. left.resultdef:=olddef;
  792. end
  793. else
  794. begin
  795. check_ranges(left.fileinfo,left,parasym.vardef);
  796. inserttypeconv(left,parasym.vardef);
  797. end;
  798. if codegenerror then
  799. begin
  800. dec(parsing_para_level);
  801. exit;
  802. end;
  803. end;
  804. { check var strings }
  805. if (cs_strict_var_strings in current_settings.localswitches) and
  806. is_shortstring(left.resultdef) and
  807. is_shortstring(parasym.vardef) and
  808. (parasym.varspez in [vs_out,vs_var]) and
  809. not(is_open_string(parasym.vardef)) and
  810. not(equal_defs(left.resultdef,parasym.vardef)) then
  811. begin
  812. current_filepos:=left.fileinfo;
  813. CGMessage(type_e_strict_var_string_violation);
  814. end;
  815. { Handle formal parameters separate }
  816. if (parasym.vardef.typ=formaldef) then
  817. begin
  818. { load procvar if a procedure is passed }
  819. if ((m_tp_procvar in current_settings.modeswitches) or
  820. (m_mac_procvar in current_settings.modeswitches)) and
  821. (left.nodetype=calln) and
  822. (is_void(left.resultdef)) then
  823. load_procvar_from_calln(left);
  824. case parasym.varspez of
  825. vs_var,
  826. vs_out :
  827. begin
  828. if not valid_for_formal_var(left,true) then
  829. CGMessagePos(left.fileinfo,parser_e_illegal_parameter_list);
  830. end;
  831. vs_const :
  832. begin
  833. if not valid_for_formal_const(left,true) then
  834. CGMessagePos(left.fileinfo,parser_e_illegal_parameter_list);
  835. end;
  836. end;
  837. end
  838. else
  839. begin
  840. { check if the argument is allowed }
  841. if (parasym.varspez in [vs_out,vs_var]) then
  842. valid_for_var(left,true);
  843. end;
  844. if parasym.varspez in [vs_var,vs_out] then
  845. set_unique(left);
  846. { When the address needs to be pushed then the register is
  847. not regable. Exception is when the location is also a var
  848. parameter and we can pass the address transparently }
  849. if (
  850. not(
  851. (vo_is_hidden_para in parasym.varoptions) and
  852. (left.resultdef.typ in [pointerdef,classrefdef])
  853. ) and
  854. paramanager.push_addr_param(parasym.varspez,parasym.vardef,
  855. aktcallnode.procdefinition.proccalloption) and
  856. not(
  857. (left.nodetype=loadn) and
  858. (tloadnode(left).is_addr_param_load)
  859. )
  860. ) then
  861. make_not_regable(left,vr_addr);
  862. if do_count then
  863. begin
  864. case parasym.varspez of
  865. vs_out :
  866. set_varstate(left,vs_readwritten,[]);
  867. vs_var :
  868. set_varstate(left,vs_readwritten,[vsf_must_be_valid,vsf_use_hints]);
  869. else
  870. set_varstate(left,vs_read,[vsf_must_be_valid]);
  871. end;
  872. end;
  873. { must only be done after typeconv PM }
  874. resultdef:=parasym.vardef;
  875. end;
  876. end;
  877. { process next node }
  878. if assigned(right) then
  879. tcallparanode(right).insert_typeconv(do_count);
  880. dec(parsing_para_level);
  881. {$ifdef extdebug}
  882. if do_count then
  883. count_ref:=store_count_ref;
  884. {$endif def extdebug}
  885. end;
  886. procedure tcallparanode.det_registers;
  887. begin
  888. if assigned(right) then
  889. begin
  890. tcallparanode(right).det_registers;
  891. registersint:=right.registersint;
  892. registersfpu:=right.registersfpu;
  893. {$ifdef SUPPORT_MMX}
  894. registersmmx:=right.registersmmx;
  895. {$endif}
  896. end;
  897. firstpass(left);
  898. if left.registersint>registersint then
  899. registersint:=left.registersint;
  900. if left.registersfpu>registersfpu then
  901. registersfpu:=left.registersfpu;
  902. {$ifdef SUPPORT_MMX}
  903. if left.registersmmx>registersmmx then
  904. registersmmx:=left.registersmmx;
  905. {$endif SUPPORT_MMX}
  906. end;
  907. procedure tcallparanode.firstcallparan;
  908. begin
  909. if not assigned(left.resultdef) then
  910. get_paratype;
  911. det_registers;
  912. end;
  913. function tcallparanode.docompare(p: tnode): boolean;
  914. begin
  915. docompare :=
  916. inherited docompare(p) and
  917. (callparaflags = tcallparanode(p).callparaflags)
  918. ;
  919. end;
  920. procedure tcallparanode.printnodetree(var t:text);
  921. begin
  922. printnodelist(t);
  923. end;
  924. {****************************************************************************
  925. TCALLNODE
  926. ****************************************************************************}
  927. constructor tcallnode.create(l:tnode;v : tprocsym;st : TSymtable; mp: tnode; callflags:tcallnodeflags);
  928. begin
  929. inherited create(calln,l,nil);
  930. symtableprocentry:=v;
  931. symtableproc:=st;
  932. callnodeflags:=callflags+[cnf_return_value_used];
  933. methodpointer:=mp;
  934. methodpointerinit:=nil;
  935. methodpointerdone:=nil;
  936. procdefinition:=nil;
  937. _funcretnode:=nil;
  938. paralength:=-1;
  939. varargsparas:=nil;
  940. end;
  941. constructor tcallnode.create_procvar(l,r:tnode);
  942. begin
  943. inherited create(calln,l,r);
  944. symtableprocentry:=nil;
  945. symtableproc:=nil;
  946. methodpointer:=nil;
  947. methodpointerinit:=nil;
  948. methodpointerdone:=nil;
  949. procdefinition:=nil;
  950. callnodeflags:=[cnf_return_value_used];
  951. _funcretnode:=nil;
  952. paralength:=-1;
  953. varargsparas:=nil;
  954. end;
  955. constructor tcallnode.createintern(const name: string; params: tnode);
  956. var
  957. srsym: tsym;
  958. begin
  959. srsym := tsym(systemunit.Find(name));
  960. if not assigned(srsym) and
  961. (cs_compilesystem in current_settings.moduleswitches) then
  962. srsym := tsym(systemunit.Find(upper(name)));
  963. if not assigned(srsym) or
  964. (srsym.typ<>procsym) then
  965. Message1(cg_f_unknown_compilerproc,name);
  966. create(params,tprocsym(srsym),srsym.owner,nil,[]);
  967. end;
  968. constructor tcallnode.createinternres(const name: string; params: tnode; res:tdef);
  969. var
  970. pd : tprocdef;
  971. begin
  972. createintern(name,params);
  973. typedef := res;
  974. include(callnodeflags,cnf_typedefset);
  975. pd:=tprocdef(symtableprocentry.ProcdefList[0]);
  976. { both the normal and specified resultdef either have to be returned via a }
  977. { parameter or not, but no mixing (JM) }
  978. if paramanager.ret_in_param(typedef,pd.proccalloption) xor
  979. paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
  980. internalerror(200108291);
  981. end;
  982. constructor tcallnode.createinternreturn(const name: string; params: tnode; returnnode : tnode);
  983. var
  984. pd : tprocdef;
  985. begin
  986. createintern(name,params);
  987. _funcretnode:=returnnode;
  988. pd:=tprocdef(symtableprocentry.ProcdefList[0]);
  989. if not paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
  990. internalerror(200204247);
  991. end;
  992. procedure tcallnode.setfuncretnode(const returnnode: tnode);
  993. var
  994. para: tcallparanode;
  995. begin
  996. if assigned(_funcretnode) then
  997. _funcretnode.free;
  998. _funcretnode := returnnode;
  999. { if the resultdef pass hasn't occurred yet, that one will do }
  1000. { everything }
  1001. if assigned(resultdef) then
  1002. begin
  1003. { these are returned as values, but we can optimize their loading }
  1004. { as well }
  1005. if is_ansistring(resultdef) or
  1006. is_widestring(resultdef) then
  1007. exit;
  1008. para := tcallparanode(left);
  1009. while assigned(para) do
  1010. begin
  1011. if (vo_is_hidden_para in para.parasym.varoptions) and
  1012. (vo_is_funcret in tparavarsym(para.parasym).varoptions) then
  1013. begin
  1014. para.left.free;
  1015. para.left := _funcretnode.getcopy;
  1016. exit;
  1017. end;
  1018. para := tcallparanode(para.right);
  1019. end;
  1020. { no hidden resultpara found, error! }
  1021. if not(po_inline in procdefinition.procoptions) then
  1022. internalerror(200306087);
  1023. end;
  1024. end;
  1025. destructor tcallnode.destroy;
  1026. begin
  1027. methodpointer.free;
  1028. methodpointerinit.free;
  1029. methodpointerdone.free;
  1030. _funcretnode.free;
  1031. if assigned(varargsparas) then
  1032. varargsparas.free;
  1033. inherited destroy;
  1034. end;
  1035. constructor tcallnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  1036. begin
  1037. methodpointerinit:=tblocknode(ppuloadnode(ppufile));
  1038. methodpointer:=ppuloadnode(ppufile);
  1039. methodpointerdone:=tblocknode(ppuloadnode(ppufile));
  1040. _funcretnode:=ppuloadnode(ppufile);
  1041. inherited ppuload(t,ppufile);
  1042. ppufile.getderef(symtableprocentryderef);
  1043. {$warning FIXME: No withsymtable support}
  1044. symtableproc:=nil;
  1045. ppufile.getderef(procdefinitionderef);
  1046. ppufile.getsmallset(callnodeflags);
  1047. end;
  1048. procedure tcallnode.ppuwrite(ppufile:tcompilerppufile);
  1049. begin
  1050. ppuwritenode(ppufile,methodpointerinit);
  1051. ppuwritenode(ppufile,methodpointer);
  1052. ppuwritenode(ppufile,methodpointerdone);
  1053. ppuwritenode(ppufile,_funcretnode);
  1054. inherited ppuwrite(ppufile);
  1055. ppufile.putderef(symtableprocentryderef);
  1056. ppufile.putderef(procdefinitionderef);
  1057. ppufile.putsmallset(callnodeflags);
  1058. end;
  1059. procedure tcallnode.derefnode;
  1060. begin
  1061. if assigned(methodpointerinit) then
  1062. methodpointerinit.derefnode;
  1063. if assigned(methodpointer) then
  1064. methodpointer.derefnode;
  1065. if assigned(methodpointerdone) then
  1066. methodpointerdone.derefnode;
  1067. if assigned(_funcretnode) then
  1068. _funcretnode.derefnode;
  1069. inherited derefnode;
  1070. end;
  1071. procedure tcallnode.buildderefimpl;
  1072. begin
  1073. inherited buildderefimpl;
  1074. symtableprocentryderef.build(symtableprocentry);
  1075. procdefinitionderef.build(procdefinition);
  1076. if assigned(methodpointer) then
  1077. methodpointer.buildderefimpl;
  1078. if assigned(methodpointerinit) then
  1079. methodpointerinit.buildderefimpl;
  1080. if assigned(methodpointerdone) then
  1081. methodpointerdone.buildderefimpl;
  1082. if assigned(_funcretnode) then
  1083. _funcretnode.buildderefimpl;
  1084. end;
  1085. procedure tcallnode.derefimpl;
  1086. var
  1087. pt : tcallparanode;
  1088. i : integer;
  1089. begin
  1090. inherited derefimpl;
  1091. symtableprocentry:=tprocsym(symtableprocentryderef.resolve);
  1092. if assigned(symtableprocentry) then
  1093. symtableproc:=symtableprocentry.owner;
  1094. procdefinition:=tabstractprocdef(procdefinitionderef.resolve);
  1095. if assigned(methodpointer) then
  1096. methodpointer.derefimpl;
  1097. if assigned(methodpointerinit) then
  1098. methodpointerinit.derefimpl;
  1099. if assigned(methodpointerdone) then
  1100. methodpointerdone.derefimpl;
  1101. if assigned(_funcretnode) then
  1102. _funcretnode.derefimpl;
  1103. { Connect parasyms }
  1104. pt:=tcallparanode(left);
  1105. while assigned(pt) and
  1106. (cpf_varargs_para in pt.callparaflags) do
  1107. pt:=tcallparanode(pt.right);
  1108. for i:=procdefinition.paras.count-1 downto 0 do
  1109. begin
  1110. if not assigned(pt) then
  1111. internalerror(200311077);
  1112. pt.parasym:=tparavarsym(procdefinition.paras[i]);
  1113. pt:=tcallparanode(pt.right);
  1114. end;
  1115. if assigned(pt) then
  1116. internalerror(200311078);
  1117. end;
  1118. function tcallnode.dogetcopy : tnode;
  1119. var
  1120. n : tcallnode;
  1121. i : integer;
  1122. hp,hpn : tparavarsym;
  1123. oldleft : tnode;
  1124. begin
  1125. { Need to use a hack here to prevent the parameters from being copied.
  1126. The parameters must be copied between methodpointerinit/methodpointerdone because
  1127. the can reference methodpointer }
  1128. oldleft:=left;
  1129. left:=nil;
  1130. n:=tcallnode(inherited dogetcopy);
  1131. left:=oldleft;
  1132. n.symtableprocentry:=symtableprocentry;
  1133. n.symtableproc:=symtableproc;
  1134. n.procdefinition:=procdefinition;
  1135. n.typedef := typedef;
  1136. n.callnodeflags := callnodeflags;
  1137. if assigned(methodpointerinit) then
  1138. n.methodpointerinit:=tblocknode(methodpointerinit.dogetcopy)
  1139. else
  1140. n.methodpointerinit:=nil;
  1141. { methodpointerinit is copied, now references to the temp will also be copied
  1142. correctly. We can now copy the parameters and methodpointer }
  1143. if assigned(left) then
  1144. n.left:=left.dogetcopy
  1145. else
  1146. n.left:=nil;
  1147. if assigned(methodpointer) then
  1148. n.methodpointer:=methodpointer.dogetcopy
  1149. else
  1150. n.methodpointer:=nil;
  1151. if assigned(methodpointerdone) then
  1152. n.methodpointerdone:=tblocknode(methodpointerdone.dogetcopy)
  1153. else
  1154. n.methodpointerdone:=nil;
  1155. if assigned(_funcretnode) then
  1156. n._funcretnode:=_funcretnode.dogetcopy
  1157. else
  1158. n._funcretnode:=nil;
  1159. if assigned(varargsparas) then
  1160. begin
  1161. n.varargsparas:=tvarargsparalist.create(true);
  1162. for i:=0 to varargsparas.count-1 do
  1163. begin
  1164. hp:=tparavarsym(varargsparas[i]);
  1165. hpn:=tparavarsym.create(hp.realname,hp.paranr,hp.varspez,hp.vardef,[]);
  1166. n.varargsparas.add(hpn);
  1167. end;
  1168. end
  1169. else
  1170. n.varargsparas:=nil;
  1171. result:=n;
  1172. end;
  1173. procedure tcallnode.insertintolist(l : tnodelist);
  1174. begin
  1175. end;
  1176. procedure tcallnode.convert_carg_array_of_const;
  1177. var
  1178. hp : tarrayconstructornode;
  1179. oldleft : tcallparanode;
  1180. begin
  1181. oldleft:=tcallparanode(left);
  1182. if oldleft.left.nodetype<>arrayconstructorn then
  1183. begin
  1184. CGMessage1(type_e_wrong_type_in_array_constructor,oldleft.left.resultdef.typename);
  1185. exit;
  1186. end;
  1187. include(callnodeflags,cnf_uses_varargs);
  1188. { Get arrayconstructor node and insert typeconvs }
  1189. hp:=tarrayconstructornode(oldleft.left);
  1190. { Add c args parameters }
  1191. { It could be an empty set }
  1192. if assigned(hp) and
  1193. assigned(hp.left) then
  1194. begin
  1195. while assigned(hp) do
  1196. begin
  1197. left:=ccallparanode.create(hp.left,left);
  1198. { set callparanode resultdef and flags }
  1199. left.resultdef:=hp.left.resultdef;
  1200. include(tcallparanode(left).callparaflags,cpf_varargs_para);
  1201. hp.left:=nil;
  1202. hp:=tarrayconstructornode(hp.right);
  1203. end;
  1204. end;
  1205. { Remove value of old array of const parameter, but keep it
  1206. in the list because it is required for bind_parasym.
  1207. Generate a nothign to keep callparanoed.left valid }
  1208. oldleft.left.free;
  1209. oldleft.left:=cnothingnode.create;
  1210. end;
  1211. procedure tcallnode.verifyabstract(sym:TObject;arg:pointer);
  1212. var
  1213. pd : tprocdef;
  1214. i : longint;
  1215. j : integer;
  1216. hs : string;
  1217. begin
  1218. if (tsym(sym).typ<>procsym) then
  1219. exit;
  1220. for i:=0 to tprocsym(sym).ProcdefList.Count-1 do
  1221. begin
  1222. pd:=tprocdef(tprocsym(sym).ProcdefList[i]);
  1223. hs:=pd.procsym.name+pd.typename_paras(false);
  1224. j:=AbstractMethodsList.FindIndexOf(hs);
  1225. if j<>-1 then
  1226. AbstractMethodsList[j]:=pd
  1227. else
  1228. AbstractMethodsList.Add(hs,pd);
  1229. end;
  1230. end;
  1231. procedure tcallnode.verifyabstractcalls;
  1232. var
  1233. objectdf : tobjectdef;
  1234. parents : tlinkedlist;
  1235. objectinfo : tobjectinfoitem;
  1236. stritem : TCmdStrListItem;
  1237. pd : tprocdef;
  1238. i : integer;
  1239. first : boolean;
  1240. begin
  1241. objectdf := nil;
  1242. { verify if trying to create an instance of a class which contains
  1243. non-implemented abstract methods }
  1244. { first verify this class type, no class than exit }
  1245. { also, this checking can only be done if the constructor is directly
  1246. called, indirect constructor calls cannot be checked.
  1247. }
  1248. if assigned(methodpointer) and
  1249. not (nf_is_self in methodpointer.flags) then
  1250. begin
  1251. if (methodpointer.resultdef.typ = objectdef) then
  1252. objectdf:=tobjectdef(methodpointer.resultdef)
  1253. else
  1254. if (methodpointer.resultdef.typ = classrefdef) and
  1255. (tclassrefdef(methodpointer.resultdef).pointeddef.typ = objectdef) and
  1256. (methodpointer.nodetype in [typen,loadvmtaddrn]) then
  1257. objectdf:=tobjectdef(tclassrefdef(methodpointer.resultdef).pointeddef);
  1258. end;
  1259. if not assigned(objectdf) then
  1260. exit;
  1261. parents := tlinkedlist.create;
  1262. AbstractMethodsList := TFPHashList.create;
  1263. { insert all parents in this class : the first item in the
  1264. list will be the base parent of the class .
  1265. }
  1266. while assigned(objectdf) do
  1267. begin
  1268. objectinfo:=tobjectinfoitem.create(objectdf);
  1269. parents.insert(objectinfo);
  1270. objectdf := objectdf.childof;
  1271. end;
  1272. { now all parents are in the correct order
  1273. insert all abstract methods in the list, and remove
  1274. those which are overriden by parent classes.
  1275. }
  1276. objectinfo:=tobjectinfoitem(parents.first);
  1277. while assigned(objectinfo) do
  1278. begin
  1279. objectdf := objectinfo.objinfo;
  1280. if assigned(objectdf.symtable) then
  1281. objectdf.symtable.SymList.ForEachCall(@verifyabstract,nil);
  1282. objectinfo:=tobjectinfoitem(objectinfo.next);
  1283. end;
  1284. if assigned(parents) then
  1285. parents.free;
  1286. { Finally give out a warning for each abstract method still in the list }
  1287. first:=true;
  1288. for i:=0 to AbstractMethodsList.Count-1 do
  1289. begin
  1290. pd:=tprocdef(AbstractMethodsList[i]);
  1291. if po_abstractmethod in pd.procoptions then
  1292. begin
  1293. if first then
  1294. begin
  1295. Message1(type_w_instance_with_abstract,objectdf.objrealname^);
  1296. first:=false;
  1297. end;
  1298. MessagePos1(pd.fileinfo,sym_h_abstract_method_list,pd.fullprocname(true));
  1299. end;
  1300. end;
  1301. if assigned(AbstractMethodsList) then
  1302. AbstractMethodsList.Free;
  1303. end;
  1304. function tcallnode.gen_self_tree_methodpointer:tnode;
  1305. var
  1306. hsym : tfieldvarsym;
  1307. begin
  1308. { find self field in methodpointer record }
  1309. hsym:=tfieldvarsym(trecorddef(methodpointertype).symtable.Find('self'));
  1310. if not assigned(hsym) then
  1311. internalerror(200305251);
  1312. { Load tmehodpointer(right).self }
  1313. result:=csubscriptnode.create(
  1314. hsym,
  1315. ctypeconvnode.create_internal(right.getcopy,methodpointertype));
  1316. end;
  1317. function tcallnode.gen_self_tree:tnode;
  1318. var
  1319. selftree : tnode;
  1320. begin
  1321. selftree:=nil;
  1322. { inherited }
  1323. if (cnf_inherited in callnodeflags) then
  1324. selftree:=load_self_node
  1325. else
  1326. { constructors }
  1327. if (procdefinition.proctypeoption=potype_constructor) then
  1328. begin
  1329. { push 0 as self when allocation is needed }
  1330. if (methodpointer.resultdef.typ=classrefdef) or
  1331. (cnf_new_call in callnodeflags) then
  1332. selftree:=cpointerconstnode.create(0,voidpointertype)
  1333. else
  1334. begin
  1335. if methodpointer.nodetype=typen then
  1336. selftree:=load_self_node
  1337. else
  1338. selftree:=methodpointer.getcopy;
  1339. end;
  1340. end
  1341. else
  1342. { Calling a static/class method }
  1343. if (po_classmethod in procdefinition.procoptions) or
  1344. (po_staticmethod in procdefinition.procoptions) then
  1345. begin
  1346. if (procdefinition.typ<>procdef) then
  1347. internalerror(200305062);
  1348. if (oo_has_vmt in tprocdef(procdefinition)._class.objectoptions) then
  1349. begin
  1350. { we only need the vmt, loading self is not required and there is no
  1351. need to check for typen, because that will always get the
  1352. loadvmtaddrnode added }
  1353. selftree:=methodpointer.getcopy;
  1354. if (methodpointer.resultdef.typ<>classrefdef) or
  1355. (methodpointer.nodetype = typen) then
  1356. selftree:=cloadvmtaddrnode.create(selftree);
  1357. end
  1358. else
  1359. selftree:=cpointerconstnode.create(0,voidpointertype);
  1360. end
  1361. else
  1362. begin
  1363. if methodpointer.nodetype=typen then
  1364. selftree:=load_self_node
  1365. else
  1366. selftree:=methodpointer.getcopy;
  1367. end;
  1368. result:=selftree;
  1369. end;
  1370. function tcallnode.gen_vmt_tree:tnode;
  1371. var
  1372. vmttree : tnode;
  1373. begin
  1374. vmttree:=nil;
  1375. if not(procdefinition.proctypeoption in [potype_constructor,potype_destructor]) then
  1376. internalerror(200305051);
  1377. { Handle classes and legacy objects separate to make it
  1378. more maintainable }
  1379. if (methodpointer.resultdef.typ=classrefdef) then
  1380. begin
  1381. if not is_class(tclassrefdef(methodpointer.resultdef).pointeddef) then
  1382. internalerror(200501041);
  1383. { constructor call via classreference => allocate memory }
  1384. if (procdefinition.proctypeoption=potype_constructor) then
  1385. begin
  1386. vmttree:=methodpointer.getcopy;
  1387. { Only a typenode can be passed when it is called with <class of xx>.create }
  1388. if vmttree.nodetype=typen then
  1389. vmttree:=cloadvmtaddrnode.create(vmttree);
  1390. end
  1391. else
  1392. begin
  1393. { Call afterconstruction }
  1394. vmttree:=cpointerconstnode.create(1,voidpointertype);
  1395. end;
  1396. end
  1397. else
  1398. { Class style objects }
  1399. if is_class(methodpointer.resultdef) then
  1400. begin
  1401. { inherited call, no create/destroy }
  1402. if (cnf_inherited in callnodeflags) then
  1403. vmttree:=cpointerconstnode.create(0,voidpointertype)
  1404. else
  1405. { do not create/destroy when called from member function
  1406. without specifying self explicit }
  1407. if (cnf_member_call in callnodeflags) then
  1408. begin
  1409. { destructor: don't release instance, vmt=0
  1410. constructor:
  1411. if called from a constructor in the same class then
  1412. don't call afterconstruction, vmt=0
  1413. else
  1414. call afterconstrution, vmt=1 }
  1415. if (procdefinition.proctypeoption=potype_destructor) then
  1416. vmttree:=cpointerconstnode.create(0,voidpointertype)
  1417. else if (current_procinfo.procdef.proctypeoption=potype_constructor) and
  1418. (procdefinition.proctypeoption=potype_constructor) then
  1419. vmttree:=cpointerconstnode.create(0,voidpointertype)
  1420. else
  1421. vmttree:=cpointerconstnode.create(1,voidpointertype);
  1422. end
  1423. else
  1424. { normal call to method like cl1.proc }
  1425. begin
  1426. { destructor:
  1427. if not called from exception block in constructor
  1428. call beforedestruction and release instance, vmt=1
  1429. else
  1430. don't call beforedestruction and release instance, vmt=-1
  1431. constructor:
  1432. if called from a constructor in the same class using self.create then
  1433. don't call afterconstruction, vmt=0
  1434. else
  1435. call afterconstrution, vmt=1 }
  1436. if (procdefinition.proctypeoption=potype_destructor) then
  1437. if not(cnf_create_failed in callnodeflags) then
  1438. vmttree:=cpointerconstnode.create(1,voidpointertype)
  1439. else
  1440. vmttree:=cpointerconstnode.create(TConstPtrUInt(-1),voidpointertype)
  1441. else
  1442. begin
  1443. if (current_procinfo.procdef.proctypeoption=potype_constructor) and
  1444. (procdefinition.proctypeoption=potype_constructor) and
  1445. (nf_is_self in methodpointer.flags) then
  1446. vmttree:=cpointerconstnode.create(0,voidpointertype)
  1447. else
  1448. vmttree:=cpointerconstnode.create(1,voidpointertype);
  1449. end;
  1450. end;
  1451. end
  1452. else
  1453. { Old style object }
  1454. begin
  1455. { constructor with extended syntax called from new }
  1456. if (cnf_new_call in callnodeflags) then
  1457. vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resultdef))
  1458. else
  1459. { destructor with extended syntax called from dispose }
  1460. if (cnf_dispose_call in callnodeflags) then
  1461. vmttree:=cloadvmtaddrnode.create(methodpointer.getcopy)
  1462. else
  1463. { inherited call, no create/destroy }
  1464. if (cnf_inherited in callnodeflags) then
  1465. vmttree:=cpointerconstnode.create(0,voidpointertype)
  1466. else
  1467. { do not create/destroy when called from member function
  1468. without specifying self explicit }
  1469. if (cnf_member_call in callnodeflags) then
  1470. begin
  1471. { destructor: don't release instance, vmt=0
  1472. constructor: don't initialize instance, vmt=0 }
  1473. vmttree:=cpointerconstnode.create(0,voidpointertype)
  1474. end
  1475. else
  1476. { normal object call like obj.proc }
  1477. begin
  1478. { destructor: direct call, no dispose, vmt=0
  1479. constructor: initialize object, load vmt }
  1480. if (procdefinition.proctypeoption=potype_constructor) then
  1481. begin
  1482. { old styled inherited call? }
  1483. if (methodpointer.nodetype=typen) then
  1484. vmttree:=cpointerconstnode.create(0,voidpointertype)
  1485. else
  1486. vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resultdef))
  1487. end
  1488. else
  1489. vmttree:=cpointerconstnode.create(0,voidpointertype);
  1490. end;
  1491. end;
  1492. result:=vmttree;
  1493. end;
  1494. type
  1495. pcallparanode = ^tcallparanode;
  1496. procedure tcallnode.bind_parasym;
  1497. var
  1498. i : integer;
  1499. pt : tcallparanode;
  1500. oldppt : pcallparanode;
  1501. varargspara,
  1502. currpara : tparavarsym;
  1503. used_by_callnode : boolean;
  1504. hiddentree : tnode;
  1505. newstatement : tstatementnode;
  1506. temp : ttempcreatenode;
  1507. begin
  1508. pt:=tcallparanode(left);
  1509. oldppt:=pcallparanode(@left);
  1510. { flag all callparanodes that belong to the varargs }
  1511. i:=paralength;
  1512. while (i>procdefinition.maxparacount) do
  1513. begin
  1514. include(pt.callparaflags,cpf_varargs_para);
  1515. oldppt:=pcallparanode(@pt.right);
  1516. pt:=tcallparanode(pt.right);
  1517. dec(i);
  1518. end;
  1519. { skip varargs that are inserted by array of const }
  1520. while assigned(pt) and
  1521. (cpf_varargs_para in pt.callparaflags) do
  1522. pt:=tcallparanode(pt.right);
  1523. { process normal parameters and insert hidden parameters }
  1524. for i:=procdefinition.paras.count-1 downto 0 do
  1525. begin
  1526. currpara:=tparavarsym(procdefinition.paras[i]);
  1527. if vo_is_hidden_para in currpara.varoptions then
  1528. begin
  1529. { generate hidden tree }
  1530. used_by_callnode:=false;
  1531. hiddentree:=nil;
  1532. if (vo_is_funcret in currpara.varoptions) then
  1533. begin
  1534. { Generate funcretnode if not specified }
  1535. if assigned(funcretnode) then
  1536. begin
  1537. hiddentree:=funcretnode.getcopy;
  1538. end
  1539. else
  1540. begin
  1541. hiddentree:=internalstatements(newstatement);
  1542. { need to use resultdef instead of procdefinition.returndef,
  1543. because they can be different }
  1544. temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  1545. addstatement(newstatement,temp);
  1546. addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
  1547. addstatement(newstatement,ctemprefnode.create(temp));
  1548. end;
  1549. end
  1550. else
  1551. if vo_is_high_para in currpara.varoptions then
  1552. begin
  1553. if not assigned(pt) or
  1554. (i=0) then
  1555. internalerror(200304082);
  1556. { we need the information of the previous parameter }
  1557. hiddentree:=gen_high_tree(pt.left,tparavarsym(procdefinition.paras[i-1]).vardef);
  1558. end
  1559. else
  1560. if vo_is_self in currpara.varoptions then
  1561. begin
  1562. if assigned(right) then
  1563. hiddentree:=gen_self_tree_methodpointer
  1564. else
  1565. hiddentree:=gen_self_tree;
  1566. end
  1567. else
  1568. if vo_is_vmt in currpara.varoptions then
  1569. begin
  1570. hiddentree:=gen_vmt_tree;
  1571. end
  1572. {$if defined(powerpc) or defined(m68k)}
  1573. else
  1574. if vo_is_syscall_lib in currpara.varoptions then
  1575. begin
  1576. { lib parameter has no special type but proccalloptions must be a syscall }
  1577. hiddentree:=cloadnode.create(tprocdef(procdefinition).libsym,tprocdef(procdefinition).libsym.owner);
  1578. end
  1579. {$endif powerpc or m68k}
  1580. else
  1581. if vo_is_parentfp in currpara.varoptions then
  1582. begin
  1583. if not(assigned(procdefinition.owner.defowner)) then
  1584. internalerror(200309287);
  1585. hiddentree:=cloadparentfpnode.create(tprocdef(procdefinition.owner.defowner));
  1586. end
  1587. else
  1588. if vo_is_range_check in currpara.varoptions then
  1589. begin
  1590. hiddentree:=cordconstnode.create(Ord(cs_check_range in current_settings.localswitches),booltype,false);
  1591. end
  1592. else
  1593. if vo_is_overflow_check in currpara.varoptions then
  1594. begin
  1595. hiddentree:=cordconstnode.create(Ord(cs_check_overflow in current_settings.localswitches),booltype,false);
  1596. end;
  1597. { add the hidden parameter }
  1598. if not assigned(hiddentree) then
  1599. internalerror(200304073);
  1600. { Already insert para and let the previous node point to
  1601. this new node }
  1602. pt:=ccallparanode.create(hiddentree,oldppt^);
  1603. pt.used_by_callnode:=used_by_callnode;
  1604. oldppt^:=pt;
  1605. end;
  1606. if not assigned(pt) then
  1607. internalerror(200310052);
  1608. pt.parasym:=currpara;
  1609. oldppt:=pcallparanode(@pt.right);
  1610. pt:=tcallparanode(pt.right);
  1611. end;
  1612. { Create parasyms for varargs, first count the number of varargs paras,
  1613. then insert the parameters with numbering in reverse order. The SortParas
  1614. will set the correct order at the end}
  1615. pt:=tcallparanode(left);
  1616. i:=0;
  1617. while assigned(pt) do
  1618. begin
  1619. if cpf_varargs_para in pt.callparaflags then
  1620. inc(i);
  1621. pt:=tcallparanode(pt.right);
  1622. end;
  1623. if (i>0) then
  1624. begin
  1625. varargsparas:=tvarargsparalist.create;
  1626. pt:=tcallparanode(left);
  1627. while assigned(pt) do
  1628. begin
  1629. if cpf_varargs_para in pt.callparaflags then
  1630. begin
  1631. varargspara:=tparavarsym.create('va'+tostr(i),i,vs_value,pt.resultdef,[]);
  1632. dec(i);
  1633. { varargspara is left-right, use insert
  1634. instead of concat }
  1635. varargsparas.add(varargspara);
  1636. pt.parasym:=varargspara;
  1637. end;
  1638. pt:=tcallparanode(pt.right);
  1639. end;
  1640. varargsparas.sortparas;
  1641. end;
  1642. end;
  1643. function tcallnode.pass_typecheck:tnode;
  1644. var
  1645. candidates : tcallcandidates;
  1646. oldcallnode : tcallnode;
  1647. hpt : tnode;
  1648. pt : tcallparanode;
  1649. lastpara : longint;
  1650. paraidx,
  1651. cand_cnt : integer;
  1652. i : longint;
  1653. is_const : boolean;
  1654. statements : tstatementnode;
  1655. converted_result_data : ttempcreatenode;
  1656. label
  1657. errorexit;
  1658. begin
  1659. result:=nil;
  1660. candidates:=nil;
  1661. oldcallnode:=aktcallnode;
  1662. aktcallnode:=self;
  1663. { determine length of parameter list }
  1664. pt:=tcallparanode(left);
  1665. paralength:=0;
  1666. while assigned(pt) do
  1667. begin
  1668. inc(paralength);
  1669. pt:=tcallparanode(pt.right);
  1670. end;
  1671. { determine the type of the parameters }
  1672. if assigned(left) then
  1673. begin
  1674. tcallparanode(left).get_paratype;
  1675. if codegenerror then
  1676. goto errorexit;
  1677. end;
  1678. if assigned(methodpointer) then
  1679. begin
  1680. typecheckpass(methodpointer);
  1681. maybe_load_para_in_temp(methodpointer);
  1682. end;
  1683. { procedure variable ? }
  1684. if assigned(right) then
  1685. begin
  1686. set_varstate(right,vs_read,[vsf_must_be_valid]);
  1687. typecheckpass(right);
  1688. if codegenerror then
  1689. exit;
  1690. procdefinition:=tabstractprocdef(right.resultdef);
  1691. { Compare parameters from right to left }
  1692. paraidx:=procdefinition.Paras.count-1;
  1693. { Skip default parameters }
  1694. if not(po_varargs in procdefinition.procoptions) then
  1695. begin
  1696. { ignore hidden parameters }
  1697. while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
  1698. dec(paraidx);
  1699. for i:=1 to procdefinition.maxparacount-paralength do
  1700. begin
  1701. if paraidx<0 then
  1702. internalerror(200402261);
  1703. if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
  1704. begin
  1705. CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
  1706. goto errorexit;
  1707. end;
  1708. dec(paraidx);
  1709. end;
  1710. end;
  1711. while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
  1712. dec(paraidx);
  1713. pt:=tcallparanode(left);
  1714. lastpara:=paralength;
  1715. while (paraidx>=0) and assigned(pt) do
  1716. begin
  1717. { only goto next para if we're out of the varargs }
  1718. if not(po_varargs in procdefinition.procoptions) or
  1719. (lastpara<=procdefinition.maxparacount) then
  1720. begin
  1721. repeat
  1722. dec(paraidx);
  1723. until (paraidx<0) or not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
  1724. end;
  1725. pt:=tcallparanode(pt.right);
  1726. dec(lastpara);
  1727. end;
  1728. if assigned(pt) or
  1729. ((paraidx>=0) and
  1730. not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)) then
  1731. begin
  1732. if assigned(pt) then
  1733. current_filepos:=pt.fileinfo;
  1734. CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
  1735. goto errorexit;
  1736. end;
  1737. end
  1738. else
  1739. { not a procedure variable }
  1740. begin
  1741. { do we know the procedure to call ? }
  1742. if not(assigned(procdefinition)) then
  1743. begin
  1744. candidates:=tcallcandidates.create(symtableprocentry,symtableproc,left,(nf_isproperty in flags),
  1745. { ignore possible private in delphi mode for anon. inherited (FK) }
  1746. (m_delphi in current_settings.modeswitches) and (cnf_anon_inherited in callnodeflags));
  1747. { no procedures found? then there is something wrong
  1748. with the parameter size or the procedures are
  1749. not accessible }
  1750. if candidates.count=0 then
  1751. begin
  1752. { when it's an auto inherited call and there
  1753. is no procedure found, but the procedures
  1754. were defined with overload directive and at
  1755. least two procedures are defined then we ignore
  1756. this inherited by inserting a nothingn. Only
  1757. do this ugly hack in Delphi mode as it looks more
  1758. like a bug. It's also not documented }
  1759. if (m_delphi in current_settings.modeswitches) and
  1760. (cnf_anon_inherited in callnodeflags) and
  1761. (symtableprocentry.owner.symtabletype=ObjectSymtable) and
  1762. (po_overload in tprocdef(symtableprocentry.ProcdefList[0]).procoptions) and
  1763. (symtableprocentry.ProcdefList.Count>=2) then
  1764. result:=cnothingnode.create
  1765. else
  1766. begin
  1767. { in tp mode we can try to convert to procvar if
  1768. there are no parameters specified }
  1769. if not(assigned(left)) and
  1770. not(cnf_inherited in callnodeflags) and
  1771. ((m_tp_procvar in current_settings.modeswitches) or
  1772. (m_mac_procvar in current_settings.modeswitches)) and
  1773. (not assigned(methodpointer) or
  1774. (methodpointer.nodetype <> typen)) then
  1775. begin
  1776. hpt:=cloadnode.create(tprocsym(symtableprocentry),symtableproc);
  1777. if assigned(methodpointer) then
  1778. tloadnode(hpt).set_mp(get_load_methodpointer);
  1779. typecheckpass(hpt);
  1780. result:=hpt;
  1781. end
  1782. else
  1783. begin
  1784. if assigned(left) then
  1785. current_filepos:=left.fileinfo;
  1786. CGMessage1(parser_e_wrong_parameter_size,symtableprocentry.realname);
  1787. symtableprocentry.write_parameter_lists(nil);
  1788. end;
  1789. end;
  1790. goto errorexit;
  1791. end;
  1792. { Retrieve information about the candidates }
  1793. candidates.get_information;
  1794. {$ifdef EXTDEBUG}
  1795. { Display info when multiple candidates are found }
  1796. if candidates.count>1 then
  1797. candidates.dump_info(V_Debug);
  1798. {$endif EXTDEBUG}
  1799. { Choose the best candidate and count the number of
  1800. candidates left }
  1801. cand_cnt:=candidates.choose_best(procdefinition,
  1802. assigned(left) and
  1803. not assigned(tcallparanode(left).right) and
  1804. (tcallparanode(left).left.resultdef.typ=variantdef));
  1805. { All parameters are checked, check if there are any
  1806. procedures left }
  1807. if cand_cnt>0 then
  1808. begin
  1809. { Multiple candidates left? }
  1810. if cand_cnt>1 then
  1811. begin
  1812. CGMessage(type_e_cant_choose_overload_function);
  1813. {$ifdef EXTDEBUG}
  1814. candidates.dump_info(V_Hint);
  1815. {$else EXTDEBUG}
  1816. candidates.list(false);
  1817. {$endif EXTDEBUG}
  1818. { we'll just use the first candidate to make the
  1819. call }
  1820. end;
  1821. { assign procdefinition }
  1822. if symtableproc=nil then
  1823. symtableproc:=procdefinition.owner;
  1824. end
  1825. else
  1826. begin
  1827. { No candidates left, this must be a type error,
  1828. because wrong size is already checked. procdefinition
  1829. is filled with the first (random) definition that is
  1830. found. We use this definition to display a nice error
  1831. message that the wrong type is passed }
  1832. candidates.find_wrong_para;
  1833. candidates.list(true);
  1834. {$ifdef EXTDEBUG}
  1835. candidates.dump_info(V_Hint);
  1836. {$endif EXTDEBUG}
  1837. { We can not proceed, release all procs and exit }
  1838. candidates.free;
  1839. goto errorexit;
  1840. end;
  1841. candidates.free;
  1842. end; { end of procedure to call determination }
  1843. end;
  1844. { check for hints (deprecated etc) }
  1845. if (procdefinition.typ = procdef) then
  1846. check_hints(tprocdef(procdefinition).procsym,tprocdef(procdefinition).symoptions);
  1847. { add needed default parameters }
  1848. if assigned(procdefinition) and
  1849. (paralength<procdefinition.maxparacount) then
  1850. begin
  1851. paraidx:=0;
  1852. i:=0;
  1853. while (i<paralength) do
  1854. begin
  1855. if paraidx>=procdefinition.Paras.count then
  1856. internalerror(200306181);
  1857. if not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) then
  1858. inc(i);
  1859. inc(paraidx);
  1860. end;
  1861. while (paraidx<procdefinition.paras.count) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
  1862. inc(paraidx);
  1863. while (paraidx<procdefinition.paras.count) do
  1864. begin
  1865. if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
  1866. internalerror(200212142);
  1867. left:=ccallparanode.create(genconstsymtree(
  1868. tconstsym(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)),left);
  1869. { Ignore vs_hidden parameters }
  1870. repeat
  1871. inc(paraidx);
  1872. until (paraidx>=procdefinition.paras.count) or not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
  1873. end;
  1874. end;
  1875. { recursive call? }
  1876. if assigned(current_procinfo) and
  1877. (procdefinition=current_procinfo.procdef) then
  1878. include(current_procinfo.flags,pi_is_recursive);
  1879. { handle predefined procedures }
  1880. is_const:=(po_internconst in procdefinition.procoptions) and
  1881. ((block_type in [bt_const,bt_type]) or
  1882. (assigned(left) and (tcallparanode(left).left.nodetype in [realconstn,ordconstn])));
  1883. if (procdefinition.proccalloption=pocall_internproc) or is_const then
  1884. begin
  1885. if assigned(left) then
  1886. begin
  1887. { ptr and settextbuf needs two args }
  1888. if assigned(tcallparanode(left).right) then
  1889. begin
  1890. hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,left);
  1891. left:=nil;
  1892. end
  1893. else
  1894. begin
  1895. hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,tcallparanode(left).left);
  1896. tcallparanode(left).left:=nil;
  1897. end;
  1898. end
  1899. else
  1900. hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,nil);
  1901. result:=hpt;
  1902. goto errorexit;
  1903. end;
  1904. { ensure that the result type is set }
  1905. if not(cnf_typedefset in callnodeflags) then
  1906. begin
  1907. { constructors return their current class type, not the type where the
  1908. constructor is declared, this can be different because of inheritance }
  1909. if (procdefinition.proctypeoption=potype_constructor) and
  1910. assigned(methodpointer) and
  1911. assigned(methodpointer.resultdef) and
  1912. (methodpointer.resultdef.typ=classrefdef) then
  1913. resultdef:=tclassrefdef(methodpointer.resultdef).pointeddef
  1914. else
  1915. { Member call to a (inherited) constructor from the class, the return
  1916. value is always self, so we change it to voidtype to generate an
  1917. error and to prevent users from generating non-working code
  1918. when they expect to clone the current instance, see bug 3662 (PFV) }
  1919. if (procdefinition.proctypeoption=potype_constructor) and
  1920. is_class(tprocdef(procdefinition)._class) and
  1921. assigned(methodpointer) and
  1922. (nf_is_self in methodpointer.flags) then
  1923. resultdef:=voidtype
  1924. else
  1925. resultdef:=procdefinition.returndef;
  1926. end
  1927. else
  1928. resultdef:=typedef;
  1929. {if resultdef.needs_inittable then
  1930. include(current_procinfo.flags,pi_needs_implicit_finally);}
  1931. if assigned(methodpointer) then
  1932. begin
  1933. { when methodpointer is a callnode we must load it first into a
  1934. temp to prevent the processing callnode twice }
  1935. if (methodpointer.nodetype=calln) then
  1936. internalerror(200405121);
  1937. { direct call to inherited abstract method, then we
  1938. can already give a error in the compiler instead
  1939. of a runtime error }
  1940. if (cnf_inherited in callnodeflags) and
  1941. (po_abstractmethod in procdefinition.procoptions) then
  1942. begin
  1943. if (m_delphi in current_settings.modeswitches) and
  1944. (cnf_anon_inherited in callnodeflags) then
  1945. begin
  1946. CGMessage(cg_h_inherited_ignored);
  1947. result:=cnothingnode.create;
  1948. exit;
  1949. end
  1950. else
  1951. CGMessage(cg_e_cant_call_abstract_method);
  1952. end;
  1953. { if an inherited con- or destructor should be }
  1954. { called in a con- or destructor then a warning }
  1955. { will be made }
  1956. { con- and destructors need a pointer to the vmt }
  1957. if (cnf_inherited in callnodeflags) and
  1958. (procdefinition.proctypeoption in [potype_constructor,potype_destructor]) and
  1959. is_object(methodpointer.resultdef) and
  1960. not(current_procinfo.procdef.proctypeoption in [potype_constructor,potype_destructor]) then
  1961. CGMessage(cg_w_member_cd_call_from_method);
  1962. if methodpointer.nodetype<>typen then
  1963. begin
  1964. { Remove all postfix operators }
  1965. hpt:=methodpointer;
  1966. while assigned(hpt) and (hpt.nodetype in [subscriptn,vecn]) do
  1967. hpt:=tunarynode(hpt).left;
  1968. if (procdefinition.proctypeoption=potype_constructor) and
  1969. assigned(symtableproc) and
  1970. (symtableproc.symtabletype=withsymtable) and
  1971. (tnode(twithsymtable(symtableproc).withrefnode).nodetype=temprefn) then
  1972. CGmessage(cg_e_cannot_call_cons_dest_inside_with);
  1973. { R.Init then R will be initialized by the constructor,
  1974. Also allow it for simple loads }
  1975. if (procdefinition.proctypeoption=potype_constructor) or
  1976. ((hpt.nodetype=loadn) and
  1977. (methodpointer.resultdef.typ=objectdef) and
  1978. not(oo_has_virtual in tobjectdef(methodpointer.resultdef).objectoptions)
  1979. ) then
  1980. { a constructor will and a method may write something to }
  1981. { the fields }
  1982. set_varstate(methodpointer,vs_readwritten,[])
  1983. else if ((hpt.nodetype=loadn) and
  1984. (methodpointer.resultdef.typ=classrefdef)) then
  1985. set_varstate(methodpointer,vs_read,[])
  1986. else
  1987. set_varstate(methodpointer,vs_read,[vsf_must_be_valid]);
  1988. { The object is already used if it is called once }
  1989. if (hpt.nodetype=loadn) and
  1990. (tloadnode(hpt).symtableentry.typ in [localvarsym,paravarsym,staticvarsym]) then
  1991. set_varstate(hpt,vs_read,[]);
  1992. // tabstractvarsym(tloadnode(hpt).symtableentry).varstate:=vs_readwritten;
  1993. end;
  1994. { if we are calling the constructor check for abstract
  1995. methods. Ignore inherited and member calls, because the
  1996. class is then already created }
  1997. if (procdefinition.proctypeoption=potype_constructor) and
  1998. not(cnf_inherited in callnodeflags) and
  1999. not(cnf_member_call in callnodeflags) then
  2000. verifyabstractcalls;
  2001. end
  2002. else
  2003. begin
  2004. { When this is method the methodpointer must be available }
  2005. if (right=nil) and
  2006. (procdefinition.owner.symtabletype=ObjectSymtable) then
  2007. internalerror(200305061);
  2008. end;
  2009. { Set flag that the procedure uses varargs, also if they are not passed it is still
  2010. needed for x86_64 to pass the number of SSE registers used }
  2011. if po_varargs in procdefinition.procoptions then
  2012. include(callnodeflags,cnf_uses_varargs);
  2013. { Change loading of array of const to varargs }
  2014. if assigned(left) and
  2015. is_array_of_const(tparavarsym(procdefinition.paras[procdefinition.paras.count-1]).vardef) and
  2016. (procdefinition.proccalloption in [pocall_cppdecl,pocall_cdecl]) then
  2017. convert_carg_array_of_const;
  2018. { bind parasyms to the callparanodes and insert hidden parameters }
  2019. bind_parasym;
  2020. { insert type conversions for parameters }
  2021. if assigned(left) then
  2022. tcallparanode(left).insert_typeconv(true);
  2023. { dispinterface methode invoke? }
  2024. if assigned(methodpointer) and is_dispinterface(methodpointer.resultdef) then
  2025. begin
  2026. { if the result is used, we've to insert a call to convert the type to be on the "safe side" }
  2027. if cnf_return_value_used in callnodeflags then
  2028. begin
  2029. result:=internalstatements(statements);
  2030. converted_result_data:=ctempcreatenode.create(procdefinition.returndef,sizeof(procdefinition.returndef),tt_persistent,true);
  2031. addstatement(statements,converted_result_data);
  2032. addstatement(statements,cassignmentnode.create(ctemprefnode.create(converted_result_data),
  2033. ctypeconvnode.create_internal(translate_disp_call(methodpointer,parameters,'',tprocdef(procdefinition).dispid),
  2034. procdefinition.returndef)));
  2035. addstatement(statements,ctempdeletenode.create_normal_temp(converted_result_data));
  2036. addstatement(statements,ctemprefnode.create(converted_result_data));
  2037. end
  2038. else
  2039. result:=translate_disp_call(methodpointer,parameters,'',tprocdef(procdefinition).dispid);
  2040. { don't free reused nodes }
  2041. methodpointer:=nil;
  2042. parameters:=nil;
  2043. end;
  2044. errorexit:
  2045. aktcallnode:=oldcallnode;
  2046. end;
  2047. procedure tcallnode.order_parameters;
  2048. var
  2049. hp,hpcurr,hpnext,hpfirst,hpprev : tcallparanode;
  2050. currloc : tcgloc;
  2051. begin
  2052. hpfirst:=nil;
  2053. hpcurr:=tcallparanode(left);
  2054. while assigned(hpcurr) do
  2055. begin
  2056. { pull out }
  2057. hpnext:=tcallparanode(hpcurr.right);
  2058. { pull in at the correct place.
  2059. Used order:
  2060. 1. LOC_REFERENCE with smallest offset (x86 only)
  2061. 2. LOC_REFERENCE with most registers
  2062. 3. LOC_REGISTER with most registers
  2063. For the moment we only look at the first parameter field. Combining it
  2064. with multiple parameter fields will make things a lot complexer (PFV) }
  2065. if not assigned(hpcurr.parasym.paraloc[callerside].location) then
  2066. internalerror(200412152);
  2067. currloc:=hpcurr.parasym.paraloc[callerside].location^.loc;
  2068. hpprev:=nil;
  2069. hp:=hpfirst;
  2070. while assigned(hp) do
  2071. begin
  2072. case currloc of
  2073. LOC_REFERENCE :
  2074. begin
  2075. case hp.parasym.paraloc[callerside].location^.loc of
  2076. LOC_REFERENCE :
  2077. begin
  2078. { Offset is calculated like:
  2079. sub esp,12
  2080. mov [esp+8],para3
  2081. mov [esp+4],para2
  2082. mov [esp],para1
  2083. call function
  2084. That means the for pushes the para with the
  2085. highest offset (see para3) needs to be pushed first
  2086. }
  2087. if (hpcurr.registersint>hp.registersint)
  2088. {$ifdef x86}
  2089. or (hpcurr.parasym.paraloc[callerside].location^.reference.offset>hp.parasym.paraloc[callerside].location^.reference.offset)
  2090. {$endif x86}
  2091. then
  2092. break;
  2093. end;
  2094. LOC_REGISTER,
  2095. LOC_FPUREGISTER :
  2096. break;
  2097. end;
  2098. end;
  2099. LOC_FPUREGISTER,
  2100. LOC_REGISTER :
  2101. begin
  2102. if (hp.parasym.paraloc[callerside].location^.loc=currloc) and
  2103. (hpcurr.registersint>hp.registersint) then
  2104. break;
  2105. end;
  2106. end;
  2107. hpprev:=hp;
  2108. hp:=tcallparanode(hp.right);
  2109. end;
  2110. hpcurr.right:=hp;
  2111. if assigned(hpprev) then
  2112. hpprev.right:=hpcurr
  2113. else
  2114. hpfirst:=hpcurr;
  2115. { next }
  2116. hpcurr:=hpnext;
  2117. end;
  2118. left:=hpfirst;
  2119. end;
  2120. function tcallnode.replaceparaload(var n: tnode; arg: pointer): foreachnoderesult;
  2121. var
  2122. paras: tcallparanode;
  2123. temp: tnode;
  2124. indexnr : integer;
  2125. begin
  2126. result := fen_false;
  2127. n.fileinfo := pfileposinfo(arg)^;
  2128. if (n.nodetype = loadn) then
  2129. begin
  2130. case tloadnode(n).symtableentry.typ of
  2131. paravarsym :
  2132. begin
  2133. paras := tcallparanode(left);
  2134. while assigned(paras) and
  2135. (paras.parasym <> tloadnode(n).symtableentry) do
  2136. paras := tcallparanode(paras.right);
  2137. if assigned(paras) then
  2138. begin
  2139. n.free;
  2140. n := paras.left.getcopy;
  2141. typecheckpass(n);
  2142. result := fen_true;
  2143. end;
  2144. end;
  2145. localvarsym :
  2146. begin
  2147. { local? }
  2148. if (tloadnode(n).symtableentry.owner <> tprocdef(procdefinition).localst) then
  2149. exit;
  2150. indexnr:=tloadnode(n).symtableentry.owner.SymList.IndexOf(tloadnode(n).symtableentry);
  2151. if (indexnr >= inlinelocals.count) or
  2152. not assigned(inlinelocals[indexnr]) then
  2153. internalerror(20040720);
  2154. temp := tnode(inlinelocals[indexnr]).getcopy;
  2155. n.free;
  2156. n := temp;
  2157. typecheckpass(n);
  2158. result := fen_true;
  2159. end;
  2160. end;
  2161. end;
  2162. end;
  2163. type
  2164. ptempnodes = ^ttempnodes;
  2165. ttempnodes = record
  2166. createstatement, deletestatement: tstatementnode;
  2167. end;
  2168. procedure tcallnode.createlocaltemps(p:TObject;arg:pointer);
  2169. var
  2170. tempinfo: ptempnodes absolute arg;
  2171. tempnode: ttempcreatenode;
  2172. indexnr : integer;
  2173. begin
  2174. if (TSym(p).typ <> localvarsym) then
  2175. exit;
  2176. indexnr:=TSym(p).Owner.SymList.IndexOf(p);
  2177. if (indexnr >= inlinelocals.count) then
  2178. inlinelocals.count:=indexnr+10;
  2179. if (vo_is_funcret in tabstractvarsym(p).varoptions) and
  2180. assigned(funcretnode) then
  2181. begin
  2182. if node_complexity(funcretnode) > 1 then
  2183. begin
  2184. { can this happen? }
  2185. { we may have to replace the funcretnode with the address of funcretnode }
  2186. { loaded in a temp in this case, because the expression may e.g. contain }
  2187. { a global variable that gets changed inside the function }
  2188. internalerror(2004072101);
  2189. end;
  2190. inlinelocals[indexnr] := funcretnode.getcopy
  2191. end
  2192. else
  2193. begin
  2194. tempnode := ctempcreatenode.create(tabstractvarsym(p).vardef,tabstractvarsym(p).vardef.size,tt_persistent,tabstractvarsym(p).is_regvar(false));
  2195. addstatement(tempinfo^.createstatement,tempnode);
  2196. if (vo_is_funcret in tlocalvarsym(p).varoptions) then
  2197. begin
  2198. funcretnode := ctemprefnode.create(tempnode);
  2199. addstatement(tempinfo^.deletestatement,ctempdeletenode.create_normal_temp(tempnode));
  2200. end
  2201. else
  2202. addstatement(tempinfo^.deletestatement,ctempdeletenode.create(tempnode));
  2203. inlinelocals[indexnr] := ctemprefnode.create(tempnode);
  2204. end;
  2205. end;
  2206. function nonlocalvars(var n: tnode; arg: pointer): foreachnoderesult;
  2207. begin
  2208. result := fen_false;
  2209. { this is just to play it safe, there are more safe situations }
  2210. if (n.nodetype = derefn) or
  2211. ((n.nodetype = loadn) and
  2212. { globals and fields of (possibly global) objects could always be changed in the callee }
  2213. ((tloadnode(n).symtable.symtabletype in [globalsymtable,ObjectSymtable]) or
  2214. { statics can only be modified by functions in the same unit }
  2215. ((tloadnode(n).symtable.symtabletype = staticsymtable) and
  2216. (tloadnode(n).symtable = TSymtable(arg))))) or
  2217. ((n.nodetype = subscriptn) and
  2218. (tsubscriptnode(n).vs.owner.symtabletype = ObjectSymtable)) then
  2219. result := fen_norecurse_true;
  2220. end;
  2221. procedure tcallnode.createinlineparas(var createstatement, deletestatement: tstatementnode);
  2222. var
  2223. para: tcallparanode;
  2224. tempnode: ttempcreatenode;
  2225. tempnodes: ttempnodes;
  2226. n: tnode;
  2227. paracomplexity: longint;
  2228. begin
  2229. { parameters }
  2230. para := tcallparanode(left);
  2231. while assigned(para) do
  2232. begin
  2233. if (para.parasym.typ = paravarsym) and
  2234. { para.left will already be the same as funcretnode in the following case, so don't change }
  2235. (not(vo_is_funcret in tparavarsym(para.parasym).varoptions) or
  2236. (not assigned(funcretnode))) then
  2237. begin
  2238. { must take copy of para.left, because if it contains a }
  2239. { temprefn pointing to a copied temp (e.g. methodpointer), }
  2240. { then this parameter must be changed to point to the copy of }
  2241. { that temp (JM) }
  2242. n := para.left.getcopy;
  2243. para.left.free;
  2244. para.left := n;
  2245. firstpass(para.left);
  2246. { create temps for value parameters, function result and also for }
  2247. { const parameters which are passed by value instead of by reference }
  2248. { we need to take care that we use the type of the defined parameter and not of the
  2249. passed parameter, because these can be different in case of a formaldef (PFV) }
  2250. paracomplexity := node_complexity(para.left);
  2251. { check if we have to create a temp, assign the parameter's }
  2252. { contents to that temp and then substitute the paramter }
  2253. { with the temp everywhere in the function }
  2254. if
  2255. ((tparavarsym(para.parasym).varregable in [vr_none,vr_addr]) and
  2256. not(para.left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE])) or
  2257. { we can't assign to formaldef temps }
  2258. ((para.parasym.vardef.typ<>formaldef) and
  2259. (
  2260. { if paracomplexity > 1, we normally take the address of }
  2261. { the parameter expression, store it in a temp and }
  2262. { substitute the dereferenced temp in the inlined function }
  2263. { We can't do this if we can't take the address of the }
  2264. { parameter expression, so in that case assign to a temp }
  2265. not(para.left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CONSTANT]) or
  2266. ((paracomplexity > 1) and
  2267. (not valid_for_addr(para.left,false) or
  2268. (para.left.nodetype = calln) or
  2269. is_constnode(para.left))) or
  2270. { the problem is that we can't take the address of a function result :( }
  2271. (vo_is_funcret in tparavarsym(para.parasym).varoptions) or
  2272. { we do not need to create a temp for value parameters }
  2273. { which are not modified in the inlined function }
  2274. { const parameters can get vs_readwritten if their }
  2275. { address is taken }
  2276. ((((para.parasym.varspez = vs_value) and
  2277. (para.parasym.varstate in [vs_initialised,vs_declared,vs_read])) or
  2278. { in case of const, this is only necessary if the }
  2279. { variable would be passed by value normally, or if }
  2280. { there is such a variable somewhere in an expression }
  2281. ((para.parasym.varspez = vs_const) and
  2282. (not paramanager.push_addr_param(vs_const,para.parasym.vardef,procdefinition.proccalloption) or
  2283. (paracomplexity > 1)))) and
  2284. { however, if we pass a global variable, an object field or}
  2285. { an expression containing a pointer dereference as }
  2286. { parameter, this value could be modified in other ways as }
  2287. { well and in such cases create a temp to be on the safe }
  2288. { side }
  2289. foreachnodestatic(para.left,@nonlocalvars,pointer(symtableproc))) or
  2290. { value parameters of which we know they are modified by }
  2291. { definition have to be copied to a temp }
  2292. ((para.parasym.varspez = vs_value) and
  2293. not(para.parasym.varstate in [vs_initialised,vs_declared,vs_read])) or
  2294. { the compiler expects that it can take the address of parameters passed by reference in
  2295. the case of const so we can't replace the node simply by a constant node
  2296. When playing with this code, ensure that
  2297. function f(const a,b : longint) : longint;inline;
  2298. begin
  2299. result:=a*b;
  2300. end;
  2301. [...]
  2302. ...:=f(10,20));
  2303. [...]
  2304. is still folded. (FK)
  2305. }
  2306. ((para.parasym.varspez = vs_const) and
  2307. { const para's can get vs_readwritten if their address }
  2308. { is taken }
  2309. ((para.parasym.varstate = vs_readwritten) or
  2310. { call-by-reference const's may need to be passed by }
  2311. { reference to function called in the inlined code }
  2312. (paramanager.push_addr_param(vs_const,para.parasym.vardef,procdefinition.proccalloption) and
  2313. (not valid_for_addr(para.left,false) or
  2314. is_constnode(para.left)))))
  2315. )
  2316. ) then
  2317. begin
  2318. tempnode:=nil;
  2319. {$ifdef reuse_existing_para_temp}
  2320. { Try to reuse existing result tempnode from a parameter }
  2321. if para.left.nodetype=blockn then
  2322. begin
  2323. n:=tstatementnode(tblocknode(para.left).left);
  2324. while assigned(n) and assigned(tstatementnode(n).right) do
  2325. begin
  2326. if tstatementnode(n).left.nodetype=tempdeleten then
  2327. break;
  2328. n:=tstatementnode(tstatementnode(n).right);
  2329. end;
  2330. { We expect to find the following statements
  2331. tempdeletenode
  2332. tempref
  2333. nil }
  2334. if assigned(n) and
  2335. assigned(tstatementnode(n).right) and
  2336. (tstatementnode(tstatementnode(n).right).right=nil) and
  2337. (tstatementnode(tstatementnode(n).right).left.nodetype=temprefn) then
  2338. begin
  2339. tempnode:=ttempdeletenode(tstatementnode(n).left).tempinfo^.owner;
  2340. para.left:=tstatementnode(tstatementnode(n).right).left;
  2341. addstatement(deletestatement,tstatementnode(n).left);
  2342. { Replace tempdelete,tempref with dummy statement }
  2343. tstatementnode(n).left:=cnothingnode.create;
  2344. tstatementnode(tstatementnode(n).right).left:=cnothingnode.create;
  2345. end;
  2346. end;
  2347. {$endif reuse_existing_para_temp}
  2348. tempnode := ctempcreatenode.create(para.parasym.vardef,para.parasym.vardef.size,tt_persistent,tparavarsym(para.parasym).is_regvar(false));
  2349. addstatement(createstatement,tempnode);
  2350. { assign the value of the parameter to the temp, except in case of the function result }
  2351. { (in that case, para.left is a block containing the creation of a new temp, while we }
  2352. { only need a temprefnode, so delete the old stuff) }
  2353. if not(vo_is_funcret in tparavarsym(para.parasym).varoptions) then
  2354. begin
  2355. addstatement(createstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
  2356. para.left));
  2357. para.left := ctemprefnode.create(tempnode);
  2358. addstatement(deletestatement,ctempdeletenode.create(tempnode));
  2359. end
  2360. else
  2361. begin
  2362. if not(assigned(funcretnode)) then
  2363. funcretnode := ctemprefnode.create(tempnode);
  2364. para.left.free;
  2365. para.left := ctemprefnode.create(tempnode);
  2366. addstatement(deletestatement,ctempdeletenode.create_normal_temp(tempnode));
  2367. end;
  2368. end
  2369. { otherwise if the parameter is "complex", take the address }
  2370. { of the parameter expression, store it in a temp and replace }
  2371. { occurrences of the parameter with dereferencings of this }
  2372. { temp }
  2373. else if (paracomplexity > 1) then
  2374. begin
  2375. tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,tparavarsym(para.parasym).is_regvar(true));
  2376. addstatement(createstatement,tempnode);
  2377. addstatement(createstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
  2378. caddrnode.create_internal(para.left)));
  2379. para.left := ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),para.left.resultdef);
  2380. addstatement(deletestatement,ctempdeletenode.create(tempnode));
  2381. end;
  2382. end;
  2383. para := tcallparanode(para.right);
  2384. end;
  2385. { local variables }
  2386. if not assigned(tprocdef(procdefinition).localst) or
  2387. (tprocdef(procdefinition).localst.SymList.count = 0) then
  2388. exit;
  2389. tempnodes.createstatement := createstatement;
  2390. tempnodes.deletestatement := deletestatement;
  2391. inlinelocals.count:=tprocdef(procdefinition).localst.SymList.count;
  2392. tprocdef(procdefinition).localst.SymList.ForEachCall(@createlocaltemps,@tempnodes);
  2393. createstatement := tempnodes.createstatement;
  2394. deletestatement := tempnodes.deletestatement;
  2395. end;
  2396. function tcallnode.getfuncretassignment(inlineblock: tblocknode): tnode;
  2397. var
  2398. hp: tstatementnode;
  2399. resassign: tnode;
  2400. begin
  2401. result:=nil;
  2402. if not assigned(funcretnode) or
  2403. not(cnf_return_value_used in callnodeflags) then
  2404. exit;
  2405. { tempcreatenode for the function result }
  2406. hp:=tstatementnode(inlineblock.left);
  2407. if not(assigned(hp)) or
  2408. (hp.left.nodetype <> tempcreaten) then
  2409. exit;
  2410. { assignment to the result }
  2411. hp:=tstatementnode(hp.right);
  2412. if not(assigned(hp)) or
  2413. (hp.left.nodetype<>assignn) or
  2414. { left must be function result }
  2415. (not(tassignmentnode(hp.left).left.isequal(funcretnode)) and
  2416. { can have extra type conversion due to absolute mapping }
  2417. { of <fucntionname> on function result var }
  2418. not((tassignmentnode(hp.left).left.nodetype = typeconvn) and
  2419. (ttypeconvnode(tassignmentnode(hp.left).left).convtype = tc_equal) and
  2420. (ttypeconvnode(tassignmentnode(hp.left).left).left.isequal(funcretnode)))) or
  2421. { right must be a constant (mainly to avoid trying to reuse }
  2422. { local temps which may already be freed afterwards once these }
  2423. { checks are made looser) }
  2424. not is_constnode(tassignmentnode(hp.left).right) then
  2425. exit
  2426. else
  2427. resassign:=hp.left;
  2428. { tempdelete to normal of the function result }
  2429. hp:=tstatementnode(hp.right);
  2430. if not(assigned(hp)) or
  2431. (hp.left.nodetype <> tempdeleten) then
  2432. exit;
  2433. { the function result once more }
  2434. hp:=tstatementnode(hp.right);
  2435. if not(assigned(hp)) or
  2436. not(hp.left.isequal(funcretnode)) then
  2437. exit;
  2438. { should be the end }
  2439. if assigned(hp.right) then
  2440. exit;
  2441. { we made it! }
  2442. result:=tassignmentnode(resassign).right.getcopy;
  2443. firstpass(result);
  2444. end;
  2445. function tcallnode.pass1_inline:tnode;
  2446. var
  2447. createstatement,deletestatement: tstatementnode;
  2448. createblock,deleteblock: tblocknode;
  2449. body : tnode;
  2450. begin
  2451. if not(assigned(tprocdef(procdefinition).inlininginfo) and
  2452. assigned(tprocdef(procdefinition).inlininginfo^.code)) then
  2453. internalerror(200412021);
  2454. { inherit flags }
  2455. current_procinfo.flags := current_procinfo.flags + ((procdefinition as tprocdef).inlininginfo^.flags*inherited_inlining_flags);
  2456. { create blocks for loading/deleting of local data }
  2457. createblock:=internalstatements(createstatement);
  2458. deleteblock:=internalstatements(deletestatement);
  2459. { add methodpointer init code to init statement }
  2460. { (fini must be done later, as it will delete the hookoncopy info) }
  2461. if assigned(methodpointerinit) then
  2462. addstatement(createstatement,methodpointerinit.getcopy);
  2463. inlinelocals:=TFPObjectList.create(true);
  2464. { get copy of the procedure body }
  2465. body:=tprocdef(procdefinition).inlininginfo^.code.getcopy;
  2466. { replace complex parameters with temps }
  2467. createinlineparas(createstatement,deletestatement);
  2468. { replace the parameter loads with the parameter values }
  2469. foreachnode(body,@replaceparaload,@fileinfo);
  2470. { copy methodpointer fini code }
  2471. if assigned(methodpointerdone) then
  2472. addstatement(deletestatement,methodpointerdone.getcopy);
  2473. { free the temps for the locals }
  2474. inlinelocals.free;
  2475. inlinelocals:=nil;
  2476. addstatement(createstatement,body);
  2477. addstatement(createstatement,deleteblock);
  2478. { set function result location if necessary }
  2479. if assigned(funcretnode) and
  2480. (cnf_return_value_used in callnodeflags) then
  2481. addstatement(createstatement,funcretnode.getcopy);
  2482. { consider it must not be inlined if called
  2483. again inside the args or itself }
  2484. exclude(procdefinition.procoptions,po_inline);
  2485. dosimplify(createblock);
  2486. firstpass(createblock);
  2487. include(procdefinition.procoptions,po_inline);
  2488. { if all that's left of the inlined function is an constant }
  2489. { assignment to the result, replace the whole block with what's }
  2490. { assigned to the result. There will also be a tempcreatenode for }
  2491. { the function result itself though, so ignore it. The statement/ }
  2492. { blocknode simplification code will have removed all nothingn- }
  2493. { statements empty nested blocks, so we don't have to care about }
  2494. { those }
  2495. result := getfuncretassignment(createblock);
  2496. if assigned(result) then
  2497. createblock.free
  2498. else
  2499. { return inlined block }
  2500. result := createblock;
  2501. {$ifdef DEBUGINLINE}
  2502. writeln;
  2503. writeln('**************************',tprocdef(procdefinition).mangledname);
  2504. printnode(output,result);
  2505. {$endif DEBUGINLINE}
  2506. end;
  2507. procedure tcallnode.check_stack_parameters;
  2508. var
  2509. hp : tcallparanode;
  2510. begin
  2511. hp:=tcallparanode(left);
  2512. while assigned(hp) do
  2513. begin
  2514. if assigned(hp.parasym) and
  2515. assigned(hp.parasym.paraloc[callerside].location) and
  2516. (hp.parasym.paraloc[callerside].location^.loc=LOC_REFERENCE) then
  2517. include(current_procinfo.flags,pi_has_stackparameter);
  2518. hp:=tcallparanode(hp.right);
  2519. end;
  2520. end;
  2521. function tcallnode.pass_1 : tnode;
  2522. var
  2523. st : TSymtable;
  2524. begin
  2525. result:=nil;
  2526. { Can we inline the procedure? }
  2527. if ([po_inline,po_has_inlininginfo] <= procdefinition.procoptions) then
  2528. begin
  2529. { Check if we can inline the procedure when it references proc/var that
  2530. are not in the globally available }
  2531. st:=procdefinition.owner;
  2532. if (st.symtabletype=ObjectSymtable) then
  2533. st:=st.defowner.owner;
  2534. if (pi_uses_static_symtable in tprocdef(procdefinition).inlininginfo^.flags) and
  2535. (st.symtabletype=globalsymtable) and
  2536. (not st.iscurrentunit) then
  2537. begin
  2538. Comment(V_lineinfo+V_Debug,'Not inlining "'+tprocdef(procdefinition).procsym.realname+'", references static symtable');
  2539. end
  2540. else
  2541. begin
  2542. result:=pass1_inline;
  2543. exit;
  2544. end;
  2545. end;
  2546. { calculate the parameter info for the procdef }
  2547. if not procdefinition.has_paraloc_info then
  2548. begin
  2549. procdefinition.requiredargarea:=paramanager.create_paraloc_info(procdefinition,callerside);
  2550. procdefinition.has_paraloc_info:=true;
  2551. end;
  2552. { calculate the parameter size needed for this call include varargs if they are available }
  2553. if assigned(varargsparas) then
  2554. pushedparasize:=paramanager.create_varargs_paraloc_info(procdefinition,varargsparas)
  2555. else
  2556. pushedparasize:=procdefinition.requiredargarea;
  2557. { record maximum parameter size used in this proc }
  2558. current_procinfo.allocate_push_parasize(pushedparasize);
  2559. { work trough all parameters to get the register requirements }
  2560. if assigned(left) then
  2561. begin
  2562. tcallparanode(left).det_registers;
  2563. if cs_opt_level1 in current_settings.optimizerswitches then
  2564. begin
  2565. { check for stacked parameters }
  2566. check_stack_parameters;
  2567. end;
  2568. end;
  2569. { order parameters }
  2570. order_parameters;
  2571. if assigned(methodpointerinit) then
  2572. firstpass(methodpointerinit);
  2573. if assigned(methodpointerdone) then
  2574. firstpass(methodpointerdone);
  2575. { function result node }
  2576. if assigned(_funcretnode) then
  2577. firstpass(_funcretnode);
  2578. { procedure variable ? }
  2579. if assigned(right) then
  2580. firstpass(right);
  2581. if not (block_type in [bt_const,bt_type]) then
  2582. include(current_procinfo.flags,pi_do_call);
  2583. { implicit finally needed ? }
  2584. if resultdef.needs_inittable and
  2585. not paramanager.ret_in_param(resultdef,procdefinition.proccalloption) and
  2586. not assigned(funcretnode) then
  2587. include(current_procinfo.flags,pi_needs_implicit_finally);
  2588. { get a register for the return value }
  2589. if (not is_void(resultdef)) then
  2590. begin
  2591. if paramanager.ret_in_param(resultdef,procdefinition.proccalloption) then
  2592. begin
  2593. expectloc:=LOC_REFERENCE;
  2594. end
  2595. else
  2596. { ansi/widestrings must be registered, so we can dispose them }
  2597. if is_ansistring(resultdef) or
  2598. is_widestring(resultdef) then
  2599. begin
  2600. expectloc:=LOC_REFERENCE;
  2601. registersint:=1;
  2602. end
  2603. else
  2604. { we have only to handle the result if it is used }
  2605. if (cnf_return_value_used in callnodeflags) then
  2606. begin
  2607. case resultdef.typ of
  2608. enumdef,
  2609. orddef :
  2610. begin
  2611. if (procdefinition.proctypeoption=potype_constructor) then
  2612. begin
  2613. expectloc:=LOC_REGISTER;
  2614. registersint:=1;
  2615. end
  2616. else
  2617. begin
  2618. expectloc:=LOC_REGISTER;
  2619. if is_64bit(resultdef) then
  2620. registersint:=2
  2621. else
  2622. registersint:=1;
  2623. end;
  2624. end;
  2625. floatdef :
  2626. begin
  2627. expectloc:=LOC_FPUREGISTER;
  2628. {$ifdef cpufpemu}
  2629. if (cs_fp_emulation in current_settings.moduleswitches) then
  2630. registersint:=1
  2631. else
  2632. {$endif cpufpemu}
  2633. {$ifdef m68k}
  2634. if (tfloatdef(resultdef).floattype=s32real) then
  2635. registersint:=1
  2636. else
  2637. {$endif m68k}
  2638. registersfpu:=1;
  2639. end;
  2640. else
  2641. begin
  2642. expectloc:=procdefinition.funcretloc[callerside].loc;
  2643. if (expectloc = LOC_REGISTER) then
  2644. {$ifndef cpu64bit}
  2645. if (resultdef.size > sizeof(aint)) then
  2646. registersint:=2
  2647. else
  2648. {$endif cpu64bit}
  2649. registersint:=1
  2650. else
  2651. registersint:=0;
  2652. end;
  2653. end;
  2654. end
  2655. else
  2656. expectloc:=LOC_VOID;
  2657. end
  2658. else
  2659. expectloc:=LOC_VOID;
  2660. {$ifdef m68k}
  2661. { we need one more address register for virtual calls on m68k }
  2662. if (po_virtualmethod in procdefinition.procoptions) then
  2663. inc(registersint);
  2664. {$endif m68k}
  2665. { a fpu can be used in any procedure !! }
  2666. {$ifdef i386}
  2667. registersfpu:=procdefinition.fpu_used;
  2668. {$endif i386}
  2669. { if this is a call to a method calc the registers }
  2670. if (methodpointer<>nil) then
  2671. begin
  2672. if methodpointer.nodetype<>typen then
  2673. begin
  2674. firstpass(methodpointer);
  2675. registersfpu:=max(methodpointer.registersfpu,registersfpu);
  2676. registersint:=max(methodpointer.registersint,registersint);
  2677. {$ifdef SUPPORT_MMX }
  2678. registersmmx:=max(methodpointer.registersmmx,registersmmx);
  2679. {$endif SUPPORT_MMX}
  2680. end;
  2681. end;
  2682. { determine the registers of the procedure variable }
  2683. { is this OK for inlined procs also ?? (PM) }
  2684. if assigned(right) then
  2685. begin
  2686. registersfpu:=max(right.registersfpu,registersfpu);
  2687. registersint:=max(right.registersint,registersint);
  2688. {$ifdef SUPPORT_MMX}
  2689. registersmmx:=max(right.registersmmx,registersmmx);
  2690. {$endif SUPPORT_MMX}
  2691. end;
  2692. { determine the registers of the procedure }
  2693. if assigned(left) then
  2694. begin
  2695. registersfpu:=max(left.registersfpu,registersfpu);
  2696. registersint:=max(left.registersint,registersint);
  2697. {$ifdef SUPPORT_MMX}
  2698. registersmmx:=max(left.registersmmx,registersmmx);
  2699. {$endif SUPPORT_MMX}
  2700. end;
  2701. end;
  2702. {$ifdef state_tracking}
  2703. function Tcallnode.track_state_pass(exec_known:boolean):boolean;
  2704. var hp:Tcallparanode;
  2705. value:Tnode;
  2706. begin
  2707. track_state_pass:=false;
  2708. hp:=Tcallparanode(left);
  2709. while assigned(hp) do
  2710. begin
  2711. if left.track_state_pass(exec_known) then
  2712. begin
  2713. left.resultdef:=nil;
  2714. do_typecheckpass(left);
  2715. end;
  2716. value:=aktstate.find_fact(hp.left);
  2717. if value<>nil then
  2718. begin
  2719. track_state_pass:=true;
  2720. hp.left.destroy;
  2721. hp.left:=value.getcopy;
  2722. do_typecheckpass(hp.left);
  2723. end;
  2724. hp:=Tcallparanode(hp.right);
  2725. end;
  2726. end;
  2727. {$endif}
  2728. function tcallnode.para_count:longint;
  2729. var
  2730. ppn : tcallparanode;
  2731. begin
  2732. result:=0;
  2733. ppn:=tcallparanode(left);
  2734. while assigned(ppn) do
  2735. begin
  2736. if not(assigned(ppn.parasym) and
  2737. (vo_is_hidden_para in ppn.parasym.varoptions)) then
  2738. inc(result);
  2739. ppn:=tcallparanode(ppn.right);
  2740. end;
  2741. end;
  2742. function tcallnode.get_load_methodpointer:tnode;
  2743. var
  2744. newstatement : tstatementnode;
  2745. begin
  2746. if assigned(methodpointerinit) then
  2747. begin
  2748. result:=internalstatements(newstatement);
  2749. addstatement(newstatement,methodpointerinit);
  2750. addstatement(newstatement,methodpointer);
  2751. addstatement(newstatement,methodpointerdone);
  2752. methodpointerinit:=nil;
  2753. methodpointer:=nil;
  2754. methodpointerdone:=nil;
  2755. end
  2756. else
  2757. begin
  2758. result:=methodpointer;
  2759. methodpointer:=nil;
  2760. end;
  2761. end;
  2762. function tcallnode.docompare(p: tnode): boolean;
  2763. begin
  2764. docompare :=
  2765. inherited docompare(p) and
  2766. (symtableprocentry = tcallnode(p).symtableprocentry) and
  2767. (procdefinition = tcallnode(p).procdefinition) and
  2768. (methodpointer.isequal(tcallnode(p).methodpointer)) and
  2769. (((cnf_typedefset in callnodeflags) and (cnf_typedefset in tcallnode(p).callnodeflags) and
  2770. (equal_defs(typedef,tcallnode(p).typedef))) or
  2771. (not(cnf_typedefset in callnodeflags) and not(cnf_typedefset in tcallnode(p).callnodeflags)));
  2772. end;
  2773. procedure tcallnode.printnodedata(var t:text);
  2774. begin
  2775. if assigned(procdefinition) and
  2776. (procdefinition.typ=procdef) then
  2777. writeln(t,printnodeindention,'proc = ',tprocdef(procdefinition).fullprocname(true))
  2778. else
  2779. begin
  2780. if assigned(symtableprocentry) then
  2781. writeln(t,printnodeindention,'proc = ',symtableprocentry.name)
  2782. else
  2783. writeln(t,printnodeindention,'proc = <nil>');
  2784. end;
  2785. if assigned(methodpointer) then
  2786. begin
  2787. writeln(t,printnodeindention,'methodpointer =');
  2788. printnode(t,methodpointer);
  2789. end;
  2790. if assigned(methodpointerinit) then
  2791. begin
  2792. writeln(t,printnodeindention,'methodpointerinit =');
  2793. printnode(t,methodpointerinit);
  2794. end;
  2795. if assigned(methodpointerdone) then
  2796. begin
  2797. writeln(t,printnodeindention,'methodpointerdone =');
  2798. printnode(t,methodpointerdone);
  2799. end;
  2800. if assigned(right) then
  2801. begin
  2802. writeln(t,printnodeindention,'right =');
  2803. printnode(t,right);
  2804. end;
  2805. if assigned(left) then
  2806. begin
  2807. writeln(t,printnodeindention,'left =');
  2808. printnode(t,left);
  2809. end;
  2810. end;
  2811. begin
  2812. ccallnode:=tcallnode;
  2813. ccallparanode:=tcallparanode;
  2814. end.