ncal.pas 113 KB

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