ncal.pas 135 KB

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