tcld.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. Type checking and register allocation for load/assignment 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 tcld;
  19. interface
  20. uses
  21. tree;
  22. procedure firstload(var p : ptree);
  23. procedure firstassignment(var p : ptree);
  24. procedure firstfuncret(var p : ptree);
  25. procedure firstarrayconstructrange(var p:ptree);
  26. procedure firstarrayconstruct(var p : ptree);
  27. procedure firsttype(var p : ptree);
  28. implementation
  29. uses
  30. cobjects,verbose,globtype,globals,systems,
  31. symconst,symtable,aasm,types,
  32. hcodegen,htypechk,pass_1,
  33. tccnv,cpubase
  34. {$ifdef i386}
  35. ,tgeni386
  36. {$endif}
  37. ;
  38. {*****************************************************************************
  39. FirstLoad
  40. *****************************************************************************}
  41. procedure firstload(var p : ptree);
  42. var
  43. p1 : ptree;
  44. begin
  45. if (p^.symtable^.symtabletype=withsymtable) and
  46. (pwithsymtable(p^.symtable)^.direct_with) and
  47. (p^.symtableentry^.typ=varsym) then
  48. begin
  49. p1:=getcopy(ptree(pwithsymtable(p^.symtable)^.withrefnode));
  50. p1:=gensubscriptnode(pvarsym(p^.symtableentry),p1);
  51. putnode(p);
  52. p:=p1;
  53. firstpass(p);
  54. exit;
  55. end;
  56. p^.location.loc:=LOC_REFERENCE;
  57. p^.registers32:=0;
  58. p^.registersfpu:=0;
  59. {$ifdef SUPPORT_MMX}
  60. p^.registersmmx:=0;
  61. {$endif SUPPORT_MMX}
  62. if p^.symtableentry^.typ=funcretsym then
  63. begin
  64. p1:=genzeronode(funcretn);
  65. p1^.funcretprocinfo:=pprocinfo(pfuncretsym(p^.symtableentry)^.funcretprocinfo);
  66. p1^.retdef:=pfuncretsym(p^.symtableentry)^.funcretdef;
  67. firstpass(p1);
  68. putnode(p);
  69. p:=p1;
  70. exit;
  71. end;
  72. if p^.symtableentry^.typ=absolutesym then
  73. begin
  74. p^.resulttype:=pabsolutesym(p^.symtableentry)^.definition;
  75. if pabsolutesym(p^.symtableentry)^.abstyp=tovar then
  76. p^.symtableentry:=pabsolutesym(p^.symtableentry)^.ref;
  77. p^.symtable:=p^.symtableentry^.owner;
  78. p^.is_absolute:=true;
  79. end;
  80. case p^.symtableentry^.typ of
  81. absolutesym :;
  82. constsym:
  83. begin
  84. if pconstsym(p^.symtableentry)^.consttype=constresourcestring then
  85. begin
  86. p^.resulttype:=cansistringdef;
  87. p^.location.loc:=LOC_MEM;
  88. end
  89. else
  90. internalerror(22799);
  91. end;
  92. varsym :
  93. begin
  94. if not(p^.is_absolute) and (p^.resulttype=nil) then
  95. p^.resulttype:=pvarsym(p^.symtableentry)^.definition;
  96. if (p^.symtable^.symtabletype in [parasymtable,localsymtable]) and
  97. (lexlevel>p^.symtable^.symtablelevel) then
  98. begin
  99. { if the variable is in an other stackframe then we need
  100. a register to dereference }
  101. if (p^.symtable^.symtablelevel)>0 then
  102. begin
  103. p^.registers32:=1;
  104. { further, the variable can't be put into a register }
  105. {$ifdef INCLUDEOK}
  106. exclude(pvarsym(p^.symtableentry)^.varoptions,vo_regable);
  107. {$else}
  108. pvarsym(p^.symtableentry)^.varoptions:=pvarsym(p^.symtableentry)^.varoptions-[vo_regable];
  109. {$endif}
  110. end;
  111. end;
  112. if (pvarsym(p^.symtableentry)^.varspez=vs_const) then
  113. p^.location.loc:=LOC_MEM;
  114. { we need a register for call by reference parameters }
  115. if (pvarsym(p^.symtableentry)^.varspez=vs_var) or
  116. ((pvarsym(p^.symtableentry)^.varspez=vs_const) and
  117. push_addr_param(pvarsym(p^.symtableentry)^.definition)) or
  118. { call by value open arrays are also indirect addressed }
  119. is_open_array(pvarsym(p^.symtableentry)^.definition) then
  120. p^.registers32:=1;
  121. if p^.symtable^.symtabletype=withsymtable then
  122. inc(p^.registers32);
  123. if ([vo_is_thread_var,vo_is_dll_var]*pvarsym(p^.symtableentry)^.varoptions)<>[] then
  124. p^.registers32:=1;
  125. { a class variable is a pointer !!!
  126. yes, but we have to resolve the reference in an
  127. appropriate tree node (FK)
  128. if (pvarsym(p^.symtableentry)^.definition^.deftype=objectdef) and
  129. ((pobjectdef(pvarsym(p^.symtableentry)^.definition)^.options and oo_is_class)<>0) then
  130. p^.registers32:=1;
  131. }
  132. { count variable references }
  133. if must_be_valid and p^.is_first then
  134. begin
  135. if (pvarsym(p^.symtableentry)^.varstate=vs_declared_and_first_found) or
  136. (pvarsym(p^.symtableentry)^.varstate=vs_set_but_first_not_passed) then
  137. if (assigned(pvarsym(p^.symtableentry)^.owner) and
  138. assigned(aktprocsym) and
  139. (pvarsym(p^.symtableentry)^.owner = aktprocsym^.definition^.localst)) then
  140. begin
  141. if p^.symtable^.symtabletype=localsymtable then
  142. CGMessage1(sym_n_uninitialized_local_variable,pvarsym(p^.symtableentry)^.name)
  143. else
  144. CGMessage1(sym_n_uninitialized_variable,pvarsym(p^.symtableentry)^.name);
  145. end;
  146. end;
  147. if count_ref then
  148. begin
  149. if (p^.is_first) then
  150. begin
  151. if pvarsym(p^.symtableentry)^.varstate=vs_declared_and_first_found then
  152. { this can only happen at left of an assignment, no ? PM }
  153. if (parsing_para_level=0) and not must_be_valid then
  154. pvarsym(p^.symtableentry)^.varstate:=vs_assigned
  155. else
  156. pvarsym(p^.symtableentry)^.varstate:=vs_used;
  157. if pvarsym(p^.symtableentry)^.varstate=vs_set_but_first_not_passed then
  158. pvarsym(p^.symtableentry)^.varstate:=vs_used;
  159. p^.is_first:=false;
  160. end
  161. else
  162. begin
  163. if (pvarsym(p^.symtableentry)^.varstate=vs_assigned) and
  164. (must_be_valid or (parsing_para_level>0) or
  165. (p^.resulttype^.deftype=procvardef)) then
  166. pvarsym(p^.symtableentry)^.varstate:=vs_used;
  167. if (pvarsym(p^.symtableentry)^.varstate=vs_declared_and_first_found) and
  168. (must_be_valid or (parsing_para_level>0) or
  169. (p^.resulttype^.deftype=procvardef)) then
  170. pvarsym(p^.symtableentry)^.varstate:=vs_set_but_first_not_passed;
  171. end;
  172. end;
  173. { this will create problem with local var set by
  174. under_procedures
  175. if (assigned(pvarsym(p^.symtableentry)^.owner) and assigned(aktprocsym)
  176. and ((pvarsym(p^.symtableentry)^.owner = aktprocsym^.definition^.localst)
  177. or (pvarsym(p^.symtableentry)^.owner = aktprocsym^.definition^.localst))) then }
  178. if t_times<1 then
  179. inc(pvarsym(p^.symtableentry)^.refs)
  180. else
  181. inc(pvarsym(p^.symtableentry)^.refs,t_times);
  182. end;
  183. typedconstsym :
  184. if not p^.is_absolute then
  185. p^.resulttype:=ptypedconstsym(p^.symtableentry)^.definition;
  186. procsym :
  187. begin
  188. if assigned(pprocsym(p^.symtableentry)^.definition^.nextoverloaded) then
  189. CGMessage(parser_e_no_overloaded_procvars);
  190. p^.resulttype:=pprocsym(p^.symtableentry)^.definition;
  191. { if the owner of the procsym is a object, }
  192. { left must be set, if left isn't set }
  193. { it can be only self }
  194. { this code is only used in TP procvar mode }
  195. if (m_tp_procvar in aktmodeswitches) and
  196. not(assigned(p^.left)) and
  197. (pprocsym(p^.symtableentry)^.owner^.symtabletype=objectsymtable) then
  198. p^.left:=genselfnode(procinfo^._class);
  199. { method pointer ? }
  200. if assigned(p^.left) then
  201. begin
  202. firstpass(p^.left);
  203. p^.registers32:=max(p^.registers32,p^.left^.registers32);
  204. p^.registersfpu:=max(p^.registersfpu,p^.left^.registersfpu);
  205. {$ifdef SUPPORT_MMX}
  206. p^.registersmmx:=max(p^.registersmmx,p^.left^.registersmmx);
  207. {$endif SUPPORT_MMX}
  208. end;
  209. end;
  210. else internalerror(3);
  211. end;
  212. end;
  213. {*****************************************************************************
  214. FirstAssignment
  215. *****************************************************************************}
  216. procedure firstassignment(var p : ptree);
  217. var
  218. store_valid : boolean;
  219. hp : ptree;
  220. begin
  221. store_valid:=must_be_valid;
  222. must_be_valid:=false;
  223. { must be made unique }
  224. set_unique(p^.left);
  225. { set we the function result? }
  226. set_funcret_is_valid(p^.left);
  227. firstpass(p^.left);
  228. if codegenerror then
  229. exit;
  230. { assignements to open arrays aren't allowed }
  231. if is_open_array(p^.left^.resulttype) then
  232. CGMessage(type_e_mismatch);
  233. { test if we can avoid copying string to temp
  234. as in s:=s+...; (PM) }
  235. {$ifdef dummyi386}
  236. if ((p^.right^.treetype=addn) or (p^.right^.treetype=subn)) and
  237. equal_trees(p^.left,p^.right^.left) and
  238. (ret_in_acc(p^.left^.resulttype)) and
  239. (not cs_rangechecking in aktmoduleswitches^) then
  240. begin
  241. disposetree(p^.right^.left);
  242. hp:=p^.right;
  243. p^.right:=p^.right^.right;
  244. if hp^.treetype=addn then
  245. p^.assigntyp:=at_plus
  246. else
  247. p^.assigntyp:=at_minus;
  248. putnode(hp);
  249. end;
  250. if p^.assigntyp<>at_normal then
  251. begin
  252. { for fpu type there is no faster way }
  253. if is_fpu(p^.left^.resulttype) then
  254. case p^.assigntyp of
  255. at_plus : p^.right:=gennode(addn,getcopy(p^.left),p^.right);
  256. at_minus : p^.right:=gennode(subn,getcopy(p^.left),p^.right);
  257. at_star : p^.right:=gennode(muln,getcopy(p^.left),p^.right);
  258. at_slash : p^.right:=gennode(slashn,getcopy(p^.left),p^.right);
  259. end;
  260. end;
  261. {$endif i386}
  262. must_be_valid:=true;
  263. firstpass(p^.right);
  264. must_be_valid:=store_valid;
  265. if codegenerror then
  266. exit;
  267. { some string functions don't need conversion, so treat them separatly }
  268. if is_shortstring(p^.left^.resulttype) and (assigned(p^.right^.resulttype)) then
  269. begin
  270. if not (is_shortstring(p^.right^.resulttype) or
  271. is_ansistring(p^.right^.resulttype) or
  272. is_char(p^.right^.resulttype)) then
  273. begin
  274. p^.right:=gentypeconvnode(p^.right,p^.left^.resulttype);
  275. firstpass(p^.right);
  276. if codegenerror then
  277. exit;
  278. end;
  279. { we call STRCOPY }
  280. procinfo^.flags:=procinfo^.flags or pi_do_call;
  281. hp:=p^.right;
  282. { test for s:=s+anything ... }
  283. { the problem is for
  284. s:=s+s+s;
  285. this is broken here !! }
  286. { while hp^.treetype=addn do hp:=hp^.left;
  287. if equal_trees(p^.left,hp) then
  288. begin
  289. p^.concat_string:=true;
  290. hp:=p^.right;
  291. while hp^.treetype=addn do
  292. begin
  293. hp^.use_strconcat:=true;
  294. hp:=hp^.left;
  295. end;
  296. end; }
  297. end
  298. else
  299. begin
  300. p^.right:=gentypeconvnode(p^.right,p^.left^.resulttype);
  301. firstpass(p^.right);
  302. if codegenerror then
  303. exit;
  304. end;
  305. { test if node can be assigned, properties are allowed }
  306. valid_for_assign(p^.left,true);
  307. { check if local proc/func is assigned to procvar }
  308. if p^.right^.resulttype^.deftype=procvardef then
  309. test_local_to_procvar(pprocvardef(p^.right^.resulttype),p^.left^.resulttype);
  310. p^.resulttype:=voiddef;
  311. {
  312. p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
  313. p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
  314. }
  315. p^.registers32:=p^.left^.registers32+p^.right^.registers32;
  316. p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
  317. {$ifdef SUPPORT_MMX}
  318. p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
  319. {$endif SUPPORT_MMX}
  320. end;
  321. {*****************************************************************************
  322. FirstFuncRet
  323. *****************************************************************************}
  324. procedure firstfuncret(var p : ptree);
  325. begin
  326. p^.resulttype:=p^.retdef;
  327. p^.location.loc:=LOC_REFERENCE;
  328. if ret_in_param(p^.retdef) or
  329. (procinfo<>pprocinfo(p^.funcretprocinfo)) then
  330. p^.registers32:=1;
  331. { no claim if setting higher return value_str }
  332. if must_be_valid and
  333. (procinfo=pprocinfo(p^.funcretprocinfo)) and
  334. ((procinfo^.funcret_state=vs_declared) or
  335. (p^.is_first_funcret)) then
  336. begin
  337. CGMessage(sym_w_function_result_not_set);
  338. { avoid multiple warnings }
  339. procinfo^.funcret_state:=vs_assigned;
  340. end;
  341. end;
  342. {*****************************************************************************
  343. FirstArrayConstructRange
  344. *****************************************************************************}
  345. procedure firstarrayconstructrange(var p:ptree);
  346. begin
  347. firstpass(p^.left);
  348. firstpass(p^.right);
  349. calcregisters(p,0,0,0);
  350. p^.resulttype:=p^.left^.resulttype;
  351. end;
  352. {*****************************************************************************
  353. FirstArrayConstruct
  354. *****************************************************************************}
  355. procedure firstarrayconstruct(var p : ptree);
  356. var
  357. pd : pdef;
  358. thp,
  359. chp,
  360. hp : ptree;
  361. len : longint;
  362. varia : boolean;
  363. begin
  364. { are we allowing array constructor? Then convert it to a set }
  365. if not allow_array_constructor then
  366. begin
  367. arrayconstructor_to_set(p);
  368. firstpass(p);
  369. exit;
  370. end;
  371. { only pass left tree, right tree contains next construct if any }
  372. pd:=p^.constructdef;
  373. len:=0;
  374. varia:=false;
  375. if assigned(p^.left) then
  376. begin
  377. hp:=p;
  378. while assigned(hp) do
  379. begin
  380. firstpass(hp^.left);
  381. if (not get_para_resulttype) and (not p^.novariaallowed) then
  382. begin
  383. case hp^.left^.resulttype^.deftype of
  384. enumdef :
  385. begin
  386. hp^.left:=gentypeconvnode(hp^.left,s32bitdef);
  387. firstpass(hp^.left);
  388. end;
  389. orddef :
  390. begin
  391. if is_integer(hp^.left^.resulttype) then
  392. begin
  393. hp^.left:=gentypeconvnode(hp^.left,s32bitdef);
  394. firstpass(hp^.left);
  395. end;
  396. end;
  397. floatdef :
  398. begin
  399. hp^.left:=gentypeconvnode(hp^.left,bestrealdef^);
  400. firstpass(hp^.left);
  401. end;
  402. stringdef :
  403. begin
  404. if p^.cargs then
  405. begin
  406. hp^.left:=gentypeconvnode(hp^.left,charpointerdef);
  407. firstpass(hp^.left);
  408. end;
  409. end;
  410. pointerdef,
  411. classrefdef,
  412. objectdef : ;
  413. else
  414. CGMessagePos1(hp^.left^.fileinfo,type_e_wrong_type_in_array_constructor,hp^.left^.resulttype^.typename);
  415. end;
  416. end;
  417. if (pd=nil) then
  418. pd:=hp^.left^.resulttype
  419. else
  420. begin
  421. if ((p^.novariaallowed) or (not varia)) and
  422. (not is_equal(pd,hp^.left^.resulttype)) then
  423. begin
  424. { if both should be equal try inserting a conversion }
  425. if p^.novariaallowed then
  426. begin
  427. hp^.left:=gentypeconvnode(hp^.left,pd);
  428. firstpass(hp^.left);
  429. end;
  430. varia:=true;
  431. end;
  432. end;
  433. inc(len);
  434. hp:=hp^.right;
  435. end;
  436. { swap the tree for cargs }
  437. if p^.cargs and (not p^.cargswap) then
  438. begin
  439. chp:=nil;
  440. hp:=p;
  441. while assigned(hp) do
  442. begin
  443. thp:=hp^.right;
  444. hp^.right:=chp;
  445. chp:=hp;
  446. hp:=thp;
  447. end;
  448. p:=chp;
  449. p^.cargs:=true;
  450. p^.cargswap:=true;
  451. end;
  452. end;
  453. calcregisters(p,0,0,0);
  454. { looks a little bit dangerous to me }
  455. { len-1 gives problems with is_open_array if len=0, }
  456. { is_open_array checks now for isconstructor (FK) }
  457. { skip if already done ! (PM) }
  458. if not assigned(p^.resulttype) or
  459. (p^.resulttype^.deftype<>arraydef) or
  460. not parraydef(p^.resulttype)^.IsConstructor or
  461. (parraydef(p^.resulttype)^.lowrange<>0) or
  462. (parraydef(p^.resulttype)^.highrange<>len-1) then
  463. p^.resulttype:=new(parraydef,init(0,len-1,s32bitdef));
  464. parraydef(p^.resulttype)^.definition:=pd;
  465. parraydef(p^.resulttype)^.IsConstructor:=true;
  466. parraydef(p^.resulttype)^.IsVariant:=varia;
  467. p^.location.loc:=LOC_MEM;
  468. end;
  469. {*****************************************************************************
  470. Type
  471. *****************************************************************************}
  472. procedure firsttype(var p : ptree);
  473. begin
  474. { do nothing, p^.resulttype is already set }
  475. end;
  476. end.
  477. {
  478. $Log$
  479. Revision 1.50 1999-11-17 17:05:07 pierre
  480. * Notes/hints changes
  481. Revision 1.49 1999/11/06 14:34:30 peter
  482. * truncated log to 20 revs
  483. Revision 1.48 1999/10/26 12:30:46 peter
  484. * const parameter is now checked
  485. * better and generic check if a node can be used for assigning
  486. * export fixes
  487. * procvar equal works now (it never had worked at least from 0.99.8)
  488. * defcoll changed to linkedlist with pparaitem so it can easily be
  489. walked both directions
  490. Revision 1.47 1999/10/13 10:35:27 peter
  491. * var must match exactly error msg extended with got and expected type
  492. * array constructor type check now gives error on wrong types
  493. Revision 1.46 1999/09/27 23:45:01 peter
  494. * procinfo is now a pointer
  495. * support for result setting in sub procedure
  496. Revision 1.45 1999/09/17 17:14:12 peter
  497. * @procvar fixes for tp mode
  498. * @<id>:= gives now an error
  499. Revision 1.44 1999/09/11 19:47:26 florian
  500. * bug fix for @tobject.method, fixes bug 557, 605 and 606
  501. Revision 1.43 1999/09/11 09:08:34 florian
  502. * fixed bug 596
  503. * fixed some problems with procedure variables and procedures of object,
  504. especially in TP mode. Procedure of object doesn't apply only to classes,
  505. it is also allowed for objects !!
  506. Revision 1.42 1999/09/10 18:48:11 florian
  507. * some bug fixes (e.g. must_be_valid and procinfo^.funcret_is_valid)
  508. * most things for stored properties fixed
  509. Revision 1.41 1999/08/16 23:23:41 peter
  510. * arrayconstructor -> openarray type conversions for element types
  511. Revision 1.40 1999/08/13 21:33:17 peter
  512. * support for array constructors extended and more error checking
  513. Revision 1.39 1999/08/05 16:53:24 peter
  514. * V_Fatal=1, all other V_ are also increased
  515. * Check for local procedure when assigning procvar
  516. * fixed comment parsing because directives
  517. * oldtp mode directives better supported
  518. * added some messages to errore.msg
  519. Revision 1.38 1999/08/04 00:23:41 florian
  520. * renamed i386asm and i386base to cpuasm and cpubase
  521. Revision 1.37 1999/08/03 22:03:33 peter
  522. * moved bitmask constants to sets
  523. * some other type/const renamings
  524. Revision 1.36 1999/07/22 09:38:00 florian
  525. + resourcestring implemented
  526. + start of longstring support
  527. Revision 1.35 1999/06/17 13:19:59 pierre
  528. * merged from 0_99_12 branch
  529. Revision 1.34.2.1 1999/06/17 12:33:39 pierre
  530. * avoid warning with extdebug for arrayconstruct
  531. Revision 1.34 1999/06/01 19:26:39 peter
  532. * fixed bug 249
  533. Revision 1.33 1999/05/27 19:45:21 peter
  534. * removed oldasm
  535. * plabel -> pasmlabel
  536. * -a switches to source writing automaticly
  537. * assembler readers OOPed
  538. * asmsymbol automaticly external
  539. * jumptables and other label fixes for asm readers
  540. Revision 1.32 1999/05/23 18:42:22 florian
  541. * better error recovering in typed constants
  542. * some problems with arrays of const fixed, some problems
  543. due my previous
  544. - the location type of array constructor is now LOC_MEM
  545. - the pushing of high fixed
  546. - parameter copying fixed
  547. - zero temp. allocation removed
  548. * small problem in the assembler writers fixed:
  549. ref to nil wasn't written correctly
  550. Revision 1.31 1999/05/19 15:26:41 florian
  551. * if a non local variables isn't initialized the compiler doesn't write
  552. any longer "local var. seems not to be ..."
  553. Revision 1.30 1999/05/19 10:31:55 florian
  554. * two bugs reported by Romio (bugs 13) are fixed:
  555. - empty array constructors are now handled correctly (e.g. for sysutils.format)
  556. - comparsion of ansistrings was sometimes coded wrong
  557. }