ncon.pas 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. Type checking and register allocation for constants
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ncon;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,widestr,
  22. cclasses,
  23. node,
  24. aasmbase,aasmtai,aasmdata,cpuinfo,globals,
  25. symconst,symtype,symdef,symsym;
  26. type
  27. tdataconstnode = class(tnode)
  28. data : tdynamicarray;
  29. maxalign : word;
  30. constructor create;virtual;
  31. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  32. destructor destroy;override;
  33. procedure ppuwrite(ppufile:tcompilerppufile);override;
  34. function dogetcopy : tnode;override;
  35. function pass_1 : tnode;override;
  36. function pass_typecheck:tnode;override;
  37. function docompare(p: tnode) : boolean; override;
  38. procedure printnodedata(var t:text);override;
  39. procedure append(const d;len : aint);
  40. procedure align(value : word);
  41. end;
  42. tdataconstnodeclass = class of tdataconstnode;
  43. trealconstnode = class(tnode)
  44. typedef : tdef;
  45. typedefderef : tderef;
  46. value_real : bestreal;
  47. lab_real : tasmlabel;
  48. constructor create(v : bestreal;def:tdef);virtual;
  49. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  50. procedure ppuwrite(ppufile:tcompilerppufile);override;
  51. procedure buildderefimpl;override;
  52. procedure derefimpl;override;
  53. function dogetcopy : tnode;override;
  54. function pass_1 : tnode;override;
  55. function pass_typecheck:tnode;override;
  56. function docompare(p: tnode) : boolean; override;
  57. procedure printnodedata(var t:text);override;
  58. end;
  59. trealconstnodeclass = class of trealconstnode;
  60. tordconstnode = class(tnode)
  61. typedef : tdef;
  62. typedefderef : tderef;
  63. value : TConstExprInt;
  64. rangecheck : boolean;
  65. { create an ordinal constant node of the specified type and value.
  66. _rangecheck determines if the value of the ordinal should be checked
  67. against the ranges of the type definition.
  68. }
  69. constructor create(v : tconstexprint;def:tdef; _rangecheck : boolean);virtual;
  70. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  71. procedure ppuwrite(ppufile:tcompilerppufile);override;
  72. procedure buildderefimpl;override;
  73. procedure derefimpl;override;
  74. function dogetcopy : tnode;override;
  75. function pass_1 : tnode;override;
  76. function pass_typecheck:tnode;override;
  77. function docompare(p: tnode) : boolean; override;
  78. procedure printnodedata(var t:text);override;
  79. end;
  80. tordconstnodeclass = class of tordconstnode;
  81. tpointerconstnode = class(tnode)
  82. typedef : tdef;
  83. typedefderef : tderef;
  84. value : TConstPtrUInt;
  85. constructor create(v : TConstPtrUInt;def:tdef);virtual;
  86. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  87. procedure ppuwrite(ppufile:tcompilerppufile);override;
  88. procedure buildderefimpl;override;
  89. procedure derefimpl;override;
  90. function dogetcopy : tnode;override;
  91. function pass_1 : tnode;override;
  92. function pass_typecheck:tnode;override;
  93. function docompare(p: tnode) : boolean; override;
  94. end;
  95. tpointerconstnodeclass = class of tpointerconstnode;
  96. tconststringtype = (
  97. cst_conststring,
  98. cst_shortstring,
  99. cst_longstring,
  100. cst_ansistring,
  101. cst_widestring
  102. );
  103. tstringconstnode = class(tnode)
  104. value_str : pchar;
  105. len : longint;
  106. lab_str : tasmlabel;
  107. cst_type : tconststringtype;
  108. constructor createstr(const s : string);virtual;
  109. constructor createpchar(s : pchar;l : longint);virtual;
  110. constructor createwstr(w : pcompilerwidestring);virtual;
  111. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  112. procedure ppuwrite(ppufile:tcompilerppufile);override;
  113. procedure buildderefimpl;override;
  114. procedure derefimpl;override;
  115. destructor destroy;override;
  116. function dogetcopy : tnode;override;
  117. function pass_1 : tnode;override;
  118. function pass_typecheck:tnode;override;
  119. function getpcharcopy : pchar;
  120. function docompare(p: tnode) : boolean; override;
  121. procedure changestringtype(def:tdef);
  122. end;
  123. tstringconstnodeclass = class of tstringconstnode;
  124. tsetconstnode = class(tunarynode)
  125. typedef : tdef;
  126. typedefderef : tderef;
  127. value_set : pconstset;
  128. lab_set : tasmlabel;
  129. constructor create(s : pconstset;def:tdef);virtual;
  130. destructor destroy;override;
  131. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  132. procedure ppuwrite(ppufile:tcompilerppufile);override;
  133. procedure buildderefimpl;override;
  134. procedure derefimpl;override;
  135. function dogetcopy : tnode;override;
  136. function pass_1 : tnode;override;
  137. function pass_typecheck:tnode;override;
  138. function docompare(p: tnode) : boolean; override;
  139. end;
  140. tsetconstnodeclass = class of tsetconstnode;
  141. tnilnode = class(tnode)
  142. constructor create;virtual;
  143. function pass_1 : tnode;override;
  144. function pass_typecheck:tnode;override;
  145. end;
  146. tnilnodeclass = class of tnilnode;
  147. tguidconstnode = class(tnode)
  148. value : tguid;
  149. constructor create(const g:tguid);virtual;
  150. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  151. procedure ppuwrite(ppufile:tcompilerppufile);override;
  152. function dogetcopy : tnode;override;
  153. function pass_1 : tnode;override;
  154. function pass_typecheck:tnode;override;
  155. function docompare(p: tnode) : boolean; override;
  156. end;
  157. tguidconstnodeclass = class of tguidconstnode;
  158. var
  159. cdataconstnode : tdataconstnodeclass;
  160. crealconstnode : trealconstnodeclass;
  161. cordconstnode : tordconstnodeclass;
  162. cpointerconstnode : tpointerconstnodeclass;
  163. cstringconstnode : tstringconstnodeclass;
  164. csetconstnode : tsetconstnodeclass;
  165. cguidconstnode : tguidconstnodeclass;
  166. cnilnode : tnilnodeclass;
  167. function genintconstnode(v : TConstExprInt) : tordconstnode;
  168. function genenumnode(v : tenumsym) : tordconstnode;
  169. { some helper routines }
  170. function get_ordinal_value(p : tnode) : TConstExprInt;
  171. function is_constresourcestringnode(p : tnode) : boolean;
  172. function is_emptyset(p : tnode):boolean;
  173. function genconstsymtree(p : tconstsym) : tnode;
  174. implementation
  175. uses
  176. cutils,
  177. verbose,systems,
  178. defutil,
  179. cpubase,cgbase,
  180. nld;
  181. function genintconstnode(v : TConstExprInt) : tordconstnode;
  182. var
  183. htype : tdef;
  184. begin
  185. int_to_type(v,htype);
  186. genintconstnode:=cordconstnode.create(v,htype,true);
  187. end;
  188. function genenumnode(v : tenumsym) : tordconstnode;
  189. var
  190. htype : tdef;
  191. begin
  192. htype:=v.definition;
  193. genenumnode:=cordconstnode.create(v.value,htype,true);
  194. end;
  195. function get_ordinal_value(p : tnode) : TConstExprInt;
  196. begin
  197. get_ordinal_value:=0;
  198. if is_constnode(p) then
  199. begin
  200. if p.nodetype=ordconstn then
  201. get_ordinal_value:=tordconstnode(p).value
  202. else
  203. Message(type_e_ordinal_expr_expected);
  204. end
  205. else
  206. Message(type_e_constant_expr_expected);
  207. end;
  208. function is_constresourcestringnode(p : tnode) : boolean;
  209. begin
  210. is_constresourcestringnode:=(p.nodetype=loadn) and
  211. (tloadnode(p).symtableentry.typ=constsym) and
  212. (tconstsym(tloadnode(p).symtableentry).consttyp=constresourcestring);
  213. end;
  214. function is_emptyset(p : tnode):boolean;
  215. begin
  216. is_emptyset:=(p.nodetype=setconstn) and
  217. (Tsetconstnode(p).value_set^=[]);
  218. end;
  219. function genconstsymtree(p : tconstsym) : tnode;
  220. var
  221. p1 : tnode;
  222. len : longint;
  223. pc : pchar;
  224. begin
  225. p1:=nil;
  226. case p.consttyp of
  227. constord :
  228. p1:=cordconstnode.create(p.value.valueord,p.constdef,true);
  229. conststring :
  230. begin
  231. len:=p.value.len;
  232. getmem(pc,len+1);
  233. move(pchar(p.value.valueptr)^,pc^,len);
  234. pc[len]:=#0;
  235. p1:=cstringconstnode.createpchar(pc,len);
  236. end;
  237. constreal :
  238. p1:=crealconstnode.create(pbestreal(p.value.valueptr)^,pbestrealtype^);
  239. constset :
  240. p1:=csetconstnode.create(pconstset(p.value.valueptr),p.constdef);
  241. constpointer :
  242. p1:=cpointerconstnode.create(p.value.valueordptr,p.constdef);
  243. constnil :
  244. p1:=cnilnode.create;
  245. else
  246. internalerror(200205103);
  247. end;
  248. genconstsymtree:=p1;
  249. end;
  250. {*****************************************************************************
  251. TDATACONSTNODE
  252. *****************************************************************************}
  253. constructor tdataconstnode.create;
  254. begin
  255. inherited create(dataconstn);
  256. data:=tdynamicarray.create(128);
  257. end;
  258. constructor tdataconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  259. var
  260. len : aint;
  261. buf : array[0..255] of byte;
  262. begin
  263. inherited ppuload(t,ppufile);
  264. len:=ppufile.getaint;
  265. if len<4096 then
  266. data:=tdynamicarray.create(len)
  267. else
  268. data:=tdynamicarray.create(4096);
  269. while len>0 do
  270. begin
  271. if len>sizeof(buf) then
  272. begin
  273. ppufile.getdata(buf,sizeof(buf));
  274. data.write(buf,sizeof(buf));
  275. dec(len,sizeof(buf));
  276. end
  277. else
  278. begin
  279. ppufile.getdata(buf,len);
  280. data.write(buf,len);
  281. len:=0;
  282. end;
  283. end;
  284. end;
  285. destructor tdataconstnode.destroy;
  286. begin
  287. data.free;
  288. inherited destroy;
  289. end;
  290. procedure tdataconstnode.ppuwrite(ppufile:tcompilerppufile);
  291. var
  292. len : aint;
  293. buf : array[0..255] of byte;
  294. begin
  295. inherited ppuwrite(ppufile);
  296. len:=data.size;
  297. ppufile.putaint(len);
  298. data.seek(0);
  299. while len>0 do
  300. begin
  301. if len>sizeof(buf) then
  302. begin
  303. data.read(buf,sizeof(buf));
  304. ppufile.putdata(buf,sizeof(buf));
  305. dec(len,sizeof(buf));
  306. end
  307. else
  308. begin
  309. data.read(buf,len);
  310. ppufile.putdata(buf,len);
  311. len:=0;
  312. end;
  313. end;
  314. end;
  315. function tdataconstnode.dogetcopy : tnode;
  316. var
  317. n : tdataconstnode;
  318. len : aint;
  319. buf : array[0..255] of byte;
  320. begin
  321. n:=tdataconstnode(inherited dogetcopy);
  322. len:=data.size;
  323. if len<4096 then
  324. n.data:=tdynamicarray.create(len)
  325. else
  326. n.data:=tdynamicarray.create(4096);
  327. data.seek(0);
  328. while len>0 do
  329. begin
  330. if len>sizeof(buf) then
  331. begin
  332. data.read(buf,sizeof(buf));
  333. n.data.write(buf,sizeof(buf));
  334. dec(len,sizeof(buf));
  335. end
  336. else
  337. begin
  338. data.read(buf,len);
  339. n.data.write(buf,len);
  340. len:=0;
  341. end;
  342. end;
  343. dogetcopy := n;
  344. end;
  345. function tdataconstnode.pass_1 : tnode;
  346. begin
  347. result:=nil;
  348. expectloc:=LOC_CREFERENCE;
  349. end;
  350. function tdataconstnode.pass_typecheck:tnode;
  351. begin
  352. result:=nil;
  353. resultdef:=voidpointertype;
  354. end;
  355. function tdataconstnode.docompare(p: tnode) : boolean;
  356. var
  357. b1,b2 : byte;
  358. I : longint;
  359. begin
  360. docompare :=
  361. inherited docompare(p) and (data.size=tdataconstnode(p).data.size);
  362. if docompare then
  363. begin
  364. data.seek(0);
  365. tdataconstnode(p).data.seek(0);
  366. for i:=0 to data.size-1 do
  367. begin
  368. data.read(b1,1);
  369. tdataconstnode(p).data.read(b2,1);
  370. if b1<>b2 then
  371. begin
  372. docompare:=false;
  373. exit;
  374. end;
  375. end;
  376. end;
  377. end;
  378. procedure tdataconstnode.printnodedata(var t:text);
  379. var
  380. i : longint;
  381. b : byte;
  382. begin
  383. inherited printnodedata(t);
  384. write(t,printnodeindention,'data size = ',data.size,' data = ');
  385. data.seek(0);
  386. for i:=0 to data.size-1 do
  387. begin
  388. data.read(b,1);
  389. if i=data.size-1 then
  390. writeln(t,b)
  391. else
  392. write(t,b,',');
  393. end;
  394. end;
  395. procedure tdataconstnode.append(const d;len : aint);
  396. begin
  397. data.seek(data.size);
  398. data.write(d,len);
  399. end;
  400. procedure tdataconstnode.align(value : word);
  401. begin
  402. if value>maxalign then
  403. maxalign:=value;
  404. data.align(value);
  405. end;
  406. {*****************************************************************************
  407. TREALCONSTNODE
  408. *****************************************************************************}
  409. { generic code }
  410. { overridden by: }
  411. { i386 }
  412. constructor trealconstnode.create(v : bestreal;def:tdef);
  413. begin
  414. inherited create(realconstn);
  415. typedef:=def;
  416. value_real:=v;
  417. lab_real:=nil;
  418. end;
  419. constructor trealconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  420. begin
  421. inherited ppuload(t,ppufile);
  422. ppufile.getderef(typedefderef);
  423. value_real:=ppufile.getreal;
  424. lab_real:=tasmlabel(ppufile.getasmsymbol);
  425. end;
  426. procedure trealconstnode.ppuwrite(ppufile:tcompilerppufile);
  427. begin
  428. inherited ppuwrite(ppufile);
  429. ppufile.putderef(typedefderef);
  430. ppufile.putreal(value_real);
  431. ppufile.putasmsymbol(lab_real);
  432. end;
  433. procedure trealconstnode.buildderefimpl;
  434. begin
  435. inherited buildderefimpl;
  436. typedefderef.build(typedef);
  437. end;
  438. procedure trealconstnode.derefimpl;
  439. begin
  440. inherited derefimpl;
  441. typedef:=tdef(typedefderef.resolve);
  442. end;
  443. function trealconstnode.dogetcopy : tnode;
  444. var
  445. n : trealconstnode;
  446. begin
  447. n:=trealconstnode(inherited dogetcopy);
  448. n.value_real:=value_real;
  449. n.lab_real:=lab_real;
  450. dogetcopy:=n;
  451. end;
  452. function trealconstnode.pass_typecheck:tnode;
  453. begin
  454. result:=nil;
  455. resultdef:=typedef;
  456. end;
  457. function trealconstnode.pass_1 : tnode;
  458. begin
  459. result:=nil;
  460. expectloc:=LOC_CREFERENCE;
  461. { needs to be loaded into an FPU register }
  462. registersfpu:=1;
  463. end;
  464. function trealconstnode.docompare(p: tnode): boolean;
  465. begin
  466. docompare :=
  467. inherited docompare(p) and
  468. (value_real = trealconstnode(p).value_real) and
  469. { floating point compares for non-numbers give strange results usually }
  470. is_number_float(value_real) and
  471. is_number_float(trealconstnode(p).value_real);
  472. end;
  473. procedure Trealconstnode.printnodedata(var t:text);
  474. begin
  475. inherited printnodedata(t);
  476. writeln(t,printnodeindention,'value = ',value_real);
  477. end;
  478. {*****************************************************************************
  479. TORDCONSTNODE
  480. *****************************************************************************}
  481. constructor tordconstnode.create(v : tconstexprint;def:tdef;_rangecheck : boolean);
  482. begin
  483. inherited create(ordconstn);
  484. value:=v;
  485. typedef:=def;
  486. rangecheck := _rangecheck;
  487. end;
  488. constructor tordconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  489. begin
  490. inherited ppuload(t,ppufile);
  491. ppufile.getderef(typedefderef);
  492. value:=ppufile.getexprint;
  493. { normally, the value is already compiled, so we don't need
  494. to do once again a range check
  495. }
  496. rangecheck := false;
  497. end;
  498. procedure tordconstnode.ppuwrite(ppufile:tcompilerppufile);
  499. begin
  500. inherited ppuwrite(ppufile);
  501. ppufile.putderef(typedefderef);
  502. ppufile.putexprint(value);
  503. end;
  504. procedure tordconstnode.buildderefimpl;
  505. begin
  506. inherited buildderefimpl;
  507. typedefderef.build(typedef);
  508. end;
  509. procedure tordconstnode.derefimpl;
  510. begin
  511. inherited derefimpl;
  512. typedef:=tdef(typedefderef.resolve);
  513. end;
  514. function tordconstnode.dogetcopy : tnode;
  515. var
  516. n : tordconstnode;
  517. begin
  518. n:=tordconstnode(inherited dogetcopy);
  519. n.value:=value;
  520. n.typedef := typedef;
  521. dogetcopy:=n;
  522. end;
  523. function tordconstnode.pass_typecheck:tnode;
  524. begin
  525. result:=nil;
  526. resultdef:=typedef;
  527. { only do range checking when explicitly asked for it }
  528. if rangecheck then
  529. testrange(resultdef,value,false);
  530. end;
  531. function tordconstnode.pass_1 : tnode;
  532. begin
  533. result:=nil;
  534. expectloc:=LOC_CONSTANT;
  535. end;
  536. function tordconstnode.docompare(p: tnode): boolean;
  537. begin
  538. docompare :=
  539. inherited docompare(p) and
  540. (value = tordconstnode(p).value);
  541. end;
  542. procedure Tordconstnode.printnodedata(var t:text);
  543. begin
  544. inherited printnodedata(t);
  545. writeln(t,printnodeindention,'value = ',value);
  546. end;
  547. {*****************************************************************************
  548. TPOINTERCONSTNODE
  549. *****************************************************************************}
  550. constructor tpointerconstnode.create(v : TConstPtrUInt;def:tdef);
  551. begin
  552. inherited create(pointerconstn);
  553. value:=v;
  554. typedef:=def;
  555. end;
  556. constructor tpointerconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  557. begin
  558. inherited ppuload(t,ppufile);
  559. ppufile.getderef(typedefderef);
  560. value:=ppufile.getptruint;
  561. end;
  562. procedure tpointerconstnode.ppuwrite(ppufile:tcompilerppufile);
  563. begin
  564. inherited ppuwrite(ppufile);
  565. ppufile.putderef(typedefderef);
  566. ppufile.putptruint(value);
  567. end;
  568. procedure tpointerconstnode.buildderefimpl;
  569. begin
  570. inherited buildderefimpl;
  571. typedefderef.build(typedef);
  572. end;
  573. procedure tpointerconstnode.derefimpl;
  574. begin
  575. inherited derefimpl;
  576. typedef:=tdef(typedefderef.resolve);
  577. end;
  578. function tpointerconstnode.dogetcopy : tnode;
  579. var
  580. n : tpointerconstnode;
  581. begin
  582. n:=tpointerconstnode(inherited dogetcopy);
  583. n.value:=value;
  584. n.typedef := typedef;
  585. dogetcopy:=n;
  586. end;
  587. function tpointerconstnode.pass_typecheck:tnode;
  588. begin
  589. result:=nil;
  590. resultdef:=typedef;
  591. end;
  592. function tpointerconstnode.pass_1 : tnode;
  593. begin
  594. result:=nil;
  595. expectloc:=LOC_CONSTANT;
  596. end;
  597. function tpointerconstnode.docompare(p: tnode): boolean;
  598. begin
  599. docompare :=
  600. inherited docompare(p) and
  601. (value = tpointerconstnode(p).value);
  602. end;
  603. {*****************************************************************************
  604. TSTRINGCONSTNODE
  605. *****************************************************************************}
  606. constructor tstringconstnode.createstr(const s : string);
  607. var
  608. l : longint;
  609. begin
  610. inherited create(stringconstn);
  611. l:=length(s);
  612. len:=l;
  613. { stringdup write even past a #0 }
  614. getmem(value_str,l+1);
  615. move(s[1],value_str^,l);
  616. value_str[l]:=#0;
  617. lab_str:=nil;
  618. cst_type:=cst_conststring;
  619. end;
  620. constructor tstringconstnode.createwstr(w : pcompilerwidestring);
  621. begin
  622. inherited create(stringconstn);
  623. len:=getlengthwidestring(w);
  624. initwidestring(pcompilerwidestring(value_str));
  625. copywidestring(w,pcompilerwidestring(value_str));
  626. lab_str:=nil;
  627. cst_type:=cst_widestring;
  628. end;
  629. constructor tstringconstnode.createpchar(s : pchar;l : longint);
  630. begin
  631. inherited create(stringconstn);
  632. len:=l;
  633. value_str:=s;
  634. cst_type:=cst_conststring;
  635. lab_str:=nil;
  636. end;
  637. destructor tstringconstnode.destroy;
  638. begin
  639. if cst_type=cst_widestring then
  640. donewidestring(pcompilerwidestring(value_str))
  641. else
  642. ansistringdispose(value_str,len);
  643. inherited destroy;
  644. end;
  645. constructor tstringconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  646. var
  647. pw : pcompilerwidestring;
  648. begin
  649. inherited ppuload(t,ppufile);
  650. cst_type:=tconststringtype(ppufile.getbyte);
  651. len:=ppufile.getlongint;
  652. if cst_type=cst_widestring then
  653. begin
  654. initwidestring(pw);
  655. setlengthwidestring(pw,len);
  656. ppufile.getdata(pw^.data,pw^.len*sizeof(tcompilerwidechar));
  657. pcompilerwidestring(value_str):=pw
  658. end
  659. else
  660. begin
  661. getmem(value_str,len+1);
  662. ppufile.getdata(value_str^,len);
  663. value_str[len]:=#0;
  664. end;
  665. lab_str:=tasmlabel(ppufile.getasmsymbol);
  666. end;
  667. procedure tstringconstnode.ppuwrite(ppufile:tcompilerppufile);
  668. begin
  669. inherited ppuwrite(ppufile);
  670. ppufile.putbyte(byte(cst_type));
  671. ppufile.putlongint(len);
  672. if cst_type=cst_widestring then
  673. ppufile.putdata(pcompilerwidestring(value_str)^.data,len*sizeof(tcompilerwidechar))
  674. else
  675. ppufile.putdata(value_str^,len);
  676. ppufile.putasmsymbol(lab_str);
  677. end;
  678. procedure tstringconstnode.buildderefimpl;
  679. begin
  680. inherited buildderefimpl;
  681. end;
  682. procedure tstringconstnode.derefimpl;
  683. begin
  684. inherited derefimpl;
  685. end;
  686. function tstringconstnode.dogetcopy : tnode;
  687. var
  688. n : tstringconstnode;
  689. begin
  690. n:=tstringconstnode(inherited dogetcopy);
  691. n.cst_type:=cst_type;
  692. n.len:=len;
  693. n.lab_str:=lab_str;
  694. if cst_type=cst_widestring then
  695. begin
  696. initwidestring(pcompilerwidestring(n.value_str));
  697. copywidestring(pcompilerwidestring(value_str),pcompilerwidestring(n.value_str));
  698. end
  699. else
  700. n.value_str:=getpcharcopy;
  701. dogetcopy:=n;
  702. end;
  703. function tstringconstnode.pass_typecheck:tnode;
  704. var
  705. l : aint;
  706. begin
  707. result:=nil;
  708. case cst_type of
  709. cst_conststring :
  710. begin
  711. { handle and store as array[0..len-1] of char }
  712. if len>0 then
  713. l:=len-1
  714. else
  715. l:=0;
  716. resultdef:=tarraydef.create(0,l,s32inttype);
  717. tarraydef(resultdef).elementdef:=cchartype;
  718. include(tarraydef(resultdef).arrayoptions,ado_IsConstString);
  719. end;
  720. cst_shortstring :
  721. resultdef:=cshortstringtype;
  722. cst_ansistring :
  723. resultdef:=cansistringtype;
  724. cst_widestring :
  725. resultdef:=cwidestringtype;
  726. cst_longstring :
  727. resultdef:=clongstringtype;
  728. end;
  729. end;
  730. function tstringconstnode.pass_1 : tnode;
  731. begin
  732. result:=nil;
  733. if (cst_type in [cst_ansistring,cst_widestring]) and
  734. (len=0) then
  735. expectloc:=LOC_CONSTANT
  736. else
  737. expectloc:=LOC_CREFERENCE;
  738. end;
  739. function tstringconstnode.getpcharcopy : pchar;
  740. var
  741. pc : pchar;
  742. begin
  743. pc:=nil;
  744. getmem(pc,len+1);
  745. if pc=nil then
  746. Message(general_f_no_memory_left);
  747. move(value_str^,pc^,len+1);
  748. getpcharcopy:=pc;
  749. end;
  750. function tstringconstnode.docompare(p: tnode): boolean;
  751. begin
  752. docompare :=
  753. inherited docompare(p) and
  754. (len = tstringconstnode(p).len) and
  755. { Don't compare the pchars, since they may contain null chars }
  756. { Since all equal constant strings are replaced by the same }
  757. { label, the following compare should be enough (JM) }
  758. (lab_str = tstringconstnode(p).lab_str);
  759. end;
  760. procedure tstringconstnode.changestringtype(def:tdef);
  761. const
  762. st2cst : array[tstringtype] of tconststringtype = (
  763. cst_shortstring,cst_longstring,cst_ansistring,cst_widestring
  764. );
  765. var
  766. pw : pcompilerwidestring;
  767. pc : pchar;
  768. begin
  769. if def.typ<>stringdef then
  770. internalerror(200510011);
  771. { convert ascii 2 unicode }
  772. if (tstringdef(def).stringtype=st_widestring) and
  773. (cst_type<>cst_widestring) then
  774. begin
  775. initwidestring(pw);
  776. ascii2unicode(value_str,len,pw);
  777. ansistringdispose(value_str,len);
  778. pcompilerwidestring(value_str):=pw;
  779. end
  780. else
  781. { convert unicode 2 ascii }
  782. if (cst_type=cst_widestring) and
  783. (tstringdef(def).stringtype<>st_widestring) then
  784. begin
  785. pw:=pcompilerwidestring(value_str);
  786. getmem(pc,getlengthwidestring(pw)+1);
  787. unicode2ascii(pw,pc);
  788. donewidestring(pw);
  789. value_str:=pc;
  790. end;
  791. cst_type:=st2cst[tstringdef(def).stringtype];
  792. resultdef:=def;
  793. end;
  794. {*****************************************************************************
  795. TSETCONSTNODE
  796. *****************************************************************************}
  797. constructor tsetconstnode.create(s : pconstset;def:tdef);
  798. begin
  799. inherited create(setconstn,nil);
  800. typedef:=def;
  801. if assigned(s) then
  802. begin
  803. new(value_set);
  804. value_set^:=s^;
  805. end
  806. else
  807. value_set:=nil;
  808. end;
  809. destructor tsetconstnode.destroy;
  810. begin
  811. if assigned(value_set) then
  812. dispose(value_set);
  813. inherited destroy;
  814. end;
  815. constructor tsetconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  816. begin
  817. inherited ppuload(t,ppufile);
  818. ppufile.getderef(typedefderef);
  819. new(value_set);
  820. ppufile.getdata(value_set^,sizeof(tconstset));
  821. end;
  822. procedure tsetconstnode.ppuwrite(ppufile:tcompilerppufile);
  823. begin
  824. inherited ppuwrite(ppufile);
  825. ppufile.putderef(typedefderef);
  826. ppufile.putdata(value_set^,sizeof(tconstset));
  827. end;
  828. procedure tsetconstnode.buildderefimpl;
  829. begin
  830. inherited buildderefimpl;
  831. typedefderef.build(typedef);
  832. end;
  833. procedure tsetconstnode.derefimpl;
  834. begin
  835. inherited derefimpl;
  836. typedef:=tdef(typedefderef.resolve);
  837. end;
  838. function tsetconstnode.dogetcopy : tnode;
  839. var
  840. n : tsetconstnode;
  841. begin
  842. n:=tsetconstnode(inherited dogetcopy);
  843. if assigned(value_set) then
  844. begin
  845. new(n.value_set);
  846. n.value_set^:=value_set^
  847. end
  848. else
  849. n.value_set:=nil;
  850. n.typedef := typedef;
  851. n.lab_set:=lab_set;
  852. dogetcopy:=n;
  853. end;
  854. function tsetconstnode.pass_typecheck:tnode;
  855. begin
  856. result:=nil;
  857. resultdef:=typedef;
  858. end;
  859. function tsetconstnode.pass_1 : tnode;
  860. begin
  861. result:=nil;
  862. if tsetdef(resultdef).settype=smallset then
  863. expectloc:=LOC_CONSTANT
  864. else
  865. expectloc:=LOC_CREFERENCE;
  866. end;
  867. function tsetconstnode.docompare(p: tnode): boolean;
  868. begin
  869. docompare:=(inherited docompare(p)) and
  870. (value_set^=Tsetconstnode(p).value_set^);
  871. end;
  872. {*****************************************************************************
  873. TNILNODE
  874. *****************************************************************************}
  875. constructor tnilnode.create;
  876. begin
  877. inherited create(niln);
  878. end;
  879. function tnilnode.pass_typecheck:tnode;
  880. begin
  881. result:=nil;
  882. resultdef:=voidpointertype;
  883. end;
  884. function tnilnode.pass_1 : tnode;
  885. begin
  886. result:=nil;
  887. expectloc:=LOC_CONSTANT;
  888. end;
  889. {*****************************************************************************
  890. TGUIDCONSTNODE
  891. *****************************************************************************}
  892. constructor tguidconstnode.create(const g:tguid);
  893. begin
  894. inherited create(guidconstn);
  895. value:=g;
  896. end;
  897. constructor tguidconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  898. begin
  899. inherited ppuload(t,ppufile);
  900. ppufile.getguid(value);
  901. end;
  902. procedure tguidconstnode.ppuwrite(ppufile:tcompilerppufile);
  903. begin
  904. inherited ppuwrite(ppufile);
  905. ppufile.putguid(value);
  906. end;
  907. function tguidconstnode.dogetcopy : tnode;
  908. var
  909. n : tguidconstnode;
  910. begin
  911. n:=tguidconstnode(inherited dogetcopy);
  912. n.value:=value;
  913. dogetcopy:=n;
  914. end;
  915. function tguidconstnode.pass_typecheck:tnode;
  916. begin
  917. result:=nil;
  918. resultdef:=rec_tguid;
  919. end;
  920. function tguidconstnode.pass_1 : tnode;
  921. begin
  922. result:=nil;
  923. expectloc:=LOC_CREFERENCE;
  924. end;
  925. function tguidconstnode.docompare(p: tnode): boolean;
  926. begin
  927. docompare :=
  928. inherited docompare(p) and
  929. (guid2string(value) = guid2string(tguidconstnode(p).value));
  930. end;
  931. begin
  932. crealconstnode:=trealconstnode;
  933. cordconstnode:=tordconstnode;
  934. cpointerconstnode:=tpointerconstnode;
  935. cstringconstnode:=tstringconstnode;
  936. csetconstnode:=tsetconstnode;
  937. cnilnode:=tnilnode;
  938. cguidconstnode:=tguidconstnode;
  939. end.