htypechk.pas 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit exports some help routines for the type checking
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit htypechk;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. tokens,
  23. node,
  24. symtype,symdef;
  25. type
  26. Ttok2nodeRec=record
  27. tok : ttoken;
  28. nod : tnodetype;
  29. op_overloading_supported : boolean;
  30. end;
  31. const
  32. tok2nodes=25;
  33. tok2node:array[1..tok2nodes] of ttok2noderec=(
  34. (tok:_PLUS ;nod:addn;op_overloading_supported:true), { binary overloading supported }
  35. (tok:_MINUS ;nod:subn;op_overloading_supported:true), { binary and unary overloading supported }
  36. (tok:_STAR ;nod:muln;op_overloading_supported:true), { binary overloading supported }
  37. (tok:_SLASH ;nod:slashn;op_overloading_supported:true), { binary overloading supported }
  38. (tok:_EQUAL ;nod:equaln;op_overloading_supported:true), { binary overloading supported }
  39. (tok:_GT ;nod:gtn;op_overloading_supported:true), { binary overloading supported }
  40. (tok:_LT ;nod:ltn;op_overloading_supported:true), { binary overloading supported }
  41. (tok:_GTE ;nod:gten;op_overloading_supported:true), { binary overloading supported }
  42. (tok:_LTE ;nod:lten;op_overloading_supported:true), { binary overloading supported }
  43. (tok:_SYMDIF ;nod:symdifn;op_overloading_supported:true), { binary overloading supported }
  44. (tok:_STARSTAR;nod:starstarn;op_overloading_supported:true), { binary overloading supported }
  45. (tok:_OP_AS ;nod:asn;op_overloading_supported:false), { binary overloading NOT supported }
  46. (tok:_OP_IN ;nod:inn;op_overloading_supported:false), { binary overloading NOT supported }
  47. (tok:_OP_IS ;nod:isn;op_overloading_supported:false), { binary overloading NOT supported }
  48. (tok:_OP_OR ;nod:orn;op_overloading_supported:true), { binary overloading supported }
  49. (tok:_OP_AND ;nod:andn;op_overloading_supported:true), { binary overloading supported }
  50. (tok:_OP_DIV ;nod:divn;op_overloading_supported:true), { binary overloading supported }
  51. (tok:_OP_NOT ;nod:notn;op_overloading_supported:true), { unary overloading supported }
  52. (tok:_OP_MOD ;nod:modn;op_overloading_supported:true), { binary overloading supported }
  53. (tok:_OP_SHL ;nod:shln;op_overloading_supported:true), { binary overloading supported }
  54. (tok:_OP_SHR ;nod:shrn;op_overloading_supported:true), { binary overloading supported }
  55. (tok:_OP_XOR ;nod:xorn;op_overloading_supported:true), { binary overloading supported }
  56. (tok:_ASSIGNMENT;nod:assignn;op_overloading_supported:true), { unary overloading supported }
  57. (tok:_CARET ;nod:caretn;op_overloading_supported:false), { binary overloading NOT supported }
  58. (tok:_UNEQUAL ;nod:unequaln;op_overloading_supported:false) { binary overloading NOT supported overload = instead }
  59. );
  60. const
  61. { firstcallparan without varspez we don't count the ref }
  62. {$ifdef extdebug}
  63. count_ref : boolean = true;
  64. {$endif def extdebug}
  65. get_para_resulttype : boolean = false;
  66. allow_array_constructor : boolean = false;
  67. { is overloading of this operator allowed for this
  68. binary operator }
  69. function isbinaryoperatoroverloadable(ld, rd,dd : tdef; treetyp : tnodetype) : boolean;
  70. { is overloading of this operator allowed for this
  71. unary operator }
  72. function isunaryoperatoroverloadable(rd,dd : tdef; treetyp : tnodetype) : boolean;
  73. { check operator args and result type }
  74. function isoperatoracceptable(pf : tprocdef; optoken : ttoken) : boolean;
  75. function isbinaryoverloaded(var t : tnode) : boolean;
  76. { Register Allocation }
  77. procedure make_not_regable(p : tnode);
  78. procedure calcregisters(p : tbinarynode;r32,fpu,mmx : word);
  79. { subroutine handling }
  80. function is_procsym_load(p:tnode):boolean;
  81. function is_procsym_call(p:tnode):boolean;
  82. procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
  83. {
  84. type
  85. tvarstaterequire = (vsr_can_be_undefined,vsr_must_be_valid,
  86. vsr_is_used_after,vsr_must_be_valid_and_is_used_after); }
  87. { sets varsym varstate field correctly }
  88. procedure unset_varstate(p : tnode);
  89. procedure set_varstate(p : tnode;must_be_valid : boolean);
  90. { sets the callunique flag, if the node is a vecn, }
  91. { takes care of type casts etc. }
  92. procedure set_unique(p : tnode);
  93. { sets funcret_is_valid to true, if p contains a funcref node }
  94. procedure set_funcret_is_valid(p : tnode);
  95. function valid_for_formal_var(p : tnode) : boolean;
  96. function valid_for_formal_const(p : tnode) : boolean;
  97. function valid_for_var(p:tnode):boolean;
  98. function valid_for_assignment(p:tnode):boolean;
  99. implementation
  100. uses
  101. globtype,systems,
  102. cutils,verbose,globals,
  103. symconst,symsym,symtable,
  104. defutil,defcmp,cpubase,
  105. ncnv,nld,
  106. nmem,ncal,nmat,
  107. cgbase
  108. ;
  109. type
  110. TValidAssign=(Valid_Property,Valid_Void);
  111. TValidAssigns=set of TValidAssign;
  112. function isbinaryoperatoroverloadable(ld,rd,dd : tdef; treetyp : tnodetype) : boolean;
  113. begin
  114. { everything is possible, the exceptions will be
  115. handled below }
  116. isbinaryoperatoroverloadable:=false;
  117. { power ** is always possible }
  118. if (treetyp=starstarn) then
  119. begin
  120. isbinaryoperatoroverloadable:=true;
  121. exit;
  122. end;
  123. case ld.deftype of
  124. recorddef,
  125. variantdef :
  126. begin
  127. isbinaryoperatoroverloadable:=true;
  128. exit;
  129. end;
  130. procvardef :
  131. begin
  132. if (rd.deftype in [pointerdef,procdef,procvardef]) and
  133. (treetyp in [equaln,unequaln]) then
  134. begin
  135. isbinaryoperatoroverloadable:=false;
  136. exit;
  137. end;
  138. end;
  139. pointerdef :
  140. begin
  141. if (rd.deftype in [pointerdef,objectdef,classrefdef,procvardef]) and
  142. (treetyp in [equaln,unequaln,gtn,gten,ltn,lten,addn,subn]) then
  143. begin
  144. isbinaryoperatoroverloadable:=false;
  145. exit;
  146. end;
  147. { don't allow operations on pointer/integer }
  148. if is_integer(rd) then
  149. begin
  150. isbinaryoperatoroverloadable:=false;
  151. exit;
  152. end;
  153. { don't allow pchar+string }
  154. if is_pchar(ld) and
  155. (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) and
  156. (is_chararray(rd) or
  157. is_char(rd) or
  158. (rd.deftype=stringdef)) then
  159. begin
  160. isbinaryoperatoroverloadable:=false;
  161. exit;
  162. end;
  163. isbinaryoperatoroverloadable:=true;
  164. end;
  165. arraydef :
  166. begin
  167. { not mmx }
  168. if (cs_mmx in aktlocalswitches) and
  169. is_mmx_able_array(ld) then
  170. begin
  171. isbinaryoperatoroverloadable:=false;
  172. exit;
  173. end;
  174. { not chararray+[char,string,chararray] }
  175. if is_chararray(ld) and
  176. (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) and
  177. (is_char(rd) or
  178. is_pchar(rd) or
  179. is_integer(rd) or
  180. (rd.deftype=stringdef) or
  181. is_chararray(rd)) then
  182. begin
  183. isbinaryoperatoroverloadable:=false;
  184. exit;
  185. end;
  186. isbinaryoperatoroverloadable:=true;
  187. end;
  188. objectdef :
  189. begin
  190. { <> and = are defined for classes }
  191. if (treetyp in [equaln,unequaln]) and
  192. is_class_or_interface(ld) then
  193. begin
  194. isbinaryoperatoroverloadable:=false;
  195. exit;
  196. end;
  197. isbinaryoperatoroverloadable:=true;
  198. end;
  199. stringdef :
  200. begin
  201. if ((rd.deftype=stringdef) or
  202. is_char(rd) or
  203. is_pchar(rd) or
  204. is_chararray(rd)) and
  205. (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) then
  206. begin
  207. isbinaryoperatoroverloadable:=false;
  208. exit;
  209. end;
  210. isbinaryoperatoroverloadable:=true;
  211. end;
  212. end;
  213. { Also check the right def. There can be some duplicated code
  214. that is never reached. But to place everything in one big
  215. case is unmaintainable }
  216. case rd.deftype of
  217. recorddef,
  218. variantdef :
  219. begin
  220. isbinaryoperatoroverloadable:=true;
  221. exit;
  222. end;
  223. procvardef :
  224. begin
  225. if (ld.deftype in [pointerdef,procdef,procvardef]) and
  226. (treetyp in [equaln,unequaln]) then
  227. begin
  228. isbinaryoperatoroverloadable:=false;
  229. exit;
  230. end;
  231. isbinaryoperatoroverloadable:=true;
  232. end;
  233. pointerdef :
  234. begin
  235. if (ld.deftype in [pointerdef,objectdef,classrefdef,procvardef]) and
  236. (treetyp in [equaln,unequaln,gtn,gten,ltn,lten,addn,subn]) then
  237. begin
  238. isbinaryoperatoroverloadable:=false;
  239. exit;
  240. end;
  241. { don't allow operations on pointer/integer }
  242. if is_integer(ld) then
  243. begin
  244. isbinaryoperatoroverloadable:=false;
  245. exit;
  246. end;
  247. { don't allow pchar+string }
  248. if is_pchar(rd) and
  249. (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) and
  250. (is_chararray(ld) or
  251. is_char(ld) or
  252. (ld.deftype=stringdef)) then
  253. begin
  254. isbinaryoperatoroverloadable:=false;
  255. exit;
  256. end;
  257. isbinaryoperatoroverloadable:=true;
  258. end;
  259. arraydef :
  260. begin
  261. { not mmx }
  262. if (cs_mmx in aktlocalswitches) and
  263. is_mmx_able_array(rd) then
  264. begin
  265. isbinaryoperatoroverloadable:=false;
  266. exit;
  267. end;
  268. { not chararray+[char,string,chararray] }
  269. if is_chararray(rd) and
  270. (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) and
  271. (is_char(ld) or
  272. is_pchar(ld) or
  273. is_integer(ld) or
  274. (ld.deftype=stringdef) or
  275. is_chararray(ld)) then
  276. begin
  277. isbinaryoperatoroverloadable:=false;
  278. exit;
  279. end;
  280. isbinaryoperatoroverloadable:=true;
  281. end;
  282. objectdef :
  283. begin
  284. { <> and = are defined for classes }
  285. if (treetyp in [equaln,unequaln]) and
  286. is_class_or_interface(rd) then
  287. begin
  288. isbinaryoperatoroverloadable:=false;
  289. exit;
  290. end;
  291. isbinaryoperatoroverloadable:=true;
  292. end;
  293. stringdef :
  294. begin
  295. if ((ld.deftype=stringdef) or
  296. is_char(ld) or
  297. is_pchar(ld) or
  298. is_chararray(ld)) and
  299. (treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) then
  300. begin
  301. isbinaryoperatoroverloadable:=false;
  302. exit;
  303. end;
  304. isbinaryoperatoroverloadable:=true;
  305. end;
  306. end;
  307. end;
  308. function isunaryoperatoroverloadable(rd,dd : tdef; treetyp : tnodetype) : boolean;
  309. begin
  310. isunaryoperatoroverloadable:=false;
  311. case treetyp of
  312. assignn :
  313. begin
  314. if (rd.deftype=orddef) and
  315. (dd.deftype=orddef) then
  316. begin
  317. isunaryoperatoroverloadable:=false;
  318. exit;
  319. end;
  320. isunaryoperatoroverloadable:=true;
  321. end;
  322. subn :
  323. begin
  324. if is_integer(rd) or
  325. (rd.deftype=floatdef) then
  326. begin
  327. isunaryoperatoroverloadable:=false;
  328. exit;
  329. end;
  330. {$ifdef SUPPORT_MMX}
  331. if (cs_mmx in aktlocalswitches) and
  332. is_mmx_able_array(rd) then
  333. begin
  334. isunaryoperatoroverloadable:=false;
  335. exit;
  336. end;
  337. {$endif SUPPORT_MMX}
  338. isunaryoperatoroverloadable:=true;
  339. end;
  340. notn :
  341. begin
  342. if is_integer(rd) or
  343. is_boolean(rd) then
  344. begin
  345. isunaryoperatoroverloadable:=false;
  346. exit;
  347. end;
  348. {$ifdef SUPPORT_MMX}
  349. if (cs_mmx in aktlocalswitches) and
  350. is_mmx_able_array(rd) then
  351. begin
  352. isunaryoperatoroverloadable:=false;
  353. exit;
  354. end;
  355. {$endif SUPPORT_MMX}
  356. isunaryoperatoroverloadable:=true;
  357. end;
  358. end;
  359. end;
  360. function isoperatoracceptable(pf : tprocdef; optoken : ttoken) : boolean;
  361. var
  362. ld,rd,dd : tdef;
  363. i : longint;
  364. begin
  365. case pf.parast.symindex.count of
  366. 2 : begin
  367. isoperatoracceptable:=false;
  368. for i:=1 to tok2nodes do
  369. if tok2node[i].tok=optoken then
  370. begin
  371. ld:=tvarsym(pf.parast.symindex.first).vartype.def;
  372. rd:=tvarsym(pf.parast.symindex.first.indexnext).vartype.def;
  373. dd:=pf.rettype.def;
  374. isoperatoracceptable:=
  375. tok2node[i].op_overloading_supported and
  376. isbinaryoperatoroverloadable(ld,rd,dd,tok2node[i].nod);
  377. break;
  378. end;
  379. end;
  380. 1 : begin
  381. rd:=tvarsym(pf.parast.symindex.first).vartype.def;
  382. dd:=pf.rettype.def;
  383. for i:=1 to tok2nodes do
  384. if tok2node[i].tok=optoken then
  385. begin
  386. isoperatoracceptable:=
  387. tok2node[i].op_overloading_supported and
  388. isunaryoperatoroverloadable(rd,dd,tok2node[i].nod);
  389. break;
  390. end;
  391. end;
  392. else
  393. isoperatoracceptable:=false;
  394. end;
  395. end;
  396. function isbinaryoverloaded(var t : tnode) : boolean;
  397. var
  398. rd,ld : tdef;
  399. optoken : ttoken;
  400. operpd : tprocdef;
  401. ht : tnode;
  402. begin
  403. isbinaryoverloaded:=false;
  404. operpd:=nil;
  405. { load easier access variables }
  406. rd:=tbinarynode(t).right.resulttype.def;
  407. ld:=tbinarynode(t).left.resulttype.def;
  408. if isbinaryoperatoroverloadable(ld,rd,voidtype.def,t.nodetype) then
  409. begin
  410. isbinaryoverloaded:=true;
  411. case t.nodetype of
  412. equaln,
  413. unequaln :
  414. optoken:=_EQUAL;
  415. addn:
  416. optoken:=_PLUS;
  417. subn:
  418. optoken:=_MINUS;
  419. muln:
  420. optoken:=_STAR;
  421. starstarn:
  422. optoken:=_STARSTAR;
  423. slashn:
  424. optoken:=_SLASH;
  425. ltn:
  426. optoken:=tokens._lt;
  427. gtn:
  428. optoken:=tokens._gt;
  429. lten:
  430. optoken:=_lte;
  431. gten:
  432. optoken:=_gte;
  433. symdifn :
  434. optoken:=_SYMDIF;
  435. modn :
  436. optoken:=_OP_MOD;
  437. orn :
  438. optoken:=_OP_OR;
  439. xorn :
  440. optoken:=_OP_XOR;
  441. andn :
  442. optoken:=_OP_AND;
  443. divn :
  444. optoken:=_OP_DIV;
  445. shln :
  446. optoken:=_OP_SHL;
  447. shrn :
  448. optoken:=_OP_SHR;
  449. else
  450. exit;
  451. end;
  452. { check if the operator contains overloaded procdefs }
  453. if overloaded_operators[optoken]=nil then
  454. begin
  455. CGMessage(parser_e_operator_not_overloaded);
  456. isbinaryoverloaded:=false;
  457. exit;
  458. end;
  459. { Check if the assignment is available, if not then
  460. give a message that the types are not compatible }
  461. if optoken in [_EQUAL] then
  462. begin
  463. operpd:=overloaded_operators[optoken].search_procdef_binary_operator(ld,rd);
  464. if not assigned(operpd) then
  465. begin
  466. CGMessage2(type_e_incompatible_types,ld.typename,rd.typename);
  467. isbinaryoverloaded:=false;
  468. exit;
  469. end;
  470. end;
  471. { the nil as symtable signs firstcalln that this is
  472. an overloaded operator }
  473. ht:=ccallnode.create(nil,overloaded_operators[optoken],nil,nil);
  474. inc(tcallnode(ht).symtableprocentry.refs);
  475. { we already know the procdef to use for equal, so it can
  476. skip the overload choosing in callnode.det_resulttype }
  477. if assigned(operpd) then
  478. tcallnode(ht).procdefinition:=operpd;
  479. { we need copies, because the originals will be destroyed when we give a }
  480. { changed node back to firstpass! (JM) }
  481. if assigned(tbinarynode(t).left) then
  482. if assigned(tbinarynode(t).right) then
  483. tcallnode(ht).left :=
  484. ccallparanode.create(tbinarynode(t).right.getcopy,
  485. ccallparanode.create(tbinarynode(t).left.getcopy,nil))
  486. else
  487. tcallnode(ht).left :=
  488. ccallparanode.create(nil,
  489. ccallparanode.create(tbinarynode(t).left.getcopy,nil))
  490. else if assigned(tbinarynode(t).right) then
  491. tcallnode(ht).left :=
  492. ccallparanode.create(tbinarynode(t).right.getcopy,
  493. ccallparanode.create(nil,nil));
  494. if t.nodetype=unequaln then
  495. ht:=cnotnode.create(ht);
  496. t:=ht;
  497. end;
  498. end;
  499. {****************************************************************************
  500. Register Calculation
  501. ****************************************************************************}
  502. { marks an lvalue as "unregable" }
  503. procedure make_not_regable(p : tnode);
  504. begin
  505. case p.nodetype of
  506. typeconvn :
  507. make_not_regable(ttypeconvnode(p).left);
  508. loadn :
  509. if tloadnode(p).symtableentry.typ=varsym then
  510. tvarsym(tloadnode(p).symtableentry).varoptions:=tvarsym(tloadnode(p).symtableentry).varoptions-[vo_regable,vo_fpuregable];
  511. end;
  512. end;
  513. { calculates the needed registers for a binary operator }
  514. procedure calcregisters(p : tbinarynode;r32,fpu,mmx : word);
  515. begin
  516. p.left_right_max;
  517. { Only when the difference between the left and right registers < the
  518. wanted registers allocate the amount of registers }
  519. if assigned(p.left) then
  520. begin
  521. if assigned(p.right) then
  522. begin
  523. { the location must be already filled in because we need it to }
  524. { calculate the necessary number of registers (JM) }
  525. if p.location.loc = LOC_INVALID then
  526. internalerror(200110101);
  527. if (abs(p.left.registers32-p.right.registers32)<r32) or
  528. ((p.location.loc = LOC_FPUREGISTER) and
  529. (p.right.registersfpu <= p.left.registersfpu) and
  530. ((p.right.registersfpu <> 0) or (p.left.registersfpu <> 0)) and
  531. (p.left.registers32 < p.right.registers32)) then
  532. inc(p.registers32,r32);
  533. if (abs(p.left.registersfpu-p.right.registersfpu)<fpu) then
  534. inc(p.registersfpu,fpu);
  535. {$ifdef SUPPORT_MMX}
  536. if (abs(p.left.registersmmx-p.right.registersmmx)<mmx) then
  537. inc(p.registersmmx,mmx);
  538. {$endif SUPPORT_MMX}
  539. { the following is a little bit guessing but I think }
  540. { it's the only way to solve same internalerrors: }
  541. { if the left and right node both uses registers }
  542. { and return a mem location, but the current node }
  543. { doesn't use an integer register we get probably }
  544. { trouble when restoring a node }
  545. if (p.left.registers32=p.right.registers32) and
  546. (p.registers32=p.left.registers32) and
  547. (p.registers32>0) and
  548. (p.left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  549. (p.right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  550. inc(p.registers32);
  551. end
  552. else
  553. begin
  554. if (p.left.registers32<r32) then
  555. inc(p.registers32,r32);
  556. if (p.left.registersfpu<fpu) then
  557. inc(p.registersfpu,fpu);
  558. {$ifdef SUPPORT_MMX}
  559. if (p.left.registersmmx<mmx) then
  560. inc(p.registersmmx,mmx);
  561. {$endif SUPPORT_MMX}
  562. end;
  563. end;
  564. { error CGMessage, if more than 8 floating point }
  565. { registers are needed }
  566. { if p.registersfpu>maxfpuregs then
  567. CGMessage(cg_e_too_complex_expr); now pushed if needed PM }
  568. end;
  569. {****************************************************************************
  570. Subroutine Handling
  571. ****************************************************************************}
  572. function is_procsym_load(p:tnode):boolean;
  573. begin
  574. { ignore vecn,subscriptn }
  575. repeat
  576. case p.nodetype of
  577. vecn :
  578. p:=tvecnode(p).left;
  579. subscriptn :
  580. p:=tsubscriptnode(p).left;
  581. else
  582. break;
  583. end;
  584. until false;
  585. is_procsym_load:=((p.nodetype=loadn) and (tloadnode(p).symtableentry.typ=procsym)) or
  586. ((p.nodetype=addrn) and (taddrnode(p).left.nodetype=loadn)
  587. and (tloadnode(taddrnode(p).left).symtableentry.typ=procsym)) ;
  588. end;
  589. { change a proc call to a procload for assignment to a procvar }
  590. { this can only happen for proc/function without arguments }
  591. function is_procsym_call(p:tnode):boolean;
  592. begin
  593. is_procsym_call:=(p.nodetype=calln) and (tcallnode(p).left=nil) and
  594. (((tcallnode(p).symtableprocentry.typ=procsym) and (tcallnode(p).right=nil)) or
  595. (assigned(tcallnode(p).right) and (tcallnode(tcallnode(p).right).symtableprocentry.typ=varsym)));
  596. end;
  597. { local routines can't be assigned to procvars }
  598. procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
  599. begin
  600. if (from_def.symtablelevel>1) and (to_def.deftype=procvardef) then
  601. CGMessage(type_e_cannot_local_proc_to_procvar);
  602. end;
  603. procedure set_varstate(p : tnode;must_be_valid : boolean);
  604. var
  605. hsym : tvarsym;
  606. begin
  607. while assigned(p) do
  608. begin
  609. if (nf_varstateset in p.flags) then
  610. exit;
  611. include(p.flags,nf_varstateset);
  612. case p.nodetype of
  613. typeconvn :
  614. begin
  615. case ttypeconvnode(p).convtype of
  616. tc_cchar_2_pchar,
  617. tc_cstring_2_pchar,
  618. tc_array_2_pointer :
  619. must_be_valid:=false;
  620. tc_pchar_2_string,
  621. tc_pointer_2_array :
  622. must_be_valid:=true;
  623. end;
  624. p:=tunarynode(p).left;
  625. end;
  626. subscriptn :
  627. p:=tunarynode(p).left;
  628. vecn:
  629. begin
  630. set_varstate(tbinarynode(p).right,true);
  631. if not(tunarynode(p).left.resulttype.def.deftype in [stringdef,arraydef]) then
  632. must_be_valid:=true;
  633. p:=tunarynode(p).left;
  634. end;
  635. { do not parse calln }
  636. calln :
  637. break;
  638. callparan :
  639. begin
  640. set_varstate(tbinarynode(p).right,must_be_valid);
  641. p:=tunarynode(p).left;
  642. end;
  643. loadn :
  644. begin
  645. if (tloadnode(p).symtableentry.typ=varsym) then
  646. begin
  647. hsym:=tvarsym(tloadnode(p).symtableentry);
  648. if must_be_valid and (nf_first in p.flags) then
  649. begin
  650. if (hsym.varstate=vs_declared_and_first_found) or
  651. (hsym.varstate=vs_set_but_first_not_passed) then
  652. begin
  653. if (assigned(hsym.owner) and
  654. assigned(aktprocsym) and
  655. (hsym.owner = aktprocdef.localst)) then
  656. begin
  657. if tloadnode(p).symtable.symtabletype=localsymtable then
  658. CGMessage1(sym_n_uninitialized_local_variable,hsym.realname)
  659. else
  660. CGMessage1(sym_n_uninitialized_variable,hsym.realname);
  661. end;
  662. end;
  663. end;
  664. if (nf_first in p.flags) then
  665. begin
  666. if hsym.varstate=vs_declared_and_first_found then
  667. begin
  668. { this can only happen at left of an assignment, no ? PM }
  669. if (parsing_para_level=0) and not must_be_valid then
  670. hsym.varstate:=vs_assigned
  671. else
  672. hsym.varstate:=vs_used;
  673. end
  674. else
  675. if hsym.varstate=vs_set_but_first_not_passed then
  676. hsym.varstate:=vs_used;
  677. exclude(p.flags,nf_first);
  678. end
  679. else
  680. begin
  681. if (hsym.varstate=vs_assigned) and
  682. (must_be_valid or (parsing_para_level>0) or
  683. (p.resulttype.def.deftype=procvardef)) then
  684. hsym.varstate:=vs_used;
  685. if (hsym.varstate=vs_declared_and_first_found) and
  686. (must_be_valid or (parsing_para_level>0) or
  687. (p.resulttype.def.deftype=procvardef)) then
  688. hsym.varstate:=vs_set_but_first_not_passed;
  689. end;
  690. end;
  691. break;
  692. end;
  693. funcretn:
  694. begin
  695. { no claim if setting higher return value_str }
  696. if must_be_valid and
  697. (lexlevel=tfuncretnode(p).funcretsym.owner.symtablelevel) and
  698. ((tfuncretnode(p).funcretsym.funcretstate=vs_declared) or
  699. ((nf_is_first_funcret in p.flags) and
  700. (tfuncretnode(p).funcretsym.funcretstate=vs_declared_and_first_found))) then
  701. begin
  702. CGMessage(sym_w_function_result_not_set);
  703. { avoid multiple warnings }
  704. tfuncretnode(p).funcretsym.funcretstate:=vs_assigned;
  705. end;
  706. if (nf_is_first_funcret in p.flags) and not must_be_valid then
  707. tfuncretnode(p).funcretsym.funcretstate:=vs_assigned;
  708. break;
  709. end;
  710. else
  711. break;
  712. end;{case }
  713. end;
  714. end;
  715. procedure unset_varstate(p : tnode);
  716. begin
  717. while assigned(p) do
  718. begin
  719. exclude(p.flags,nf_varstateset);
  720. case p.nodetype of
  721. typeconvn,
  722. subscriptn,
  723. vecn :
  724. p:=tunarynode(p).left;
  725. else
  726. break;
  727. end;
  728. end;
  729. end;
  730. procedure set_unique(p : tnode);
  731. begin
  732. while assigned(p) do
  733. begin
  734. case p.nodetype of
  735. vecn:
  736. begin
  737. include(p.flags,nf_callunique);
  738. break;
  739. end;
  740. typeconvn,
  741. subscriptn,
  742. derefn:
  743. p:=tunarynode(p).left;
  744. else
  745. break;
  746. end;
  747. end;
  748. end;
  749. procedure set_funcret_is_valid(p:tnode);
  750. begin
  751. while assigned(p) do
  752. begin
  753. case p.nodetype of
  754. funcretn:
  755. begin
  756. if (nf_is_first_funcret in p.flags) or
  757. (tfuncretnode(p).funcretsym.funcretstate=vs_declared_and_first_found) then
  758. tfuncretnode(p).funcretsym.funcretstate:=vs_assigned;
  759. break;
  760. end;
  761. vecn,
  762. {derefn,}
  763. typeconvn,
  764. subscriptn:
  765. p:=tunarynode(p).left;
  766. else
  767. break;
  768. end;
  769. end;
  770. end;
  771. function valid_for_assign(p:tnode;opts:TValidAssigns):boolean;
  772. var
  773. hp : tnode;
  774. gotwith,
  775. gotsubscript,
  776. gotpointer,
  777. gotvec,
  778. gotclass,
  779. gotderef : boolean;
  780. fromdef,
  781. todef : tdef;
  782. begin
  783. valid_for_assign:=false;
  784. gotsubscript:=false;
  785. gotvec:=false;
  786. gotderef:=false;
  787. gotclass:=false;
  788. gotpointer:=false;
  789. gotwith:=false;
  790. hp:=p;
  791. if not(valid_void in opts) and
  792. is_void(hp.resulttype.def) then
  793. begin
  794. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  795. exit;
  796. end;
  797. while assigned(hp) do
  798. begin
  799. { property allowed? calln has a property check itself }
  800. if (nf_isproperty in hp.flags) then
  801. begin
  802. if (valid_property in opts) then
  803. valid_for_assign:=true
  804. else
  805. begin
  806. { check return type }
  807. case hp.resulttype.def.deftype of
  808. pointerdef :
  809. gotpointer:=true;
  810. objectdef :
  811. gotclass:=is_class_or_interface(hp.resulttype.def);
  812. recorddef, { handle record like class it needs a subscription }
  813. classrefdef :
  814. gotclass:=true;
  815. end;
  816. { 1. if it returns a pointer and we've found a deref,
  817. 2. if it returns a class or record and a subscription or with is found }
  818. if (gotpointer and gotderef) or
  819. (gotclass and (gotsubscript or gotwith)) then
  820. valid_for_assign:=true
  821. else
  822. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  823. end;
  824. exit;
  825. end;
  826. case hp.nodetype of
  827. temprefn :
  828. begin
  829. valid_for_assign := true;
  830. exit;
  831. end;
  832. derefn :
  833. begin
  834. gotderef:=true;
  835. hp:=tderefnode(hp).left;
  836. end;
  837. typeconvn :
  838. begin
  839. { typecast sizes must match, exceptions:
  840. - from formaldef
  841. - from void
  842. - typecast from pointer to array }
  843. fromdef:=ttypeconvnode(hp).left.resulttype.def;
  844. todef:=hp.resulttype.def;
  845. if not((fromdef.deftype=formaldef) or
  846. is_void(fromdef) or
  847. ((fromdef.deftype=pointerdef) and (todef.deftype=arraydef)) or
  848. ((fromdef.deftype = objectdef) and (todef.deftype = objectdef) and
  849. (tobjectdef(fromdef).is_related(tobjectdef(todef))))) and
  850. (fromdef.size<>todef.size) then
  851. begin
  852. { in TP it is allowed to typecast to smaller types }
  853. if not(m_tp7 in aktmodeswitches) or
  854. (todef.size>fromdef.size) then
  855. CGMessagePos2(hp.fileinfo,type_e_typecast_wrong_size_for_assignment,tostr(fromdef.size),tostr(todef.size));
  856. end;
  857. case hp.resulttype.def.deftype of
  858. pointerdef :
  859. gotpointer:=true;
  860. objectdef :
  861. gotclass:=is_class_or_interface(hp.resulttype.def);
  862. classrefdef :
  863. gotclass:=true;
  864. arraydef :
  865. begin
  866. { pointer -> array conversion is done then we need to see it
  867. as a deref, because a ^ is then not required anymore }
  868. if (ttypeconvnode(hp).left.resulttype.def.deftype=pointerdef) then
  869. gotderef:=true;
  870. end;
  871. end;
  872. hp:=ttypeconvnode(hp).left;
  873. end;
  874. vecn :
  875. begin
  876. gotvec:=true;
  877. hp:=tunarynode(hp).left;
  878. end;
  879. asn :
  880. hp:=tunarynode(hp).left;
  881. subscriptn :
  882. begin
  883. gotsubscript:=true;
  884. { a class/interface access is an implicit }
  885. { dereferencing }
  886. hp:=tsubscriptnode(hp).left;
  887. if is_class_or_interface(hp.resulttype.def) then
  888. gotderef:=true;
  889. end;
  890. subn,
  891. addn :
  892. begin
  893. { Allow add/sub operators on a pointer, or an integer
  894. and a pointer typecast and deref has been found }
  895. if ((hp.resulttype.def.deftype=pointerdef) or
  896. (is_integer(hp.resulttype.def) and gotpointer)) and
  897. gotderef then
  898. valid_for_assign:=true
  899. else
  900. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  901. exit;
  902. end;
  903. addrn :
  904. begin
  905. if gotderef or
  906. (nf_procvarload in hp.flags) then
  907. valid_for_assign:=true
  908. else
  909. CGMessagePos(hp.fileinfo,type_e_no_assign_to_addr);
  910. exit;
  911. end;
  912. selfn,
  913. funcretn :
  914. begin
  915. valid_for_assign:=true;
  916. exit;
  917. end;
  918. calln :
  919. begin
  920. { check return type }
  921. case hp.resulttype.def.deftype of
  922. arraydef :
  923. begin
  924. { dynamic arrays are allowed when there is also a
  925. vec node }
  926. if is_dynamic_array(hp.resulttype.def) and
  927. gotvec then
  928. begin
  929. gotderef:=true;
  930. gotpointer:=true;
  931. end;
  932. end;
  933. pointerdef :
  934. gotpointer:=true;
  935. objectdef :
  936. gotclass:=is_class_or_interface(hp.resulttype.def);
  937. recorddef, { handle record like class it needs a subscription }
  938. classrefdef :
  939. gotclass:=true;
  940. end;
  941. { 1. if it returns a pointer and we've found a deref,
  942. 2. if it returns a class or record and a subscription or with is found }
  943. if (gotpointer and gotderef) or
  944. (gotclass and (gotsubscript or gotwith)) then
  945. valid_for_assign:=true
  946. else
  947. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  948. exit;
  949. end;
  950. loadn :
  951. begin
  952. case tloadnode(hp).symtableentry.typ of
  953. absolutesym,
  954. varsym :
  955. begin
  956. if (tvarsym(tloadnode(hp).symtableentry).varspez=vs_const) then
  957. begin
  958. { allow p^:= constructions with p is const parameter }
  959. if gotderef then
  960. valid_for_assign:=true
  961. else
  962. CGMessagePos(tloadnode(hp).fileinfo,type_e_no_assign_to_const);
  963. exit;
  964. end;
  965. { Are we at a with symtable, then we need to process the
  966. withrefnode also to check for maybe a const load }
  967. if (tloadnode(hp).symtable.symtabletype=withsymtable) then
  968. begin
  969. { continue with processing the withref node }
  970. hp:=tnode(twithsymtable(tloadnode(hp).symtable).withrefnode);
  971. gotwith:=true;
  972. end
  973. else
  974. begin
  975. { set the assigned flag for varsyms }
  976. if (tvarsym(tloadnode(hp).symtableentry).varstate=vs_declared) then
  977. tvarsym(tloadnode(hp).symtableentry).varstate:=vs_assigned;
  978. valid_for_assign:=true;
  979. exit;
  980. end;
  981. end;
  982. funcretsym :
  983. begin
  984. valid_for_assign:=true;
  985. exit;
  986. end;
  987. typedconstsym :
  988. begin
  989. if ttypedconstsym(tloadnode(hp).symtableentry).is_writable then
  990. valid_for_assign:=true
  991. else
  992. CGMessagePos(hp.fileinfo,type_e_no_assign_to_const);
  993. exit;
  994. end;
  995. else
  996. begin
  997. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  998. exit;
  999. end;
  1000. end;
  1001. end;
  1002. else
  1003. begin
  1004. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  1005. exit;
  1006. end;
  1007. end;
  1008. end;
  1009. end;
  1010. function valid_for_var(p:tnode):boolean;
  1011. begin
  1012. valid_for_var:=valid_for_assign(p,[]);
  1013. end;
  1014. function valid_for_formal_var(p : tnode) : boolean;
  1015. begin
  1016. valid_for_formal_var:=valid_for_assign(p,[valid_void]);
  1017. end;
  1018. function valid_for_formal_const(p : tnode) : boolean;
  1019. var
  1020. v : boolean;
  1021. begin
  1022. { p must have been firstpass'd before }
  1023. { accept about anything but not a statement ! }
  1024. case p.nodetype of
  1025. calln,
  1026. statementn,
  1027. addrn :
  1028. begin
  1029. { addrn is not allowed as this generate a constant value,
  1030. but a tp procvar are allowed (PFV) }
  1031. if nf_procvarload in p.flags then
  1032. v:=true
  1033. else
  1034. v:=false;
  1035. end;
  1036. else
  1037. v:=true;
  1038. end;
  1039. valid_for_formal_const:=v;
  1040. end;
  1041. function valid_for_assignment(p:tnode):boolean;
  1042. begin
  1043. valid_for_assignment:=valid_for_assign(p,[valid_property]);
  1044. end;
  1045. end.
  1046. {
  1047. $Log$
  1048. Revision 1.53 2002-12-11 22:39:24 peter
  1049. * better error message when no operator is found for equal
  1050. Revision 1.52 2002/11/27 22:11:59 peter
  1051. * rewrote isbinaryoverloadable to use a case. it's now much easier
  1052. to understand what is happening
  1053. Revision 1.51 2002/11/25 17:43:17 peter
  1054. * splitted defbase in defutil,symutil,defcmp
  1055. * merged isconvertable and is_equal into compare_defs(_ext)
  1056. * made operator search faster by walking the list only once
  1057. Revision 1.50 2002/10/07 20:12:08 peter
  1058. * ugly hack to fix tb0411
  1059. Revision 1.49 2002/10/05 00:47:03 peter
  1060. * support dynamicarray<>nil
  1061. Revision 1.48 2002/10/04 21:13:59 peter
  1062. * ignore vecn,subscriptn when checking for a procvar loadn
  1063. Revision 1.47 2002/09/16 18:09:34 peter
  1064. * set_funcret_valid fixed when result was already used in a nested
  1065. procedure
  1066. Revision 1.46 2002/07/20 11:57:53 florian
  1067. * types.pas renamed to defbase.pas because D6 contains a types
  1068. unit so this would conflicts if D6 programms are compiled
  1069. + Willamette/SSE2 instructions to assembler added
  1070. Revision 1.45 2002/05/18 13:34:08 peter
  1071. * readded missing revisions
  1072. Revision 1.44 2002/05/16 19:46:37 carl
  1073. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1074. + try to fix temp allocation (still in ifdef)
  1075. + generic constructor calls
  1076. + start of tassembler / tmodulebase class cleanup
  1077. Revision 1.42 2002/04/02 17:11:28 peter
  1078. * tlocation,treference update
  1079. * LOC_CONSTANT added for better constant handling
  1080. * secondadd splitted in multiple routines
  1081. * location_force_reg added for loading a location to a register
  1082. of a specified size
  1083. * secondassignment parses now first the right and then the left node
  1084. (this is compatible with Kylix). This saves a lot of push/pop especially
  1085. with string operations
  1086. * adapted some routines to use the new cg methods
  1087. Revision 1.41 2002/01/16 09:33:46 jonas
  1088. * no longer allow assignments to pointer expressions (unless there's a
  1089. deref), reported by John Lee
  1090. }