tcmem.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. Type checking and register allocation for memory related nodes
  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 tcmem;
  19. interface
  20. uses
  21. tree;
  22. procedure firstloadvmt(var p : ptree);
  23. procedure firsthnew(var p : ptree);
  24. procedure firstnew(var p : ptree);
  25. procedure firsthdispose(var p : ptree);
  26. procedure firstsimplenewdispose(var p : ptree);
  27. procedure firstaddr(var p : ptree);
  28. procedure firstdoubleaddr(var p : ptree);
  29. procedure firstderef(var p : ptree);
  30. procedure firstsubscript(var p : ptree);
  31. procedure firstvec(var p : ptree);
  32. procedure firstself(var p : ptree);
  33. procedure firstwith(var p : ptree);
  34. implementation
  35. uses
  36. globtype,systems,
  37. cobjects,verbose,globals,
  38. symconst,symtable,aasm,types,
  39. hcodegen,htypechk,pass_1,cpubase;
  40. {*****************************************************************************
  41. FirstLoadVMT
  42. *****************************************************************************}
  43. procedure firstloadvmt(var p : ptree);
  44. begin
  45. p^.registers32:=1;
  46. p^.location.loc:=LOC_REGISTER;
  47. end;
  48. {*****************************************************************************
  49. FirstHNew
  50. *****************************************************************************}
  51. procedure firsthnew(var p : ptree);
  52. begin
  53. end;
  54. {*****************************************************************************
  55. FirstNewN
  56. *****************************************************************************}
  57. procedure firstnew(var p : ptree);
  58. begin
  59. { Standardeinleitung }
  60. if assigned(p^.left) then
  61. firstpass(p^.left);
  62. if codegenerror then
  63. exit;
  64. if assigned(p^.left) then
  65. begin
  66. p^.registers32:=p^.left^.registers32;
  67. p^.registersfpu:=p^.left^.registersfpu;
  68. {$ifdef SUPPORT_MMX}
  69. p^.registersmmx:=p^.left^.registersmmx;
  70. {$endif SUPPORT_MMX}
  71. end;
  72. { result type is already set }
  73. procinfo^.flags:=procinfo^.flags or pi_do_call;
  74. if assigned(p^.left) then
  75. p^.location.loc:=LOC_REGISTER
  76. else
  77. p^.location.loc:=LOC_REFERENCE;
  78. end;
  79. {*****************************************************************************
  80. FirstDispose
  81. *****************************************************************************}
  82. procedure firsthdispose(var p : ptree);
  83. begin
  84. firstpass(p^.left);
  85. if codegenerror then
  86. exit;
  87. p^.registers32:=p^.left^.registers32;
  88. p^.registersfpu:=p^.left^.registersfpu;
  89. {$ifdef SUPPORT_MMX}
  90. p^.registersmmx:=p^.left^.registersmmx;
  91. {$endif SUPPORT_MMX}
  92. if p^.registers32<1 then
  93. p^.registers32:=1;
  94. {
  95. if p^.left^.location.loc<>LOC_REFERENCE then
  96. CGMessage(cg_e_illegal_expression);
  97. }
  98. if p^.left^.location.loc=LOC_CREGISTER then
  99. inc(p^.registers32);
  100. p^.location.loc:=LOC_REFERENCE;
  101. p^.resulttype:=ppointerdef(p^.left^.resulttype)^.definition;
  102. end;
  103. {*****************************************************************************
  104. FirstSimpleNewDispose
  105. *****************************************************************************}
  106. procedure firstsimplenewdispose(var p : ptree);
  107. begin
  108. { this cannot be in a register !! }
  109. make_not_regable(p^.left);
  110. firstpass(p^.left);
  111. if codegenerror then
  112. exit;
  113. { check the type }
  114. if p^.left^.resulttype=nil then
  115. p^.left^.resulttype:=generrordef;
  116. if (p^.left^.resulttype^.deftype<>pointerdef) then
  117. CGMessage1(type_e_pointer_type_expected,p^.left^.resulttype^.typename);
  118. if (p^.left^.location.loc<>LOC_REFERENCE) {and
  119. (p^.left^.location.loc<>LOC_CREGISTER)} then
  120. CGMessage(cg_e_illegal_expression);
  121. p^.registers32:=p^.left^.registers32;
  122. p^.registersfpu:=p^.left^.registersfpu;
  123. {$ifdef SUPPORT_MMX}
  124. p^.registersmmx:=p^.left^.registersmmx;
  125. {$endif SUPPORT_MMX}
  126. p^.resulttype:=voiddef;
  127. procinfo^.flags:=procinfo^.flags or pi_do_call;
  128. end;
  129. {*****************************************************************************
  130. FirstAddr
  131. *****************************************************************************}
  132. procedure firstaddr(var p : ptree);
  133. var
  134. hp : ptree;
  135. hp2 : pparaitem;
  136. hp3 : pabstractprocdef;
  137. begin
  138. make_not_regable(p^.left);
  139. if not(assigned(p^.resulttype)) then
  140. begin
  141. { tp @procvar support (type of @procvar is a void pointer)
  142. Note: we need to leave the addrn in the tree,
  143. else we can't see the difference between @procvar and procvar.
  144. we set the procvarload flag so a secondpass does nothing for
  145. this node (PFV) }
  146. if (m_tp_procvar in aktmodeswitches) then
  147. begin
  148. hp:=p^.left;
  149. case hp^.treetype of
  150. calln :
  151. begin
  152. { is it a procvar? }
  153. hp:=hp^.right;
  154. if assigned(hp) then
  155. begin
  156. { remove calln node }
  157. putnode(p^.left);
  158. p^.left:=hp;
  159. firstpass(hp);
  160. p^.procvarload:=true;
  161. end;
  162. end;
  163. loadn,
  164. subscriptn,
  165. typeconvn,
  166. vecn,
  167. derefn :
  168. begin
  169. firstpass(hp);
  170. if codegenerror then
  171. exit;
  172. if hp^.resulttype^.deftype=procvardef then
  173. begin
  174. p^.procvarload:=true;
  175. end;
  176. end;
  177. end;
  178. end;
  179. if p^.procvarload then
  180. begin
  181. p^.registers32:=p^.left^.registers32;
  182. p^.registersfpu:=p^.left^.registersfpu;
  183. {$ifdef SUPPORT_MMX}
  184. p^.registersmmx:=p^.left^.registersmmx;
  185. {$endif SUPPORT_MMX}
  186. if p^.registers32<1 then
  187. p^.registers32:=1;
  188. p^.location.loc:=p^.left^.location.loc;
  189. p^.resulttype:=voidpointerdef;
  190. exit;
  191. end;
  192. { proc 2 procvar ? }
  193. if p^.left^.treetype=calln then
  194. begin
  195. { generate a methodcallnode or proccallnode }
  196. { we shouldn't convert things like @tcollection.load }
  197. if (p^.left^.symtableprocentry^.owner^.symtabletype=objectsymtable) and
  198. not(assigned(p^.left^.methodpointer) and (p^.left^.methodpointer^.treetype=typen)) then
  199. begin
  200. hp:=genloadmethodcallnode(pprocsym(p^.left^.symtableprocentry),p^.left^.symtableproc,
  201. getcopy(p^.left^.methodpointer));
  202. end
  203. else
  204. hp:=genloadcallnode(pprocsym(p^.left^.symtableprocentry),p^.left^.symtableproc);
  205. { result is a procedure variable }
  206. { No, to be TP compatible, you must return a pointer to
  207. the procedure that is stored in the procvar.}
  208. if not(m_tp_procvar in aktmodeswitches) then
  209. begin
  210. p^.resulttype:=new(pprocvardef,init);
  211. { it could also be a procvar, not only pprocsym ! }
  212. if p^.left^.symtableprocentry^.typ=varsym then
  213. hp3:=pabstractprocdef(pvarsym(p^.left^.symtableentry)^.definition)
  214. else
  215. hp3:=pabstractprocdef(pprocsym(p^.left^.symtableprocentry)^.definition);
  216. pprocvardef(p^.resulttype)^.proctypeoption:=hp3^.proctypeoption;
  217. pprocvardef(p^.resulttype)^.proccalloptions:=hp3^.proccalloptions;
  218. pprocvardef(p^.resulttype)^.procoptions:=hp3^.procoptions;
  219. pprocvardef(p^.resulttype)^.retdef:=hp3^.retdef;
  220. pprocvardef(p^.resulttype)^.symtablelevel:=hp3^.symtablelevel;
  221. { method ? then set the methodpointer flag }
  222. if (hp3^.owner^.symtabletype=objectsymtable) and
  223. (pobjectdef(hp3^.owner^.defowner)^.is_class) then
  224. {$ifdef INCLUDEOK}
  225. include(pprocvardef(p^.resulttype)^.procoptions,po_methodpointer);
  226. {$else}
  227. pprocvardef(p^.resulttype)^.procoptions:=pprocvardef(p^.resulttype)^.procoptions+[po_methodpointer];
  228. {$endif}
  229. { we need to process the parameters reverse so they are inserted
  230. in the correct right2left order (PFV) }
  231. hp2:=pparaitem(hp3^.para^.last);
  232. while assigned(hp2) do
  233. begin
  234. pprocvardef(p^.resulttype)^.concatdef(hp2^.data,hp2^.paratyp);
  235. hp2:=pparaitem(hp2^.previous);
  236. end;
  237. end
  238. else
  239. p^.resulttype:=voidpointerdef;
  240. disposetree(p^.left);
  241. p^.left:=hp;
  242. end
  243. else
  244. begin
  245. { what are we getting the address from an absolute sym? }
  246. hp:=p^.left;
  247. while assigned(hp) and (hp^.treetype in [vecn,derefn,subscriptn]) do
  248. hp:=hp^.left;
  249. if assigned(hp) and (hp^.treetype=loadn) and
  250. ((hp^.symtableentry^.typ=absolutesym) and
  251. pabsolutesym(hp^.symtableentry)^.absseg) then
  252. begin
  253. if not(cs_typed_addresses in aktlocalswitches) then
  254. p^.resulttype:=voidfarpointerdef
  255. else
  256. p^.resulttype:=new(ppointerdef,initfar(p^.left^.resulttype));
  257. end
  258. else
  259. begin
  260. if not(cs_typed_addresses in aktlocalswitches) then
  261. p^.resulttype:=voidpointerdef
  262. else
  263. p^.resulttype:=new(ppointerdef,init(p^.left^.resulttype));
  264. end;
  265. end;
  266. end;
  267. firstpass(p^.left);
  268. { this is like the function addr }
  269. inc(parsing_para_level);
  270. set_varstate(p^.left,false);
  271. dec(parsing_para_level);
  272. if codegenerror then
  273. exit;
  274. { don't allow constants }
  275. if is_constnode(p^.left) then
  276. begin
  277. aktfilepos:=p^.left^.fileinfo;
  278. CGMessage(type_e_no_addr_of_constant);
  279. end
  280. else
  281. begin
  282. { we should allow loc_mem for @string }
  283. if not(p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  284. begin
  285. aktfilepos:=p^.left^.fileinfo;
  286. CGMessage(cg_e_illegal_expression);
  287. end;
  288. end;
  289. p^.registers32:=p^.left^.registers32;
  290. p^.registersfpu:=p^.left^.registersfpu;
  291. {$ifdef SUPPORT_MMX}
  292. p^.registersmmx:=p^.left^.registersmmx;
  293. {$endif SUPPORT_MMX}
  294. if p^.registers32<1 then
  295. p^.registers32:=1;
  296. { is this right for object of methods ?? }
  297. p^.location.loc:=LOC_REGISTER;
  298. end;
  299. {*****************************************************************************
  300. FirstDoubleAddr
  301. *****************************************************************************}
  302. procedure firstdoubleaddr(var p : ptree);
  303. begin
  304. make_not_regable(p^.left);
  305. firstpass(p^.left);
  306. inc(parsing_para_level);
  307. set_varstate(p^.left,false);
  308. dec(parsing_para_level);
  309. if p^.resulttype=nil then
  310. p^.resulttype:=voidpointerdef;
  311. if codegenerror then
  312. exit;
  313. if (p^.left^.resulttype^.deftype)<>procvardef then
  314. CGMessage(cg_e_illegal_expression);
  315. if (p^.left^.location.loc<>LOC_REFERENCE) then
  316. CGMessage(cg_e_illegal_expression);
  317. p^.registers32:=p^.left^.registers32;
  318. p^.registersfpu:=p^.left^.registersfpu;
  319. {$ifdef SUPPORT_MMX}
  320. p^.registersmmx:=p^.left^.registersmmx;
  321. {$endif SUPPORT_MMX}
  322. if p^.registers32<1 then
  323. p^.registers32:=1;
  324. p^.location.loc:=LOC_REGISTER;
  325. end;
  326. {*****************************************************************************
  327. FirstDeRef
  328. *****************************************************************************}
  329. procedure firstderef(var p : ptree);
  330. begin
  331. firstpass(p^.left);
  332. set_varstate(p^.left,true);
  333. if codegenerror then
  334. begin
  335. p^.resulttype:=generrordef;
  336. exit;
  337. end;
  338. p^.registers32:=max(p^.left^.registers32,1);
  339. p^.registersfpu:=p^.left^.registersfpu;
  340. {$ifdef SUPPORT_MMX}
  341. p^.registersmmx:=p^.left^.registersmmx;
  342. {$endif SUPPORT_MMX}
  343. if p^.left^.resulttype^.deftype<>pointerdef then
  344. CGMessage(cg_e_invalid_qualifier);
  345. p^.resulttype:=ppointerdef(p^.left^.resulttype)^.definition;
  346. p^.location.loc:=LOC_REFERENCE;
  347. end;
  348. {*****************************************************************************
  349. FirstSubScript
  350. *****************************************************************************}
  351. procedure firstsubscript(var p : ptree);
  352. begin
  353. firstpass(p^.left);
  354. if codegenerror then
  355. begin
  356. p^.resulttype:=generrordef;
  357. exit;
  358. end;
  359. p^.resulttype:=p^.vs^.definition;
  360. p^.registers32:=p^.left^.registers32;
  361. p^.registersfpu:=p^.left^.registersfpu;
  362. {$ifdef SUPPORT_MMX}
  363. p^.registersmmx:=p^.left^.registersmmx;
  364. {$endif SUPPORT_MMX}
  365. { classes must be dereferenced implicit }
  366. if (p^.left^.resulttype^.deftype=objectdef) and
  367. pobjectdef(p^.left^.resulttype)^.is_class then
  368. begin
  369. if p^.registers32=0 then
  370. p^.registers32:=1;
  371. p^.location.loc:=LOC_REFERENCE;
  372. end
  373. else
  374. begin
  375. if (p^.left^.location.loc<>LOC_MEM) and
  376. (p^.left^.location.loc<>LOC_REFERENCE) then
  377. CGMessage(cg_e_illegal_expression);
  378. set_location(p^.location,p^.left^.location);
  379. end;
  380. end;
  381. {*****************************************************************************
  382. FirstVec
  383. *****************************************************************************}
  384. procedure firstvec(var p : ptree);
  385. var
  386. harr : pdef;
  387. ct : tconverttype;
  388. {$ifdef consteval}
  389. tcsym : ptypedconstsym;
  390. {$endif}
  391. begin
  392. firstpass(p^.left);
  393. firstpass(p^.right);
  394. if codegenerror then
  395. exit;
  396. { range check only for arrays }
  397. if (p^.left^.resulttype^.deftype=arraydef) then
  398. begin
  399. if (isconvertable(p^.right^.resulttype,parraydef(p^.left^.resulttype)^.rangedef,
  400. ct,ordconstn,false)=0) and
  401. not(is_equal(p^.right^.resulttype,parraydef(p^.left^.resulttype)^.rangedef)) then
  402. CGMessage(type_e_mismatch);
  403. end;
  404. { Never convert a boolean or a char !}
  405. { maybe type conversion }
  406. if (p^.right^.resulttype^.deftype<>enumdef) and
  407. not(is_char(p^.right^.resulttype)) and
  408. not(is_boolean(p^.right^.resulttype)) then
  409. begin
  410. p^.right:=gentypeconvnode(p^.right,s32bitdef);
  411. firstpass(p^.right);
  412. if codegenerror then
  413. exit;
  414. end;
  415. { determine return type }
  416. if not assigned(p^.resulttype) then
  417. if p^.left^.resulttype^.deftype=arraydef then
  418. p^.resulttype:=parraydef(p^.left^.resulttype)^.definition
  419. else if (p^.left^.resulttype^.deftype=pointerdef) then
  420. begin
  421. { convert pointer to array }
  422. harr:=new(parraydef,init(0,$7fffffff,s32bitdef));
  423. parraydef(harr)^.definition:=ppointerdef(p^.left^.resulttype)^.definition;
  424. p^.left:=gentypeconvnode(p^.left,harr);
  425. firstpass(p^.left);
  426. if codegenerror then
  427. begin
  428. exit;
  429. end;
  430. p^.resulttype:=parraydef(harr)^.definition
  431. end
  432. else if p^.left^.resulttype^.deftype=stringdef then
  433. begin
  434. { indexed access to strings }
  435. case pstringdef(p^.left^.resulttype)^.string_typ of
  436. {
  437. st_widestring : p^.resulttype:=cwchardef;
  438. }
  439. st_ansistring : p^.resulttype:=cchardef;
  440. st_longstring : p^.resulttype:=cchardef;
  441. st_shortstring : p^.resulttype:=cchardef;
  442. end;
  443. end
  444. else
  445. CGMessage(type_e_mismatch);
  446. { the register calculation is easy if a const index is used }
  447. if p^.right^.treetype=ordconstn then
  448. begin
  449. {$ifdef consteval}
  450. { constant evaluation }
  451. if (p^.left^.treetype=loadn) and
  452. (p^.left^.symtableentry^.typ=typedconstsym) then
  453. begin
  454. tcsym:=ptypedconstsym(p^.left^.symtableentry);
  455. if tcsym^.defintion^.typ=stringdef then
  456. begin
  457. end;
  458. end;
  459. {$endif}
  460. p^.registers32:=p^.left^.registers32;
  461. { for ansi/wide strings, we need at least one register }
  462. if is_ansistring(p^.left^.resulttype) or
  463. is_widestring(p^.left^.resulttype) then
  464. p^.registers32:=max(p^.registers32,1);
  465. end
  466. else
  467. begin
  468. { this rules are suboptimal, but they should give }
  469. { good results }
  470. p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
  471. { for ansi/wide strings, we need at least one register }
  472. if is_ansistring(p^.left^.resulttype) or
  473. is_widestring(p^.left^.resulttype) then
  474. p^.registers32:=max(p^.registers32,1);
  475. { need we an extra register when doing the restore ? }
  476. if (p^.left^.registers32<=p^.right^.registers32) and
  477. { only if the node needs less than 3 registers }
  478. { two for the right node and one for the }
  479. { left address }
  480. (p^.registers32<3) then
  481. inc(p^.registers32);
  482. { need we an extra register for the index ? }
  483. if (p^.right^.location.loc<>LOC_REGISTER)
  484. { only if the right node doesn't need a register }
  485. and (p^.right^.registers32<1) then
  486. inc(p^.registers32);
  487. { not correct, but what works better ?
  488. if p^.left^.registers32>0 then
  489. p^.registers32:=max(p^.registers32,2)
  490. else
  491. min. one register
  492. p^.registers32:=max(p^.registers32,1);
  493. }
  494. end;
  495. p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
  496. {$ifdef SUPPORT_MMX}
  497. p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
  498. {$endif SUPPORT_MMX}
  499. if p^.left^.location.loc in [LOC_CREGISTER,LOC_REFERENCE] then
  500. p^.location.loc:=LOC_REFERENCE
  501. else
  502. p^.location.loc:=LOC_MEM;
  503. end;
  504. {*****************************************************************************
  505. FirstSelf
  506. *****************************************************************************}
  507. procedure firstself(var p : ptree);
  508. begin
  509. if (p^.resulttype^.deftype=classrefdef) or
  510. ((p^.resulttype^.deftype=objectdef)
  511. and pobjectdef(p^.resulttype)^.is_class
  512. ) then
  513. p^.location.loc:=LOC_CREGISTER
  514. else
  515. p^.location.loc:=LOC_REFERENCE;
  516. end;
  517. {*****************************************************************************
  518. FirstWithN
  519. *****************************************************************************}
  520. procedure firstwith(var p : ptree);
  521. var
  522. symtable : pwithsymtable;
  523. i : longint;
  524. begin
  525. if assigned(p^.left) and assigned(p^.right) then
  526. begin
  527. firstpass(p^.left);
  528. { is this correct ? At least after is like if used }
  529. inc(parsing_para_level);
  530. set_varstate(p^.left,false);
  531. dec(parsing_para_level);
  532. if codegenerror then
  533. exit;
  534. symtable:=p^.withsymtable;
  535. for i:=1 to p^.tablecount do
  536. begin
  537. if (p^.left^.treetype=loadn) and
  538. (p^.left^.symtable=aktprocsym^.definition^.localst) then
  539. symtable^.direct_with:=true;
  540. symtable^.withnode:=p;
  541. symtable:=pwithsymtable(symtable^.next);
  542. end;
  543. firstpass(p^.right);
  544. if codegenerror then
  545. exit;
  546. left_right_max(p);
  547. p^.resulttype:=voiddef;
  548. end
  549. else
  550. begin
  551. { optimization }
  552. disposetree(p);
  553. p:=nil;
  554. end;
  555. end;
  556. end.
  557. {
  558. $Log$
  559. Revision 1.34 1999-11-18 15:34:51 pierre
  560. * Notes/Hints for local syms changed to
  561. Set_varstate function
  562. Revision 1.33 1999/11/17 17:05:07 pierre
  563. * Notes/hints changes
  564. Revision 1.32 1999/11/06 14:34:30 peter
  565. * truncated log to 20 revs
  566. Revision 1.31 1999/10/26 12:30:46 peter
  567. * const parameter is now checked
  568. * better and generic check if a node can be used for assigning
  569. * export fixes
  570. * procvar equal works now (it never had worked at least from 0.99.8)
  571. * defcoll changed to linkedlist with pparaitem so it can easily be
  572. walked both directions
  573. Revision 1.30 1999/10/13 10:40:55 peter
  574. * subscript support for tp_procvar
  575. Revision 1.29 1999/09/27 23:45:02 peter
  576. * procinfo is now a pointer
  577. * support for result setting in sub procedure
  578. Revision 1.28 1999/09/17 17:14:12 peter
  579. * @procvar fixes for tp mode
  580. * @<id>:= gives now an error
  581. Revision 1.27 1999/09/11 11:10:39 florian
  582. * fix of my previous commit, make cycle was broken
  583. Revision 1.26 1999/09/11 09:08:34 florian
  584. * fixed bug 596
  585. * fixed some problems with procedure variables and procedures of object,
  586. especially in TP mode. Procedure of object doesn't apply only to classes,
  587. it is also allowed for objects !!
  588. Revision 1.25 1999/08/23 23:34:15 pierre
  589. * one more register needed if hnewn with CREGISTER
  590. Revision 1.24 1999/08/05 16:53:25 peter
  591. * V_Fatal=1, all other V_ are also increased
  592. * Check for local procedure when assigning procvar
  593. * fixed comment parsing because directives
  594. * oldtp mode directives better supported
  595. * added some messages to errore.msg
  596. Revision 1.23 1999/08/04 00:23:44 florian
  597. * renamed i386asm and i386base to cpuasm and cpubase
  598. Revision 1.22 1999/08/03 22:03:35 peter
  599. * moved bitmask constants to sets
  600. * some other type/const renamings
  601. Revision 1.21 1999/07/16 10:04:39 peter
  602. * merged
  603. Revision 1.20 1999/07/05 20:25:41 peter
  604. * merged
  605. Revision 1.19 1999/07/05 16:24:17 peter
  606. * merged
  607. Revision 1.18.2.4 1999/07/16 09:54:59 peter
  608. * @procvar support in tp7 mode works again
  609. Revision 1.18.2.3 1999/07/05 20:06:47 peter
  610. * give error instead of warning for ln(0) and sqrt(0)
  611. Revision 1.18.2.2 1999/07/05 16:22:56 peter
  612. * error if @constant
  613. Revision 1.18.2.1 1999/06/28 00:33:53 pierre
  614. * better error position bug0269
  615. Revision 1.18 1999/06/03 09:34:12 peter
  616. * better methodpointer check for proc->procvar
  617. Revision 1.17 1999/05/27 19:45:24 peter
  618. * removed oldasm
  619. * plabel -> pasmlabel
  620. * -a switches to source writing automaticly
  621. * assembler readers OOPed
  622. * asmsymbol automaticly external
  623. * jumptables and other label fixes for asm readers
  624. Revision 1.16 1999/05/18 09:52:21 peter
  625. * procedure of object and addrn fixes
  626. }