tcmem.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  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. store_valid : boolean;
  137. hp3 : pabstractprocdef;
  138. begin
  139. make_not_regable(p^.left);
  140. if not(assigned(p^.resulttype)) then
  141. begin
  142. { tp @procvar support (type of @procvar is a void pointer)
  143. Note: we need to leave the addrn in the tree,
  144. else we can't see the difference between @procvar and procvar.
  145. we set the procvarload flag so a secondpass does nothing for
  146. this node (PFV) }
  147. if (m_tp_procvar in aktmodeswitches) then
  148. begin
  149. hp:=p^.left;
  150. case hp^.treetype of
  151. calln :
  152. begin
  153. { is it a procvar? }
  154. hp:=hp^.right;
  155. if assigned(hp) then
  156. begin
  157. { remove calln node }
  158. putnode(p^.left);
  159. p^.left:=hp;
  160. firstpass(hp);
  161. p^.procvarload:=true;
  162. end;
  163. end;
  164. loadn,
  165. subscriptn,
  166. typeconvn,
  167. vecn,
  168. derefn :
  169. begin
  170. firstpass(hp);
  171. if codegenerror then
  172. exit;
  173. if hp^.resulttype^.deftype=procvardef then
  174. begin
  175. p^.procvarload:=true;
  176. end;
  177. end;
  178. end;
  179. end;
  180. if p^.procvarload then
  181. begin
  182. p^.registers32:=p^.left^.registers32;
  183. p^.registersfpu:=p^.left^.registersfpu;
  184. {$ifdef SUPPORT_MMX}
  185. p^.registersmmx:=p^.left^.registersmmx;
  186. {$endif SUPPORT_MMX}
  187. if p^.registers32<1 then
  188. p^.registers32:=1;
  189. p^.location.loc:=p^.left^.location.loc;
  190. p^.resulttype:=voidpointerdef;
  191. exit;
  192. end;
  193. { proc 2 procvar ? }
  194. if p^.left^.treetype=calln then
  195. begin
  196. { generate a methodcallnode or proccallnode }
  197. { we shouldn't convert things like @tcollection.load }
  198. if (p^.left^.symtableprocentry^.owner^.symtabletype=objectsymtable) and
  199. not(assigned(p^.left^.methodpointer) and (p^.left^.methodpointer^.treetype=typen)) then
  200. begin
  201. hp:=genloadmethodcallnode(pprocsym(p^.left^.symtableprocentry),p^.left^.symtableproc,
  202. getcopy(p^.left^.methodpointer));
  203. end
  204. else
  205. hp:=genloadcallnode(pprocsym(p^.left^.symtableprocentry),p^.left^.symtableproc);
  206. { result is a procedure variable }
  207. { No, to be TP compatible, you must return a pointer to
  208. the procedure that is stored in the procvar.}
  209. if not(m_tp_procvar in aktmodeswitches) then
  210. begin
  211. p^.resulttype:=new(pprocvardef,init);
  212. { it could also be a procvar, not only pprocsym ! }
  213. if p^.left^.symtableprocentry^.typ=varsym then
  214. hp3:=pabstractprocdef(pvarsym(p^.left^.symtableentry)^.definition)
  215. else
  216. hp3:=pabstractprocdef(pprocsym(p^.left^.symtableprocentry)^.definition);
  217. pprocvardef(p^.resulttype)^.proctypeoption:=hp3^.proctypeoption;
  218. pprocvardef(p^.resulttype)^.proccalloptions:=hp3^.proccalloptions;
  219. pprocvardef(p^.resulttype)^.procoptions:=hp3^.procoptions;
  220. pprocvardef(p^.resulttype)^.retdef:=hp3^.retdef;
  221. pprocvardef(p^.resulttype)^.symtablelevel:=hp3^.symtablelevel;
  222. { method ? then set the methodpointer flag }
  223. if (hp3^.owner^.symtabletype=objectsymtable) and
  224. (pobjectdef(hp3^.owner^.defowner)^.is_class) then
  225. {$ifdef INCLUDEOK}
  226. include(pprocvardef(p^.resulttype)^.procoptions,po_methodpointer);
  227. {$else}
  228. pprocvardef(p^.resulttype)^.procoptions:=pprocvardef(p^.resulttype)^.procoptions+[po_methodpointer];
  229. {$endif}
  230. { we need to process the parameters reverse so they are inserted
  231. in the correct right2left order (PFV) }
  232. hp2:=pparaitem(hp3^.para^.last);
  233. while assigned(hp2) do
  234. begin
  235. pprocvardef(p^.resulttype)^.concatdef(hp2^.data,hp2^.paratyp);
  236. hp2:=pparaitem(hp2^.previous);
  237. end;
  238. end
  239. else
  240. p^.resulttype:=voidpointerdef;
  241. disposetree(p^.left);
  242. p^.left:=hp;
  243. end
  244. else
  245. begin
  246. { what are we getting the address from an absolute sym? }
  247. hp:=p^.left;
  248. while assigned(hp) and (hp^.treetype in [vecn,derefn,subscriptn]) do
  249. hp:=hp^.left;
  250. if assigned(hp) and (hp^.treetype=loadn) and
  251. ((hp^.symtableentry^.typ=absolutesym) and
  252. pabsolutesym(hp^.symtableentry)^.absseg) then
  253. begin
  254. if not(cs_typed_addresses in aktlocalswitches) then
  255. p^.resulttype:=voidfarpointerdef
  256. else
  257. p^.resulttype:=new(ppointerdef,initfar(p^.left^.resulttype));
  258. end
  259. else
  260. begin
  261. if not(cs_typed_addresses in aktlocalswitches) then
  262. p^.resulttype:=voidpointerdef
  263. else
  264. p^.resulttype:=new(ppointerdef,init(p^.left^.resulttype));
  265. end;
  266. end;
  267. end;
  268. store_valid:=must_be_valid;
  269. must_be_valid:=false;
  270. firstpass(p^.left);
  271. must_be_valid:=store_valid;
  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. if p^.resulttype=nil then
  307. p^.resulttype:=voidpointerdef;
  308. if codegenerror then
  309. exit;
  310. if (p^.left^.resulttype^.deftype)<>procvardef then
  311. CGMessage(cg_e_illegal_expression);
  312. if (p^.left^.location.loc<>LOC_REFERENCE) then
  313. CGMessage(cg_e_illegal_expression);
  314. p^.registers32:=p^.left^.registers32;
  315. p^.registersfpu:=p^.left^.registersfpu;
  316. {$ifdef SUPPORT_MMX}
  317. p^.registersmmx:=p^.left^.registersmmx;
  318. {$endif SUPPORT_MMX}
  319. if p^.registers32<1 then
  320. p^.registers32:=1;
  321. p^.location.loc:=LOC_REGISTER;
  322. end;
  323. {*****************************************************************************
  324. FirstDeRef
  325. *****************************************************************************}
  326. procedure firstderef(var p : ptree);
  327. var store_valid : boolean;
  328. begin
  329. store_valid:=must_be_valid;
  330. must_be_valid:=true;
  331. firstpass(p^.left);
  332. must_be_valid:=store_valid;
  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. store_valid : boolean;
  389. {$ifdef consteval}
  390. tcsym : ptypedconstsym;
  391. {$endif}
  392. begin
  393. firstpass(p^.left);
  394. firstpass(p^.right);
  395. if codegenerror then
  396. exit;
  397. { range check only for arrays }
  398. if (p^.left^.resulttype^.deftype=arraydef) then
  399. begin
  400. if (isconvertable(p^.right^.resulttype,parraydef(p^.left^.resulttype)^.rangedef,
  401. ct,ordconstn,false)=0) and
  402. not(is_equal(p^.right^.resulttype,parraydef(p^.left^.resulttype)^.rangedef)) then
  403. CGMessage(type_e_mismatch);
  404. end;
  405. { Never convert a boolean or a char !}
  406. { maybe type conversion }
  407. if (p^.right^.resulttype^.deftype<>enumdef) and
  408. not(is_char(p^.right^.resulttype)) and
  409. not(is_boolean(p^.right^.resulttype)) then
  410. begin
  411. p^.right:=gentypeconvnode(p^.right,s32bitdef);
  412. firstpass(p^.right);
  413. if codegenerror then
  414. exit;
  415. end;
  416. { determine return type }
  417. if not assigned(p^.resulttype) then
  418. if p^.left^.resulttype^.deftype=arraydef then
  419. p^.resulttype:=parraydef(p^.left^.resulttype)^.definition
  420. else if (p^.left^.resulttype^.deftype=pointerdef) then
  421. begin
  422. { convert pointer to array }
  423. harr:=new(parraydef,init(0,$7fffffff,s32bitdef));
  424. parraydef(harr)^.definition:=ppointerdef(p^.left^.resulttype)^.definition;
  425. p^.left:=gentypeconvnode(p^.left,harr);
  426. store_valid:=must_be_valid;
  427. must_be_valid:=true;
  428. firstpass(p^.left);
  429. must_be_valid:=store_valid;
  430. if codegenerror then
  431. exit;
  432. p^.resulttype:=parraydef(harr)^.definition
  433. end
  434. else if p^.left^.resulttype^.deftype=stringdef then
  435. begin
  436. { indexed access to strings }
  437. case pstringdef(p^.left^.resulttype)^.string_typ of
  438. {
  439. st_widestring : p^.resulttype:=cwchardef;
  440. }
  441. st_ansistring : p^.resulttype:=cchardef;
  442. st_longstring : p^.resulttype:=cchardef;
  443. st_shortstring : p^.resulttype:=cchardef;
  444. end;
  445. end
  446. else
  447. CGMessage(type_e_mismatch);
  448. { the register calculation is easy if a const index is used }
  449. if p^.right^.treetype=ordconstn then
  450. begin
  451. {$ifdef consteval}
  452. { constant evaluation }
  453. if (p^.left^.treetype=loadn) and
  454. (p^.left^.symtableentry^.typ=typedconstsym) then
  455. begin
  456. tcsym:=ptypedconstsym(p^.left^.symtableentry);
  457. if tcsym^.defintion^.typ=stringdef then
  458. begin
  459. end;
  460. end;
  461. {$endif}
  462. p^.registers32:=p^.left^.registers32;
  463. { for ansi/wide strings, we need at least one register }
  464. if is_ansistring(p^.left^.resulttype) or
  465. is_widestring(p^.left^.resulttype) then
  466. p^.registers32:=max(p^.registers32,1);
  467. end
  468. else
  469. begin
  470. { this rules are suboptimal, but they should give }
  471. { good results }
  472. p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
  473. { for ansi/wide strings, we need at least one register }
  474. if is_ansistring(p^.left^.resulttype) or
  475. is_widestring(p^.left^.resulttype) then
  476. p^.registers32:=max(p^.registers32,1);
  477. { need we an extra register when doing the restore ? }
  478. if (p^.left^.registers32<=p^.right^.registers32) and
  479. { only if the node needs less than 3 registers }
  480. { two for the right node and one for the }
  481. { left address }
  482. (p^.registers32<3) then
  483. inc(p^.registers32);
  484. { need we an extra register for the index ? }
  485. if (p^.right^.location.loc<>LOC_REGISTER)
  486. { only if the right node doesn't need a register }
  487. and (p^.right^.registers32<1) then
  488. inc(p^.registers32);
  489. { not correct, but what works better ?
  490. if p^.left^.registers32>0 then
  491. p^.registers32:=max(p^.registers32,2)
  492. else
  493. min. one register
  494. p^.registers32:=max(p^.registers32,1);
  495. }
  496. end;
  497. p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
  498. {$ifdef SUPPORT_MMX}
  499. p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
  500. {$endif SUPPORT_MMX}
  501. if p^.left^.location.loc in [LOC_CREGISTER,LOC_REFERENCE] then
  502. p^.location.loc:=LOC_REFERENCE
  503. else
  504. p^.location.loc:=LOC_MEM;
  505. end;
  506. {*****************************************************************************
  507. FirstSelf
  508. *****************************************************************************}
  509. procedure firstself(var p : ptree);
  510. begin
  511. if (p^.resulttype^.deftype=classrefdef) or
  512. ((p^.resulttype^.deftype=objectdef)
  513. and pobjectdef(p^.resulttype)^.is_class
  514. ) then
  515. p^.location.loc:=LOC_CREGISTER
  516. else
  517. p^.location.loc:=LOC_REFERENCE;
  518. end;
  519. {*****************************************************************************
  520. FirstWithN
  521. *****************************************************************************}
  522. procedure firstwith(var p : ptree);
  523. var
  524. symtable : pwithsymtable;
  525. i : longint;
  526. begin
  527. if assigned(p^.left) and assigned(p^.right) then
  528. begin
  529. firstpass(p^.left);
  530. if codegenerror then
  531. exit;
  532. symtable:=p^.withsymtable;
  533. for i:=1 to p^.tablecount do
  534. begin
  535. if (p^.left^.treetype=loadn) and
  536. (p^.left^.symtable=aktprocsym^.definition^.localst) then
  537. symtable^.direct_with:=true;
  538. symtable^.withnode:=p;
  539. symtable:=pwithsymtable(symtable^.next);
  540. end;
  541. firstpass(p^.right);
  542. if codegenerror then
  543. exit;
  544. left_right_max(p);
  545. p^.resulttype:=voiddef;
  546. end
  547. else
  548. begin
  549. { optimization }
  550. disposetree(p);
  551. p:=nil;
  552. end;
  553. end;
  554. end.
  555. {
  556. $Log$
  557. Revision 1.33 1999-11-17 17:05:07 pierre
  558. * Notes/hints changes
  559. Revision 1.32 1999/11/06 14:34:30 peter
  560. * truncated log to 20 revs
  561. Revision 1.31 1999/10/26 12:30:46 peter
  562. * const parameter is now checked
  563. * better and generic check if a node can be used for assigning
  564. * export fixes
  565. * procvar equal works now (it never had worked at least from 0.99.8)
  566. * defcoll changed to linkedlist with pparaitem so it can easily be
  567. walked both directions
  568. Revision 1.30 1999/10/13 10:40:55 peter
  569. * subscript support for tp_procvar
  570. Revision 1.29 1999/09/27 23:45:02 peter
  571. * procinfo is now a pointer
  572. * support for result setting in sub procedure
  573. Revision 1.28 1999/09/17 17:14:12 peter
  574. * @procvar fixes for tp mode
  575. * @<id>:= gives now an error
  576. Revision 1.27 1999/09/11 11:10:39 florian
  577. * fix of my previous commit, make cycle was broken
  578. Revision 1.26 1999/09/11 09:08:34 florian
  579. * fixed bug 596
  580. * fixed some problems with procedure variables and procedures of object,
  581. especially in TP mode. Procedure of object doesn't apply only to classes,
  582. it is also allowed for objects !!
  583. Revision 1.25 1999/08/23 23:34:15 pierre
  584. * one more register needed if hnewn with CREGISTER
  585. Revision 1.24 1999/08/05 16:53:25 peter
  586. * V_Fatal=1, all other V_ are also increased
  587. * Check for local procedure when assigning procvar
  588. * fixed comment parsing because directives
  589. * oldtp mode directives better supported
  590. * added some messages to errore.msg
  591. Revision 1.23 1999/08/04 00:23:44 florian
  592. * renamed i386asm and i386base to cpuasm and cpubase
  593. Revision 1.22 1999/08/03 22:03:35 peter
  594. * moved bitmask constants to sets
  595. * some other type/const renamings
  596. Revision 1.21 1999/07/16 10:04:39 peter
  597. * merged
  598. Revision 1.20 1999/07/05 20:25:41 peter
  599. * merged
  600. Revision 1.19 1999/07/05 16:24:17 peter
  601. * merged
  602. Revision 1.18.2.4 1999/07/16 09:54:59 peter
  603. * @procvar support in tp7 mode works again
  604. Revision 1.18.2.3 1999/07/05 20:06:47 peter
  605. * give error instead of warning for ln(0) and sqrt(0)
  606. Revision 1.18.2.2 1999/07/05 16:22:56 peter
  607. * error if @constant
  608. Revision 1.18.2.1 1999/06/28 00:33:53 pierre
  609. * better error position bug0269
  610. Revision 1.18 1999/06/03 09:34:12 peter
  611. * better methodpointer check for proc->procvar
  612. Revision 1.17 1999/05/27 19:45:24 peter
  613. * removed oldasm
  614. * plabel -> pasmlabel
  615. * -a switches to source writing automaticly
  616. * assembler readers OOPed
  617. * asmsymbol automaticly external
  618. * jumptables and other label fixes for asm readers
  619. Revision 1.16 1999/05/18 09:52:21 peter
  620. * procedure of object and addrn fixes
  621. }