ncal.pas 120 KB

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