ncgcon.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate assembler for constant nodes which are the same for
  4. all (most) processors
  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 ncgcon;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. aasmbase,
  23. node,ncon;
  24. type
  25. tcgdataconstnode = class(tdataconstnode)
  26. procedure pass_generate_code;override;
  27. end;
  28. tcgrealconstnode = class(trealconstnode)
  29. procedure pass_generate_code;override;
  30. end;
  31. tcgordconstnode = class(tordconstnode)
  32. procedure pass_generate_code;override;
  33. end;
  34. tcgpointerconstnode = class(tpointerconstnode)
  35. procedure pass_generate_code;override;
  36. end;
  37. tcgstringconstnode = class(tstringconstnode)
  38. procedure pass_generate_code;override;
  39. end;
  40. tcgsetconstnode = class(tsetconstnode)
  41. protected
  42. function emitvarsetconst: tasmsymbol; virtual;
  43. procedure handlevarsetconst;
  44. public
  45. procedure pass_generate_code;override;
  46. end;
  47. tcgnilnode = class(tnilnode)
  48. procedure pass_generate_code;override;
  49. end;
  50. tcgguidconstnode = class(tguidconstnode)
  51. procedure pass_generate_code;override;
  52. end;
  53. implementation
  54. uses
  55. globtype,widestr,systems,
  56. verbose,globals,cutils,
  57. aasmcnst,
  58. symconst,symdef,aasmtai,aasmdata,aasmcpu,defutil,
  59. cpuinfo,cpubase,
  60. cgbase,cgobj,cgutils,
  61. ncgutil,hlcgobj,symtype,cclasses,asmutils,tgobj
  62. ;
  63. {*****************************************************************************
  64. TCGDATACONSTNODE
  65. *****************************************************************************}
  66. procedure tcgdataconstnode.pass_generate_code;
  67. var
  68. l : tasmlabel;
  69. i : longint;
  70. b : byte;
  71. begin
  72. location_reset_ref(location,LOC_CREFERENCE,OS_NO,const_align(maxalign));
  73. current_asmdata.getdatalabel(l);
  74. maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
  75. new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,l.name,const_align(maxalign));
  76. current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l));
  77. data.seek(0);
  78. for i:=0 to data.size-1 do
  79. begin
  80. data.read(b,1);
  81. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(b));
  82. end;
  83. location.reference.symbol:=l;
  84. end;
  85. {*****************************************************************************
  86. TCGREALCONSTNODE
  87. *****************************************************************************}
  88. procedure tcgrealconstnode.pass_generate_code;
  89. { I suppose the parser/pass_1 must make sure the generated real }
  90. { constants are actually supported by the target processor? (JM) }
  91. const
  92. floattype2ait:array[tfloattype] of tairealconsttype=
  93. (aitrealconst_s32bit,aitrealconst_s64bit,aitrealconst_s80bit,aitrealconst_s80bit,aitrealconst_s64comp,aitrealconst_s64comp,aitrealconst_s128bit);
  94. { Since the value is stored always as bestreal, we share a single pool
  95. between all float types. This requires type and hiloswapped flag to
  96. be matched along with the value }
  97. type
  98. tfloatkey = record
  99. value: bestreal;
  100. typ: tfloattype;
  101. swapped: boolean;
  102. end;
  103. var
  104. lastlabel : tasmlabel;
  105. realait : tairealconsttype;
  106. entry : PHashSetItem;
  107. key: tfloatkey;
  108. {$ifdef ARM}
  109. hiloswapped : boolean;
  110. {$endif ARM}
  111. begin
  112. location_reset_ref(location,LOC_CREFERENCE,def_cgsize(resultdef),const_align(resultdef.alignment));
  113. lastlabel:=nil;
  114. realait:=floattype2ait[tfloatdef(resultdef).floattype];
  115. {$ifdef ARM}
  116. hiloswapped:=is_double_hilo_swapped;
  117. {$endif ARM}
  118. { const already used ? }
  119. if not assigned(lab_real) then
  120. begin
  121. { there may be gap between record fields, zero it out }
  122. fillchar(key,sizeof(key),0);
  123. key.value:=value_real;
  124. key.typ:=tfloatdef(resultdef).floattype;
  125. {$ifdef ARM}
  126. key.swapped:=hiloswapped;
  127. {$endif ARM}
  128. entry := current_asmdata.ConstPools[sp_floats].FindOrAdd(@key, sizeof(key));
  129. lab_real := TAsmLabel(entry^.Data); // is it needed anymore?
  130. { :-(, we must generate a new entry }
  131. if not(assigned(lab_real)) then
  132. begin
  133. current_asmdata.getdatalabel(lastlabel);
  134. entry^.Data:=lastlabel;
  135. lab_real:=lastlabel;
  136. maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
  137. new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(resultdef.alignment));
  138. current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
  139. case realait of
  140. aitrealconst_s32bit :
  141. begin
  142. current_asmdata.asmlists[al_typedconsts].concat(tai_realconst.create_s32real(ts32real(value_real)));
  143. { range checking? }
  144. if floating_point_range_check_error and
  145. (tai_realconst(current_asmdata.asmlists[al_typedconsts].last).value.s32val=MathInf.Value) then
  146. Message(parser_e_range_check_error);
  147. end;
  148. aitrealconst_s64bit :
  149. begin
  150. {$ifdef ARM}
  151. if hiloswapped then
  152. current_asmdata.asmlists[al_typedconsts].concat(tai_realconst.create_s64real_hiloswapped(ts64real(value_real)))
  153. else
  154. {$endif ARM}
  155. current_asmdata.asmlists[al_typedconsts].concat(tai_realconst.create_s64real(ts64real(value_real)));
  156. { range checking? }
  157. if floating_point_range_check_error and
  158. (tai_realconst(current_asmdata.asmlists[al_typedconsts].last).value.s64val=MathInf.Value) then
  159. Message(parser_e_range_check_error);
  160. end;
  161. aitrealconst_s80bit :
  162. begin
  163. current_asmdata.asmlists[al_typedconsts].concat(tai_realconst.create_s80real(value_real,tfloatdef(resultdef).size));
  164. { range checking? }
  165. if floating_point_range_check_error and
  166. (tai_realconst(current_asmdata.asmlists[al_typedconsts].last).value.s80val=MathInf.Value) then
  167. Message(parser_e_range_check_error);
  168. end;
  169. {$ifdef cpufloat128}
  170. aitrealconst_s128bit :
  171. begin
  172. current_asmdata.asmlists[al_typedconsts].concat(tai_realconst.create_s128real(value_real));
  173. { range checking? }
  174. if floating_point_range_check_error and
  175. (tai_realconst(current_asmdata.asmlists[al_typedconsts].last).value.s128val=MathInf.Value) then
  176. Message(parser_e_range_check_error);
  177. end;
  178. {$endif cpufloat128}
  179. { the round is necessary for native compilers where comp isn't a float }
  180. aitrealconst_s64comp :
  181. if (value_real>9223372036854775807.0) or (value_real<-9223372036854775808.0) then
  182. message(parser_e_range_check_error)
  183. else
  184. current_asmdata.asmlists[al_typedconsts].concat(tai_realconst.create_s64compreal(round(value_real)));
  185. else
  186. internalerror(10120);
  187. end;
  188. end;
  189. end;
  190. location.reference.symbol:=lab_real;
  191. end;
  192. {*****************************************************************************
  193. TCGORDCONSTNODE
  194. *****************************************************************************}
  195. procedure tcgordconstnode.pass_generate_code;
  196. begin
  197. location_reset(location,LOC_CONSTANT,def_cgsize(resultdef));
  198. {$ifdef cpu64bitalu}
  199. location.value:=value.svalue;
  200. {$else cpu64bitalu}
  201. location.value64:=value.svalue;
  202. {$endif cpu64bitalu}
  203. end;
  204. {*****************************************************************************
  205. TCGPOINTERCONSTNODE
  206. *****************************************************************************}
  207. procedure tcgpointerconstnode.pass_generate_code;
  208. begin
  209. { an integer const. behaves as a memory reference }
  210. location_reset(location,LOC_CONSTANT,OS_ADDR);
  211. location.value:=aint(value);
  212. end;
  213. {*****************************************************************************
  214. TCGSTRINGCONSTNODE
  215. *****************************************************************************}
  216. procedure tcgstringconstnode.pass_generate_code;
  217. var
  218. lastlabel: tasmlabofs;
  219. pc: pchar;
  220. l: longint;
  221. href: treference;
  222. pool: THashSet;
  223. entry: PHashSetItem;
  224. winlikewidestring: boolean;
  225. elementdef: tdef;
  226. strpointerdef: tdef;
  227. datatcb: ttai_lowleveltypedconstbuilder;
  228. datadef: tdef;
  229. const
  230. PoolMap: array[tconststringtype] of TConstPoolType = (
  231. sp_conststr,
  232. sp_shortstr,
  233. sp_longstr,
  234. sp_ansistr,
  235. sp_widestr,
  236. sp_unicodestr
  237. );
  238. begin
  239. case cst_type of
  240. cst_shortstring,
  241. cst_conststring,
  242. cst_ansistring:
  243. begin
  244. elementdef:=cansichartype;
  245. strpointerdef:=charpointertype;
  246. end;
  247. cst_widestring,
  248. cst_unicodestring:
  249. begin
  250. elementdef:=cwidechartype;
  251. strpointerdef:=widecharpointertype;
  252. end;
  253. else
  254. internalerror(2014032803);
  255. end;
  256. { for empty ansistrings we could return a constant 0 }
  257. if (cst_type in [cst_ansistring,cst_widestring,cst_unicodestring]) and (len=0) then
  258. begin
  259. location_reset(location,LOC_CONSTANT,def_cgsize(strpointerdef));
  260. location.value:=0;
  261. exit;
  262. end;
  263. winlikewidestring:=(cst_type=cst_widestring) and (tf_winlikewidestring in target_info.flags);
  264. { const already used ? }
  265. if not assigned(lab_str) then
  266. begin
  267. pool := current_asmdata.ConstPools[PoolMap[cst_type]];
  268. if cst_type in [cst_widestring, cst_unicodestring] then
  269. entry := pool.FindOrAdd(pcompilerwidestring(value_str)^.data,len*cwidechartype.size)
  270. else
  271. if cst_type = cst_ansistring then
  272. entry := PHashSetItem(TTagHashSet(pool).FindOrAdd(value_str,len,tstringdef(resultdef).encoding))
  273. else
  274. entry := pool.FindOrAdd(value_str,len);
  275. lab_str := TAsmLabel(entry^.Data); // is it needed anymore?
  276. { :-(, we must generate a new entry }
  277. if not assigned(entry^.Data) then
  278. begin
  279. case cst_type of
  280. cst_ansistring:
  281. begin
  282. if len=0 then
  283. InternalError(2008032301) { empty string should be handled above }
  284. else
  285. begin
  286. lastlabel:=emit_ansistring_const(current_asmdata.AsmLists[al_typedconsts],value_str,len,tstringdef(resultdef).encoding);
  287. { because we hardcode the offset below due to it
  288. not being stored in the hashset, check here }
  289. if lastlabel.ofs<>ctai_typedconstbuilder.get_string_symofs(st_ansistring,false) then
  290. internalerror(2012051703);
  291. end;
  292. end;
  293. cst_unicodestring,
  294. cst_widestring:
  295. begin
  296. if len=0 then
  297. InternalError(2008032302) { empty string should be handled above }
  298. else
  299. begin
  300. lastlabel := emit_unicodestring_const(current_asmdata.AsmLists[al_typedconsts],
  301. value_str,
  302. tstringdef(resultdef).encoding,
  303. winlikewidestring);
  304. { because we hardcode the offset below due to it
  305. not being stored in the hashset, check here }
  306. if lastlabel.ofs<>ctai_typedconstbuilder.get_string_symofs(tstringdef(resultdef).stringtype,winlikewidestring) then
  307. internalerror(2012051704);
  308. end;
  309. end;
  310. cst_shortstring:
  311. begin
  312. current_asmdata.getdatalabel(lastlabel.lab);
  313. datatcb:=ctai_typedconstbuilder.create;
  314. { truncate strings larger than 255 chars }
  315. if len>255 then
  316. l:=255
  317. else
  318. l:=len;
  319. { include length and terminating zero for quick conversion to pchar }
  320. getmem(pc,l+2);
  321. move(value_str^,pc[1],l);
  322. pc[0]:=chr(l);
  323. pc[l+1]:=#0;
  324. datadef:=getarraydef(cansichartype,l+1);
  325. datatcb.maybe_begin_aggregate(datadef);
  326. datatcb.emit_tai(Tai_string.Create_pchar(pc,l+1),datadef);
  327. datatcb.maybe_end_aggregate(datadef);
  328. current_asmdata.asmlists[al_typedconsts].concatList(
  329. datatcb.get_final_asmlist(lastlabel.lab,datadef,sec_rodata_norel,lastlabel.lab.name,const_align(sizeof(pint)),true)
  330. );
  331. datatcb.free;
  332. end;
  333. cst_conststring:
  334. begin
  335. current_asmdata.getdatalabel(lastlabel.lab);
  336. datatcb:=ctai_typedconstbuilder.create;
  337. { include terminating zero }
  338. getmem(pc,len+1);
  339. move(value_str^,pc[0],len);
  340. pc[len]:=#0;
  341. { the data includes the terminating #0 because this
  342. string can be used for pchar assignments (but it's
  343. also used for array-of-char assignments, in which
  344. case the terminating #0 is not part of the data) }
  345. datadef:=getarraydef(cansichartype,len+1);
  346. datatcb.maybe_begin_aggregate(datadef);
  347. datatcb.emit_tai(Tai_string.Create_pchar(pc,len+1),datadef);
  348. datatcb.maybe_end_aggregate(datadef);
  349. current_asmdata.asmlists[al_typedconsts].concatList(
  350. datatcb.get_final_asmlist(lastlabel.lab,datadef,sec_rodata_norel,lastlabel.lab.name,const_align(sizeof(pint)),true)
  351. );
  352. datatcb.free;
  353. end;
  354. else
  355. internalerror(2013120103);
  356. end;
  357. lab_str:=lastlabel.lab;
  358. entry^.Data:=lastlabel.lab;
  359. end;
  360. end;
  361. if cst_type in [cst_ansistring, cst_widestring, cst_unicodestring] then
  362. begin
  363. location_reset(location, LOC_REGISTER, def_cgsize(strpointerdef));
  364. reference_reset_symbol(href, lab_str,
  365. ctai_typedconstbuilder.get_string_symofs(tstringdef(resultdef).stringtype,winlikewidestring),
  366. const_align(strpointerdef.size));
  367. location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,strpointerdef);
  368. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,elementdef,strpointerdef,href,location.register)
  369. end
  370. else
  371. begin
  372. location_reset_ref(location, LOC_CREFERENCE, def_cgsize(resultdef), const_align(strpointerdef.size));
  373. location.reference.symbol:=lab_str;
  374. end;
  375. end;
  376. {*****************************************************************************
  377. TCGSETCONSTNODE
  378. *****************************************************************************}
  379. function tcgsetconstnode.emitvarsetconst: tasmsymbol;
  380. type
  381. setbytes=array[0..31] of byte;
  382. Psetbytes=^setbytes;
  383. var
  384. lab: tasmlabel;
  385. i: longint;
  386. begin
  387. current_asmdata.getdatalabel(lab);
  388. result:=lab;
  389. lab_set:=lab;
  390. maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
  391. new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,result.name,const_align(8));
  392. current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lab));
  393. if (source_info.endian=target_info.endian) then
  394. for i:=0 to 31 do
  395. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(Psetbytes(value_set)^[i]))
  396. else
  397. for i:=0 to 31 do
  398. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(reverse_byte(Psetbytes(value_set)^[i])));
  399. end;
  400. procedure tcgsetconstnode.handlevarsetconst;
  401. var
  402. entry : PHashSetItem;
  403. begin
  404. location_reset_ref(location,LOC_CREFERENCE,OS_NO,const_align(8));
  405. { const already used ? }
  406. if not assigned(lab_set) then
  407. begin
  408. entry := current_asmdata.ConstPools[sp_varsets].FindOrAdd(value_set, 32);
  409. { :-(, we must generate a new entry }
  410. if not assigned(entry^.Data) then
  411. entry^.Data:=emitvarsetconst;
  412. lab_set := TAsmSymbol(entry^.Data);
  413. end;
  414. location.reference.symbol:=lab_set;
  415. end;
  416. procedure tcgsetconstnode.pass_generate_code;
  417. type
  418. setbytes=array[0..31] of byte;
  419. Psetbytes=^setbytes;
  420. procedure smallsetconst;
  421. begin
  422. location_reset(location,LOC_CONSTANT,int_cgsize(resultdef.size));
  423. if (source_info.endian=target_info.endian) then
  424. begin
  425. { not plongint, because that will "sign extend" the set on 64 bit platforms }
  426. { if changed to "paword", please also modify "32-resultdef.size*8" and }
  427. { cross-endian code below }
  428. { Extra aint type cast to avoid range errors }
  429. location.value:=aint(pCardinal(value_set)^)
  430. end
  431. else
  432. begin
  433. location.value:=swapendian(Pcardinal(value_set)^);
  434. location.value:=aint(
  435. reverse_byte (location.value and $ff) or
  436. (reverse_byte((location.value shr 8) and $ff) shl 8) or
  437. (reverse_byte((location.value shr 16) and $ff) shl 16) or
  438. (reverse_byte((location.value shr 24) and $ff) shl 24)
  439. );
  440. end;
  441. if (target_info.endian=endian_big) then
  442. location.value:=location.value shr (32-resultdef.size*8);
  443. end;
  444. procedure varsetconst;
  445. var
  446. lastlabel : tasmlabel;
  447. i : longint;
  448. entry : PHashSetItem;
  449. begin
  450. location_reset_ref(location,LOC_CREFERENCE,OS_NO,const_align(8));
  451. lastlabel:=nil;
  452. { const already used ? }
  453. if not assigned(lab_set) then
  454. begin
  455. entry := current_asmdata.ConstPools[sp_varsets].FindOrAdd(value_set, 32);
  456. lab_set := TAsmLabel(entry^.Data); // is it needed anymore?
  457. { :-(, we must generate a new entry }
  458. if not assigned(entry^.Data) then
  459. begin
  460. current_asmdata.getdatalabel(lastlabel);
  461. lab_set:=lastlabel;
  462. entry^.Data:=lastlabel;
  463. maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
  464. new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(8));
  465. current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
  466. if (source_info.endian=target_info.endian) then
  467. for i:=0 to 31 do
  468. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(Psetbytes(value_set)^[i]))
  469. else
  470. for i:=0 to 31 do
  471. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(reverse_byte(Psetbytes(value_set)^[i])));
  472. end;
  473. end;
  474. location.reference.symbol:=lab_set;
  475. end;
  476. begin
  477. adjustforsetbase;
  478. { small sets are loaded as constants }
  479. if is_smallset(resultdef) then
  480. smallsetconst
  481. else
  482. handlevarsetconst;
  483. end;
  484. {*****************************************************************************
  485. TCGNILNODE
  486. *****************************************************************************}
  487. procedure tcgnilnode.pass_generate_code;
  488. begin
  489. location_reset(location,LOC_CONSTANT,OS_ADDR);
  490. location.value:=0;
  491. end;
  492. {*****************************************************************************
  493. TCGGUIDCONSTNODE
  494. *****************************************************************************}
  495. procedure tcgguidconstnode.pass_generate_code;
  496. var
  497. lastlabel : tasmlabel;
  498. i : longint;
  499. entry : PHashSetItem;
  500. begin
  501. location_reset_ref(location,LOC_CREFERENCE,OS_NO,const_align(16));
  502. lastlabel:=nil;
  503. { const already used ? }
  504. if not assigned(lab_set) then
  505. begin
  506. entry := current_asmdata.ConstPools[sp_guids].FindOrAdd(@value,sizeof(value));
  507. lab_set := TAsmLabel(entry^.Data); // is it needed anymore?
  508. { :-(, we must generate a new entry }
  509. if not assigned(entry^.Data) then
  510. begin
  511. current_asmdata.getdatalabel(lastlabel);
  512. lab_set:=lastlabel;
  513. entry^.Data:=lastlabel;
  514. maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
  515. new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(16));
  516. current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
  517. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(longint(value.D1)));
  518. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(value.D2));
  519. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(value.D3));
  520. for i:=low(value.D4) to high(value.D4) do
  521. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(value.D4[i]));
  522. end;
  523. end;
  524. location.reference.symbol:=lab_set;
  525. end;
  526. begin
  527. cdataconstnode:=tcgdataconstnode;
  528. crealconstnode:=tcgrealconstnode;
  529. cordconstnode:=tcgordconstnode;
  530. cpointerconstnode:=tcgpointerconstnode;
  531. cstringconstnode:=tcgstringconstnode;
  532. csetconstnode:=tcgsetconstnode;
  533. cnilnode:=tcgnilnode;
  534. cguidconstnode:=tcgguidconstnode;
  535. end.