ptconst.pas 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Reads typed constants
  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 ptconst;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses symtype,symsym;
  22. { this procedure reads typed constants }
  23. { sym is only needed for ansi strings }
  24. { the assembler label is in the middle (PM) }
  25. procedure readtypedconst(const t:ttype;sym : ttypedconstsym;writable : boolean);
  26. implementation
  27. uses
  28. {$ifdef Delphi}
  29. sysutils,
  30. {$else}
  31. strings,
  32. {$endif Delphi}
  33. globtype,systems,tokens,verbose,
  34. cutils,globals,widestr,scanner,
  35. symconst,symbase,symdef,symtable,
  36. aasmbase,aasmtai,aasmcpu,defutil,defcmp,
  37. { pass 1 }
  38. node,
  39. nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  40. { parser specific stuff }
  41. pbase,pexpr,
  42. { codegen }
  43. cpuinfo,cgbase
  44. ;
  45. {$ifdef fpc}
  46. {$maxfpuregisters 0}
  47. {$endif fpc}
  48. { this procedure reads typed constants }
  49. procedure readtypedconst(const t:ttype;sym : ttypedconstsym;writable : boolean);
  50. var
  51. len,base : longint;
  52. p,hp,hpstart : tnode;
  53. i,j,l,offset,
  54. varalign,
  55. strlength : longint;
  56. curconstsegment : TAAsmoutput;
  57. ll : tasmlabel;
  58. s,sorg : string;
  59. c : char;
  60. ca : pchar;
  61. tmpguid : tguid;
  62. aktpos : longint;
  63. obj : tobjectdef;
  64. recsym,
  65. srsym : tsym;
  66. symt : tsymtable;
  67. value : bestreal;
  68. intvalue : tconstexprint;
  69. strval : pchar;
  70. pw : pcompilerwidestring;
  71. error : boolean;
  72. type
  73. setbytes = array[0..31] of byte;
  74. Psetbytes = ^setbytes;
  75. procedure check_range(def:torddef);
  76. begin
  77. if ((tordconstnode(p).value>def.high) or
  78. (tordconstnode(p).value<def.low)) then
  79. begin
  80. if (cs_check_range in aktlocalswitches) then
  81. Message(parser_e_range_check_error)
  82. else
  83. Message(parser_w_range_check_error);
  84. end;
  85. end;
  86. {$R-} {Range check creates problem with init_8bit(-1) !!}
  87. begin
  88. if writable then
  89. curconstsegment:=datasegment
  90. else
  91. curconstsegment:=consts;
  92. case t.def.deftype of
  93. orddef:
  94. begin
  95. p:=comp_expr(true);
  96. case torddef(t.def).typ of
  97. bool8bit :
  98. begin
  99. if is_constboolnode(p) then
  100. curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value))
  101. else
  102. Message(cg_e_illegal_expression);
  103. end;
  104. bool16bit :
  105. begin
  106. if is_constboolnode(p) then
  107. curconstSegment.concat(Tai_const.Create_16bit(tordconstnode(p).value))
  108. else
  109. Message(cg_e_illegal_expression);
  110. end;
  111. bool32bit :
  112. begin
  113. if is_constboolnode(p) then
  114. curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value))
  115. else
  116. Message(cg_e_illegal_expression);
  117. end;
  118. uchar :
  119. begin
  120. if is_constcharnode(p) then
  121. curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value))
  122. else
  123. Message(cg_e_illegal_expression);
  124. end;
  125. uwidechar :
  126. begin
  127. if is_constcharnode(p) then
  128. inserttypeconv(p,cwidechartype);
  129. if is_constwidecharnode(p) then
  130. curconstSegment.concat(Tai_const.Create_16bit(tordconstnode(p).value))
  131. else
  132. Message(cg_e_illegal_expression);
  133. end;
  134. s8bit,
  135. u8bit :
  136. begin
  137. if is_constintnode(p) then
  138. begin
  139. curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value));
  140. check_range(torddef(t.def));
  141. end
  142. else
  143. Message(cg_e_illegal_expression);
  144. end;
  145. u16bit,
  146. s16bit :
  147. begin
  148. if is_constintnode(p) then
  149. begin
  150. curconstSegment.concat(Tai_const.Create_16bit(tordconstnode(p).value));
  151. check_range(torddef(t.def));
  152. end
  153. else
  154. Message(cg_e_illegal_expression);
  155. end;
  156. s32bit,
  157. u32bit :
  158. begin
  159. if is_constintnode(p) then
  160. begin
  161. curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value));
  162. if torddef(t.def).typ<>u32bit then
  163. check_range(torddef(t.def));
  164. end
  165. else
  166. Message(cg_e_illegal_expression);
  167. end;
  168. s64bit,
  169. u64bit,
  170. scurrency:
  171. begin
  172. if is_constintnode(p) then
  173. intvalue := tordconstnode(p).value
  174. {$ifndef VER1_0}
  175. else if is_constrealnode(p) and
  176. (torddef(t.def).typ = scurrency) and
  177. (trealconstnode(p).value_real*10000 >= low(int64)) and
  178. (trealconstnode(p).value_real*10000 <= high(int64)) then
  179. intvalue := round(trealconstnode(p).value_real*10000)
  180. {$endif ndef VER1_0}
  181. else
  182. begin
  183. intvalue := 0;
  184. Message(cg_e_illegal_expression);
  185. end;
  186. {$warning maybe change to create_64bit}
  187. if target_info.endian = endian_little then
  188. begin
  189. curconstSegment.concat(Tai_const.Create_32bit(Cardinal(intvalue and $ffffffff)));
  190. curconstSegment.concat(Tai_const.Create_32bit(Cardinal(intvalue shr 32)));
  191. end
  192. else
  193. begin
  194. curconstSegment.concat(Tai_const.Create_32bit(Cardinal(intvalue shr 32)));
  195. curconstSegment.concat(Tai_const.Create_32bit(Cardinal(intvalue and $ffffffff)));
  196. end;
  197. end;
  198. else
  199. internalerror(3799);
  200. end;
  201. p.free;
  202. end;
  203. floatdef:
  204. begin
  205. p:=comp_expr(true);
  206. if is_constrealnode(p) then
  207. value:=trealconstnode(p).value_real
  208. else if is_constintnode(p) then
  209. value:=tordconstnode(p).value
  210. else
  211. Message(cg_e_illegal_expression);
  212. case tfloatdef(t.def).typ of
  213. s32real :
  214. curconstSegment.concat(Tai_real_32bit.Create(ts32real(value)));
  215. s64real :
  216. curconstSegment.concat(Tai_real_64bit.Create(ts64real(value)));
  217. s80real :
  218. curconstSegment.concat(Tai_real_80bit.Create(value));
  219. {$ifdef ver1_0}
  220. s64comp :
  221. curconstSegment.concat(Tai_comp_64bit.Create(value));
  222. s64currency:
  223. curconstSegment.concat(Tai_comp_64bit.Create(value*10000));
  224. {$else ver1_0}
  225. { the round is necessary for native compilers where comp isn't a float }
  226. s64comp :
  227. curconstSegment.concat(Tai_comp_64bit.Create(round(value)));
  228. s64currency:
  229. curconstSegment.concat(Tai_comp_64bit.Create(round(value*10000)));
  230. {$endif ver1_0}
  231. s128real:
  232. curconstSegment.concat(Tai_real_128bit.Create(value));
  233. else
  234. internalerror(18);
  235. end;
  236. p.free;
  237. end;
  238. classrefdef:
  239. begin
  240. p:=comp_expr(true);
  241. case p.nodetype of
  242. loadvmtaddrn:
  243. with Tclassrefdef(p.resulttype.def) do
  244. begin
  245. if not Tobjectdef(pointertype.def).is_related(Tobjectdef(pointertype.def)) then
  246. message(cg_e_illegal_expression);
  247. curconstSegment.concat(Tai_const_symbol.Create(objectlibrary.newasmsymbol(
  248. Tobjectdef(pointertype.def).vmt_mangledname,AB_EXTERNAL,AT_DATA)));
  249. end;
  250. niln:
  251. curconstSegment.concat(Tai_const.Create_ptr(0));
  252. else Message(cg_e_illegal_expression);
  253. end;
  254. p.free;
  255. end;
  256. pointerdef:
  257. begin
  258. p:=comp_expr(true);
  259. if (p.nodetype=typeconvn) then
  260. with Ttypeconvnode(p) do
  261. if (left.nodetype in [addrn,niln]) and equal_defs(t.def,p.resulttype.def) then
  262. begin
  263. hp:=left;
  264. left:=nil;
  265. p.free;
  266. p:=hp;
  267. end;
  268. { allows horrible ofs(typeof(TButton)^) code !! }
  269. if (p.nodetype=addrn) then
  270. with Taddrnode(p) do
  271. if left.nodetype=derefn then
  272. begin
  273. hp:=tderefnode(left).left;
  274. tderefnode(left).left:=nil;
  275. p.free;
  276. p:=hp;
  277. end;
  278. { const pointer ? }
  279. if (p.nodetype = pointerconstn) then
  280. curconstsegment.concat(Tai_const.Create_ptr(TConstPtrUInt(tpointerconstnode(p).value)))
  281. { nil pointer ? }
  282. else if p.nodetype=niln then
  283. curconstSegment.concat(Tai_const.Create_ptr(0))
  284. { maybe pchar ? }
  285. else
  286. if is_char(tpointerdef(t.def).pointertype.def) and
  287. (p.nodetype<>addrn) then
  288. begin
  289. objectlibrary.getdatalabel(ll);
  290. curconstSegment.concat(Tai_const_symbol.Create(ll));
  291. if p.nodetype=stringconstn then
  292. varalign:=tstringconstnode(p).len
  293. else
  294. varalign:=0;
  295. varalign:=const_align(varalign);
  296. Consts.concat(Tai_align.Create(varalign));
  297. Consts.concat(Tai_label.Create(ll));
  298. if p.nodetype=stringconstn then
  299. begin
  300. len:=tstringconstnode(p).len;
  301. { For tp7 the maximum lentgh can be 255 }
  302. if (m_tp7 in aktmodeswitches) and
  303. (len>255) then
  304. len:=255;
  305. getmem(ca,len+2);
  306. move(tstringconstnode(p).value_str^,ca^,len+1);
  307. Consts.concat(Tai_string.Create_length_pchar(ca,len+1));
  308. end
  309. else
  310. if is_constcharnode(p) then
  311. Consts.concat(Tai_string.Create(char(byte(tordconstnode(p).value))+#0))
  312. else
  313. Message(cg_e_illegal_expression);
  314. end
  315. { maybe pwidechar ? }
  316. else
  317. if is_widechar(tpointerdef(t.def).pointertype.def) and
  318. (p.nodetype<>addrn) then
  319. begin
  320. objectlibrary.getdatalabel(ll);
  321. curconstSegment.concat(Tai_const_symbol.Create(ll));
  322. Consts.concat(tai_align.create(const_align(pointer_size)));
  323. Consts.concat(Tai_label.Create(ll));
  324. if (p.nodetype in [stringconstn,ordconstn]) then
  325. begin
  326. { convert to widestring stringconstn }
  327. inserttypeconv(p,cwidestringtype);
  328. if (p.nodetype=stringconstn) and
  329. (tstringconstnode(p).st_type=st_widestring) then
  330. begin
  331. pw:=pcompilerwidestring(tstringconstnode(p).value_str);
  332. for i:=0 to tstringconstnode(p).len-1 do
  333. Consts.concat(Tai_const.Create_16bit(pw^.data[i]));
  334. { ending #0 }
  335. Consts.concat(Tai_const.Create_16bit(0))
  336. end;
  337. end
  338. else
  339. Message(cg_e_illegal_expression);
  340. end
  341. else
  342. if p.nodetype=addrn then
  343. begin
  344. { support @@procvar in tp mode }
  345. if (m_tp_procvar in aktmodeswitches) and
  346. (taddrnode(p).left.nodetype=addrn) then
  347. p:=taddrnode(p).left;
  348. { insert typeconv }
  349. inserttypeconv(p,t);
  350. { if a typeconv node was inserted then check if it was an tc_equal. If
  351. true then we remove the node. If not tc_equal then we leave the typeconvn
  352. and the nodetype=loadn will always be false and generate the error (PFV) }
  353. if (p.nodetype=typeconvn) then
  354. begin
  355. if (ttypeconvnode(p).convtype=tc_equal) then
  356. hpstart:=taddrnode(ttypeconvnode(p).left).left
  357. else
  358. hpstart:=p;
  359. end
  360. else
  361. hpstart:=taddrnode(p).left;
  362. hp:=hpstart;
  363. while assigned(hp) and (hp.nodetype in [subscriptn,vecn]) do
  364. hp:=tunarynode(hp).left;
  365. if (hp.nodetype=loadn) then
  366. begin
  367. hp:=hpstart;
  368. offset:=0;
  369. while assigned(hp) and (hp.nodetype<>loadn) do
  370. begin
  371. case hp.nodetype of
  372. vecn :
  373. begin
  374. case tvecnode(hp).left.resulttype.def.deftype of
  375. stringdef :
  376. begin
  377. { this seems OK for shortstring and ansistrings PM }
  378. { it is wrong for widestrings !! }
  379. len:=1;
  380. base:=0;
  381. end;
  382. arraydef :
  383. begin
  384. len:=tarraydef(tvecnode(hp).left.resulttype.def).elesize;
  385. base:=tarraydef(tvecnode(hp).left.resulttype.def).lowrange;
  386. end
  387. else
  388. Message(cg_e_illegal_expression);
  389. end;
  390. if is_constintnode(tvecnode(hp).right) then
  391. inc(offset,len*(get_ordinal_value(tvecnode(hp).right)-base))
  392. else
  393. Message(cg_e_illegal_expression);
  394. end;
  395. subscriptn :
  396. inc(offset,tsubscriptnode(hp).vs.fieldoffset)
  397. else
  398. Message(cg_e_illegal_expression);
  399. end;
  400. hp:=tbinarynode(hp).left;
  401. end;
  402. srsym:=tloadnode(hp).symtableentry;
  403. case srsym.typ of
  404. procsym :
  405. begin
  406. if Tprocsym(srsym).procdef_count>1 then
  407. Message(parser_e_no_overloaded_procvars);
  408. if po_abstractmethod in tprocsym(srsym).first_procdef.procoptions then
  409. Message(type_e_cant_take_address_of_abstract_method)
  410. else
  411. curconstSegment.concat(Tai_const_symbol.Createname(tprocsym(srsym).first_procdef.mangledname,AT_FUNCTION,offset));
  412. end;
  413. varsym :
  414. curconstSegment.concat(Tai_const_symbol.Createname(tvarsym(srsym).mangledname,AT_FUNCTION,offset));
  415. typedconstsym :
  416. curconstSegment.concat(Tai_const_symbol.Createname(ttypedconstsym(srsym).mangledname,AT_FUNCTION,offset));
  417. else
  418. Message(type_e_variable_id_expected);
  419. end;
  420. end
  421. else
  422. Message(cg_e_illegal_expression);
  423. end
  424. else
  425. { allow typeof(Object type)}
  426. if (p.nodetype=inlinen) and
  427. (tinlinenode(p).inlinenumber=in_typeof_x) then
  428. begin
  429. if (tinlinenode(p).left.nodetype=typen) then
  430. begin
  431. curconstSegment.concat(Tai_const_symbol.createname(
  432. tobjectdef(tinlinenode(p).left.resulttype.def).vmt_mangledname,AT_FUNCTION,0));
  433. end
  434. else
  435. Message(cg_e_illegal_expression);
  436. end
  437. else
  438. Message(cg_e_illegal_expression);
  439. p.free;
  440. end;
  441. setdef:
  442. begin
  443. p:=comp_expr(true);
  444. if p.nodetype=setconstn then
  445. begin
  446. { be sure to convert to the correct result, else
  447. it can generate smallset data instead of normalset (PFV) }
  448. inserttypeconv(p,t);
  449. { we only allow const sets }
  450. if assigned(tsetconstnode(p).left) then
  451. Message(cg_e_illegal_expression)
  452. else
  453. begin
  454. { this writing is endian independant }
  455. { untrue - because they are considered }
  456. { arrays of 32-bit values CEC }
  457. if source_info.endian = target_info.endian then
  458. begin
  459. for l:=0 to p.resulttype.def.size-1 do
  460. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[l]));
  461. end
  462. else
  463. begin
  464. { store as longint values in swaped format }
  465. j:=0;
  466. for l:=0 to ((p.resulttype.def.size-1) div 4) do
  467. begin
  468. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+3]));
  469. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+2]));
  470. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+1]));
  471. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j]));
  472. Inc(j,4);
  473. end;
  474. end;
  475. end;
  476. end
  477. else
  478. Message(cg_e_illegal_expression);
  479. p.free;
  480. end;
  481. enumdef:
  482. begin
  483. p:=comp_expr(true);
  484. if p.nodetype=ordconstn then
  485. begin
  486. if equal_defs(p.resulttype.def,t.def) or
  487. is_subequal(p.resulttype.def,t.def) then
  488. begin
  489. case p.resulttype.def.size of
  490. 1 : curconstSegment.concat(Tai_const.Create_8bit(Byte(tordconstnode(p).value)));
  491. 2 : curconstSegment.concat(Tai_const.Create_16bit(Word(tordconstnode(p).value)));
  492. 4 : curconstSegment.concat(Tai_const.Create_32bit(Cardinal(tordconstnode(p).value)));
  493. end;
  494. end
  495. else
  496. IncompatibleTypes(p.resulttype.def,t.def);
  497. end
  498. else
  499. Message(cg_e_illegal_expression);
  500. p.free;
  501. end;
  502. stringdef:
  503. begin
  504. p:=comp_expr(true);
  505. { load strval and strlength of the constant tree }
  506. if (p.nodetype=stringconstn) or is_widestring(t.def) then
  507. begin
  508. { convert to the expected string type so that
  509. for widestrings strval is a pcompilerwidestring }
  510. inserttypeconv(p,t);
  511. strlength:=tstringconstnode(p).len;
  512. strval:=tstringconstnode(p).value_str;
  513. end
  514. else if is_constcharnode(p) then
  515. begin
  516. { strval:=pchar(@tordconstnode(p).value);
  517. THIS FAIL on BIG_ENDIAN MACHINES PM }
  518. c:=chr(tordconstnode(p).value and $ff);
  519. strval:=@c;
  520. strlength:=1
  521. end
  522. else if is_constresourcestringnode(p) then
  523. begin
  524. strval:=pchar(tconstsym(tloadnode(p).symtableentry).value.valueptr);
  525. strlength:=tconstsym(tloadnode(p).symtableentry).value.len;
  526. end
  527. else
  528. begin
  529. Message(cg_e_illegal_expression);
  530. strlength:=-1;
  531. end;
  532. if strlength>=0 then
  533. begin
  534. case tstringdef(t.def).string_typ of
  535. st_shortstring:
  536. begin
  537. if strlength>=t.def.size then
  538. begin
  539. message2(parser_w_string_too_long,strpas(strval),tostr(t.def.size-1));
  540. strlength:=t.def.size-1;
  541. end;
  542. curconstSegment.concat(Tai_const.Create_8bit(strlength));
  543. { this can also handle longer strings }
  544. getmem(ca,strlength+1);
  545. move(strval^,ca^,strlength);
  546. ca[strlength]:=#0;
  547. curconstSegment.concat(Tai_string.Create_length_pchar(ca,strlength));
  548. { fillup with spaces if size is shorter }
  549. if t.def.size>strlength then
  550. begin
  551. getmem(ca,t.def.size-strlength);
  552. { def.size contains also the leading length, so we }
  553. { we have to subtract one }
  554. fillchar(ca[0],t.def.size-strlength-1,' ');
  555. ca[t.def.size-strlength-1]:=#0;
  556. { this can also handle longer strings }
  557. curconstSegment.concat(Tai_string.Create_length_pchar(ca,t.def.size-strlength-1));
  558. end;
  559. end;
  560. st_ansistring:
  561. begin
  562. { an empty ansi string is nil! }
  563. if (strlength=0) then
  564. curconstSegment.concat(Tai_const.Create_ptr(0))
  565. else
  566. begin
  567. objectlibrary.getdatalabel(ll);
  568. curconstSegment.concat(Tai_const_symbol.Create(ll));
  569. { the actual structure starts at -12 from start label - CEC }
  570. Consts.concat(tai_align.create(const_align(pointer_size)));
  571. { first write the maximum size }
  572. Consts.concat(Tai_const.Create_32bit(strlength));
  573. { second write the real length }
  574. Consts.concat(Tai_const.Create_32bit(strlength));
  575. { redondent with maxlength but who knows ... (PM) }
  576. { third write use count (set to -1 for safety ) }
  577. Consts.concat(Tai_const.Create_32bit(Cardinal(-1)));
  578. Consts.concat(Tai_label.Create(ll));
  579. getmem(ca,strlength+2);
  580. move(strval^,ca^,strlength);
  581. { The terminating #0 to be stored in the .data section (JM) }
  582. ca[strlength]:=#0;
  583. { End of the PChar. The memory has to be allocated because in }
  584. { tai_string.done, there is a freemem(len+1) (JM) }
  585. ca[strlength+1]:=#0;
  586. Consts.concat(Tai_string.Create_length_pchar(ca,strlength+1));
  587. end;
  588. end;
  589. st_widestring:
  590. begin
  591. { an empty ansi string is nil! }
  592. if (strlength=0) then
  593. curconstSegment.concat(Tai_const.Create_ptr(0))
  594. else
  595. begin
  596. objectlibrary.getdatalabel(ll);
  597. curconstSegment.concat(Tai_const_symbol.Create(ll));
  598. { the actual structure starts at -12 from start label - CEC }
  599. Consts.concat(tai_align.create(const_align(pointer_size)));
  600. Consts.concat(Tai_const.Create_32bit(strlength));
  601. Consts.concat(Tai_const.Create_32bit(strlength));
  602. Consts.concat(Tai_const.Create_32bit(Cardinal(-1)));
  603. Consts.concat(Tai_label.Create(ll));
  604. for i:=0 to strlength-1 do
  605. Consts.concat(Tai_const.Create_16bit(pcompilerwidestring(strval)^.data[i]));
  606. { ending #0 }
  607. Consts.concat(Tai_const.Create_16bit(0))
  608. end;
  609. end;
  610. st_longstring:
  611. begin
  612. internalerror(200107081);
  613. {curconstSegment.concat(Tai_const.Create_32bit(strlength))));
  614. curconstSegment.concat(Tai_const.Create_8bit(0));
  615. getmem(ca,strlength+1);
  616. move(strval^,ca^,strlength);
  617. ca[strlength]:=#0;
  618. generate_pascii(consts,ca,strlength);
  619. curconstSegment.concat(Tai_const.Create_8bit(0));}
  620. end;
  621. end;
  622. end;
  623. p.free;
  624. end;
  625. arraydef:
  626. begin
  627. if try_to_consume(_LKLAMMER) then
  628. begin
  629. for l:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange-1 do
  630. begin
  631. readtypedconst(tarraydef(t.def).elementtype,nil,writable);
  632. consume(_COMMA);
  633. end;
  634. readtypedconst(tarraydef(t.def).elementtype,nil,writable);
  635. consume(_RKLAMMER);
  636. end
  637. else
  638. { if array of char then we allow also a string }
  639. if is_char(tarraydef(t.def).elementtype.def) then
  640. begin
  641. p:=comp_expr(true);
  642. if p.nodetype=stringconstn then
  643. begin
  644. len:=tstringconstnode(p).len;
  645. { For tp7 the maximum lentgh can be 255 }
  646. if (m_tp7 in aktmodeswitches) and
  647. (len>255) then
  648. len:=255;
  649. ca:=tstringconstnode(p).value_str;
  650. end
  651. else
  652. if is_constcharnode(p) then
  653. begin
  654. c:=chr(tordconstnode(p).value and $ff);
  655. ca:=@c;
  656. len:=1;
  657. end
  658. else
  659. begin
  660. Message(cg_e_illegal_expression);
  661. len:=0;
  662. end;
  663. if len>(tarraydef(t.def).highrange-tarraydef(t.def).lowrange+1) then
  664. Message(parser_e_string_larger_array);
  665. for i:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange do
  666. begin
  667. if i+1-tarraydef(t.def).lowrange<=len then
  668. begin
  669. curconstSegment.concat(Tai_const.Create_8bit(byte(ca^)));
  670. inc(ca);
  671. end
  672. else
  673. {Fill the remaining positions with #0.}
  674. curconstSegment.concat(Tai_const.Create_8bit(0));
  675. end;
  676. p.free;
  677. end
  678. else
  679. { dynamic array nil }
  680. if is_dynamic_array(t.def) then
  681. begin
  682. { Only allow nil initialization }
  683. consume(_NIL);
  684. curconstSegment.concat(Tai_const.Create_ptr(0));
  685. end
  686. else
  687. begin
  688. { we want the ( }
  689. consume(_LKLAMMER);
  690. end;
  691. end;
  692. procvardef:
  693. begin
  694. { Procvars and pointers are no longer compatible. }
  695. { under tp: =nil or =var under fpc: =nil or =@var }
  696. if token=_NIL then
  697. begin
  698. curconstSegment.concat(Tai_const.Create_ptr(0));
  699. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  700. curconstSegment.concat(Tai_const.Create_ptr(0));
  701. consume(_NIL);
  702. exit;
  703. end;
  704. { you can't assign a value other than NIL to a typed constant }
  705. { which is a "procedure of object", because this also requires }
  706. { address of an object/class instance, which is not known at }
  707. { compile time (JM) }
  708. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  709. Message(parser_e_no_procvarobj_const);
  710. { parse the rest too, so we can continue with error checking }
  711. getprocvardef:=tprocvardef(t.def);
  712. p:=comp_expr(true);
  713. getprocvardef:=nil;
  714. if codegenerror then
  715. begin
  716. p.free;
  717. exit;
  718. end;
  719. { let type conversion check everything needed }
  720. inserttypeconv(p,t);
  721. if codegenerror then
  722. begin
  723. p.free;
  724. exit;
  725. end;
  726. { remove typeconvn, that will normally insert a lea
  727. instruction which is not necessary for us }
  728. if p.nodetype=typeconvn then
  729. begin
  730. hp:=ttypeconvnode(p).left;
  731. ttypeconvnode(p).left:=nil;
  732. p.free;
  733. p:=hp;
  734. end;
  735. { remove addrn which we also don't need here }
  736. if p.nodetype=addrn then
  737. begin
  738. hp:=taddrnode(p).left;
  739. taddrnode(p).left:=nil;
  740. p.free;
  741. p:=hp;
  742. end;
  743. { we now need to have a loadn with a procsym }
  744. if (p.nodetype=loadn) and
  745. (tloadnode(p).symtableentry.typ=procsym) then
  746. begin
  747. curconstSegment.concat(Tai_const_symbol.createname(
  748. tprocsym(tloadnode(p).symtableentry).first_procdef.mangledname,AT_FUNCTION,0));
  749. end
  750. else
  751. Message(cg_e_illegal_expression);
  752. p.free;
  753. end;
  754. { reads a typed constant record }
  755. recorddef:
  756. begin
  757. { KAZ }
  758. if (trecorddef(t.def)=rec_tguid) and
  759. ((token=_CSTRING) or (token=_CCHAR) or (token=_ID)) then
  760. begin
  761. p:=comp_expr(true);
  762. inserttypeconv(p,cshortstringtype);
  763. if p.nodetype=stringconstn then
  764. begin
  765. s:=strpas(tstringconstnode(p).value_str);
  766. p.free;
  767. if string2guid(s,tmpguid) then
  768. begin
  769. curconstSegment.concat(Tai_const.Create_32bit(tmpguid.D1));
  770. curconstSegment.concat(Tai_const.Create_16bit(tmpguid.D2));
  771. curconstSegment.concat(Tai_const.Create_16bit(tmpguid.D3));
  772. for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
  773. curconstSegment.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
  774. end
  775. else
  776. Message(parser_e_improper_guid_syntax);
  777. end
  778. else
  779. begin
  780. p.free;
  781. Message(cg_e_illegal_expression);
  782. exit;
  783. end;
  784. end
  785. else
  786. begin
  787. consume(_LKLAMMER);
  788. sorg:='';
  789. aktpos:=0;
  790. srsym := tsym(trecorddef(t.def).symtable.symindex.first);
  791. recsym := nil;
  792. while token<>_RKLAMMER do
  793. begin
  794. s:=pattern;
  795. sorg:=orgpattern;
  796. consume(_ID);
  797. consume(_COLON);
  798. error := false;
  799. recsym := tsym(trecorddef(t.def).symtable.search(s));
  800. if not assigned(recsym) then
  801. begin
  802. Message1(sym_e_illegal_field,sorg);
  803. error := true;
  804. end;
  805. if (not error) and
  806. (not assigned(srsym) or
  807. (s <> srsym.name)) then
  808. { possible variant record (JM) }
  809. begin
  810. { All parts of a variant start at the same offset }
  811. { Also allow jumping from one variant part to another, }
  812. { as long as the offsets match }
  813. if (assigned(srsym) and
  814. (tvarsym(recsym).fieldoffset = tvarsym(srsym).fieldoffset)) or
  815. { srsym is not assigned after parsing w2 in the }
  816. { typed const in the next example: }
  817. { type tr = record case byte of }
  818. { 1: (l1,l2: dword); }
  819. { 2: (w1,w2: word); }
  820. { end; }
  821. { const r: tr = (w1:1;w2:1;l2:5); }
  822. (tvarsym(recsym).fieldoffset = aktpos) then
  823. srsym := recsym
  824. { going backwards isn't allowed in any mode }
  825. else if (tvarsym(recsym).fieldoffset<aktpos) then
  826. begin
  827. Message(parser_e_invalid_record_const);
  828. error := true;
  829. end
  830. { Delphi allows you to skip fields }
  831. else if (m_delphi in aktmodeswitches) then
  832. begin
  833. Message1(parser_w_skipped_fields_before,sorg);
  834. srsym := recsym;
  835. end
  836. { FPC and TP don't }
  837. else
  838. begin
  839. Message1(parser_e_skipped_fields_before,sorg);
  840. error := true;
  841. end;
  842. end;
  843. if error then
  844. consume_all_until(_SEMICOLON)
  845. else
  846. begin
  847. { if needed fill (alignment) }
  848. if tvarsym(srsym).fieldoffset>aktpos then
  849. for i:=1 to tvarsym(srsym).fieldoffset-aktpos do
  850. curconstSegment.concat(Tai_const.Create_8bit(0));
  851. { new position }
  852. aktpos:=tvarsym(srsym).fieldoffset+tvarsym(srsym).vartype.def.size;
  853. { read the data }
  854. readtypedconst(tvarsym(srsym).vartype,nil,writable);
  855. { keep previous field for checking whether whole }
  856. { record was initialized (JM) }
  857. recsym := srsym;
  858. { goto next field }
  859. srsym := tsym(srsym.indexnext);
  860. if token=_SEMICOLON then
  861. consume(_SEMICOLON)
  862. else break;
  863. end;
  864. end;
  865. { are there any fields left? }
  866. if assigned(srsym) and
  867. { don't complain if there only come other variant parts }
  868. { after the last initialized field }
  869. ((recsym=nil) or
  870. (tvarsym(srsym).fieldoffset > tvarsym(recsym).fieldoffset)) then
  871. Message1(parser_w_skipped_fields_after,sorg);
  872. for i:=1 to t.def.size-aktpos do
  873. curconstSegment.concat(Tai_const.Create_8bit(0));
  874. consume(_RKLAMMER);
  875. end;
  876. end;
  877. { reads a typed object }
  878. objectdef:
  879. begin
  880. if is_class_or_interface(t.def) then
  881. begin
  882. p:=comp_expr(true);
  883. if p.nodetype<>niln then
  884. begin
  885. Message(parser_e_type_const_not_possible);
  886. consume_all_until(_RKLAMMER);
  887. end
  888. else
  889. begin
  890. curconstSegment.concat(Tai_const.Create_ptr(0));
  891. end;
  892. p.free;
  893. end
  894. { for objects we allow it only if it doesn't contain a vmt }
  895. else if (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  896. (m_fpc in aktmodeswitches) then
  897. Message(parser_e_type_const_not_possible)
  898. else
  899. begin
  900. consume(_LKLAMMER);
  901. aktpos:=0;
  902. while token<>_RKLAMMER do
  903. begin
  904. s:=pattern;
  905. sorg:=orgpattern;
  906. consume(_ID);
  907. consume(_COLON);
  908. srsym:=nil;
  909. obj:=tobjectdef(t.def);
  910. symt:=obj.symtable;
  911. while (srsym=nil) and assigned(symt) do
  912. begin
  913. srsym:=tsym(symt.search(s));
  914. if assigned(obj) then
  915. obj:=obj.childof;
  916. if assigned(obj) then
  917. symt:=obj.symtable
  918. else
  919. symt:=nil;
  920. end;
  921. if srsym=nil then
  922. begin
  923. Message1(sym_e_id_not_found,sorg);
  924. consume_all_until(_SEMICOLON);
  925. end
  926. else
  927. with Tvarsym(srsym) do
  928. begin
  929. { check position }
  930. if fieldoffset<aktpos then
  931. message(parser_e_invalid_record_const);
  932. { check in VMT needs to be added for TP mode }
  933. with Tobjectdef(t.def) do
  934. if not(m_fpc in aktmodeswitches) and
  935. (oo_has_vmt in objectoptions) and
  936. (vmt_offset<fieldoffset) then
  937. begin
  938. for i:=1 to vmt_offset-aktpos do
  939. curconstsegment.concat(tai_const.create_8bit(0));
  940. curconstsegment.concat(tai_const_symbol.createname(vmt_mangledname,AT_FUNCTION,0));
  941. { this is more general }
  942. aktpos:=vmt_offset + pointer_size;
  943. end;
  944. { if needed fill }
  945. if fieldoffset>aktpos then
  946. for i:=1 to fieldoffset-aktpos do
  947. curconstSegment.concat(Tai_const.Create_8bit(0));
  948. { new position }
  949. aktpos:=fieldoffset+vartype.def.size;
  950. { read the data }
  951. readtypedconst(vartype,nil,writable);
  952. if token=_SEMICOLON then
  953. consume(_SEMICOLON)
  954. else break;
  955. end;
  956. end;
  957. if not(m_fpc in aktmodeswitches) and
  958. (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  959. (tobjectdef(t.def).vmt_offset>=aktpos) then
  960. begin
  961. for i:=1 to tobjectdef(t.def).vmt_offset-aktpos do
  962. curconstsegment.concat(tai_const.create_8bit(0));
  963. curconstsegment.concat(tai_const_symbol.createname(tobjectdef(t.def).vmt_mangledname,AT_FUNCTION,0));
  964. { this is more general }
  965. aktpos:=tobjectdef(t.def).vmt_offset + pointer_size;
  966. end;
  967. for i:=1 to t.def.size-aktpos do
  968. curconstSegment.concat(Tai_const.Create_8bit(0));
  969. consume(_RKLAMMER);
  970. end;
  971. end;
  972. errordef:
  973. begin
  974. { try to consume something useful }
  975. if token=_LKLAMMER then
  976. consume_all_until(_RKLAMMER)
  977. else
  978. consume_all_until(_SEMICOLON);
  979. end;
  980. else Message(parser_e_type_const_not_possible);
  981. end;
  982. end;
  983. {$ifdef fpc}
  984. {$maxfpuregisters default}
  985. {$endif fpc}
  986. end.
  987. {
  988. $Log$
  989. Revision 1.80 2004-03-02 00:36:33 olle
  990. * big transformation of Tai_[const_]Symbol.Create[data]name*
  991. Revision 1.79 2004/02/26 16:15:23 peter
  992. * support @@procvar in typed consts
  993. Revision 1.78 2004/02/07 23:28:34 daniel
  994. * Take advantage of our new with statement optimization
  995. Revision 1.77 2003/12/29 12:48:39 jonas
  996. + support for currency typed constants if currency=int64. Warning: does
  997. not work properly for extreme values if bestreal <= double
  998. Revision 1.76 2003/12/08 22:34:24 peter
  999. * tai_const.create_32bit changed to cardinal
  1000. Revision 1.75 2003/11/22 00:32:35 jonas
  1001. * fixed reversed "got <type 1>, expected <type 1>" error message
  1002. Revision 1.74 2003/11/12 16:05:39 florian
  1003. * assembler readers OOPed
  1004. + typed currency constants
  1005. + typed 128 bit float constants if the CPU supports it
  1006. Revision 1.73 2003/11/08 10:23:35 florian
  1007. * fixed parsing of typed widestring constants with length 1
  1008. Revision 1.72 2003/10/21 18:16:13 peter
  1009. * IncompatibleTypes() added that will include unit names when
  1010. the typenames are the same
  1011. Revision 1.71 2003/09/23 17:56:06 peter
  1012. * locals and paras are allocated in the code generation
  1013. * tvarsym.localloc contains the location of para/local when
  1014. generating code for the current procedure
  1015. Revision 1.70 2003/09/03 15:55:01 peter
  1016. * NEWRA branch merged
  1017. Revision 1.69 2003/05/09 17:47:03 peter
  1018. * self moved to hidden parameter
  1019. * removed hdisposen,hnewn,selfn
  1020. Revision 1.68 2003/04/30 20:53:32 florian
  1021. * error when address of an abstract method is taken
  1022. * fixed some x86-64 problems
  1023. * merged some more x86-64 and i386 code
  1024. Revision 1.67 2003/04/24 22:29:58 florian
  1025. * fixed a lot of PowerPC related stuff
  1026. Revision 1.66 2003/04/06 21:11:23 olle
  1027. * changed newasmsymbol to newasmsymboldata for data symbols
  1028. Revision 1.65 2003/03/17 21:42:32 peter
  1029. * allow nil initialization of dynamic array
  1030. Revision 1.64 2003/01/02 20:45:08 peter
  1031. * fix uninited var
  1032. Revision 1.63 2002/12/26 12:34:54 florian
  1033. * fixed support for type widechar consts
  1034. Revision 1.62 2002/12/07 14:15:33 carl
  1035. + add some explicit typecasts to remove some warnings
  1036. Revision 1.61 2002/11/25 18:43:33 carl
  1037. - removed the invalid if <> checking (Delphi is strange on this)
  1038. + implemented abstract warning on instance creation of class with
  1039. abstract methods.
  1040. * some error message cleanups
  1041. Revision 1.60 2002/11/25 17:43:23 peter
  1042. * splitted defbase in defutil,symutil,defcmp
  1043. * merged isconvertable and is_equal into compare_defs(_ext)
  1044. * made operator search faster by walking the list only once
  1045. Revision 1.59 2002/11/22 22:48:10 carl
  1046. * memory optimization with tconstsym (1.5%)
  1047. Revision 1.58 2002/11/09 15:31:57 carl
  1048. + align ansi/wide string constants
  1049. Revision 1.57 2002/09/06 19:58:31 carl
  1050. * start bugfix 1996
  1051. * 64-bit typed constant now work correctly and fully (bugfix 2001)
  1052. Revision 1.56 2002/09/03 16:26:27 daniel
  1053. * Make Tprocdef.defs protected
  1054. Revision 1.55 2002/08/11 14:32:27 peter
  1055. * renamed current_library to objectlibrary
  1056. Revision 1.54 2002/08/11 13:24:13 peter
  1057. * saving of asmsymbols in ppu supported
  1058. * asmsymbollist global is removed and moved into a new class
  1059. tasmlibrarydata that will hold the info of a .a file which
  1060. corresponds with a single module. Added librarydata to tmodule
  1061. to keep the library info stored for the module. In the future the
  1062. objectfiles will also be stored to the tasmlibrarydata class
  1063. * all getlabel/newasmsymbol and friends are moved to the new class
  1064. Revision 1.53 2002/07/23 12:34:30 daniel
  1065. * Readded old set code. To use it define 'oldset'. Activated by default
  1066. for ppc.
  1067. Revision 1.52 2002/07/22 11:48:04 daniel
  1068. * Sets are now internally sets.
  1069. Revision 1.51 2002/07/20 11:57:56 florian
  1070. * types.pas renamed to defbase.pas because D6 contains a types
  1071. unit so this would conflicts if D6 programms are compiled
  1072. + Willamette/SSE2 instructions to assembler added
  1073. Revision 1.50 2002/07/01 18:46:25 peter
  1074. * internal linker
  1075. * reorganized aasm layer
  1076. Revision 1.49 2002/05/18 13:34:16 peter
  1077. * readded missing revisions
  1078. Revision 1.48 2002/05/16 19:46:44 carl
  1079. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1080. + try to fix temp allocation (still in ifdef)
  1081. + generic constructor calls
  1082. + start of tassembler / tmodulebase class cleanup
  1083. Revision 1.46 2002/05/12 16:53:09 peter
  1084. * moved entry and exitcode to ncgutil and cgobj
  1085. * foreach gets extra argument for passing local data to the
  1086. iterator function
  1087. * -CR checks also class typecasts at runtime by changing them
  1088. into as
  1089. * fixed compiler to cycle with the -CR option
  1090. * fixed stabs with elf writer, finally the global variables can
  1091. be watched
  1092. * removed a lot of routines from cga unit and replaced them by
  1093. calls to cgobj
  1094. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1095. u32bit then the other is typecasted also to u32bit without giving
  1096. a rangecheck warning/error.
  1097. * fixed pascal calling method with reversing also the high tree in
  1098. the parast, detected by tcalcst3 test
  1099. Revision 1.45 2002/04/23 19:16:35 peter
  1100. * add pinline unit that inserts compiler supported functions using
  1101. one or more statements
  1102. * moved finalize and setlength from ninl to pinline
  1103. Revision 1.44 2002/04/20 21:32:24 carl
  1104. + generic FPC_CHECKPOINTER
  1105. + first parameter offset in stack now portable
  1106. * rename some constants
  1107. + move some cpu stuff to other units
  1108. - remove unused constents
  1109. * fix stacksize for some targets
  1110. * fix generic size problems which depend now on EXTEND_SIZE constant
  1111. Revision 1.43 2002/04/15 19:01:53 carl
  1112. + target_info.size_of_pointer -> pointer_Size
  1113. Revision 1.42 2002/04/04 19:06:03 peter
  1114. * removed unused units
  1115. * use tlocation.size in cg.a_*loc*() routines
  1116. Revision 1.41 2002/01/24 18:25:49 peter
  1117. * implicit result variable generation for assembler routines
  1118. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  1119. Revision 1.40 2002/01/06 21:47:32 peter
  1120. * removed getprocvar, use only getprocvardef
  1121. }