ptconst.pas 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  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. type
  51. setbytes = array[0..31] of byte;
  52. Psetbytes = ^setbytes;
  53. var
  54. len,base : longint;
  55. p,hp,hpstart : tnode;
  56. i,j,l,
  57. varalign : longint;
  58. offset,
  59. strlength : aint;
  60. curconstsegment : TAAsmoutput;
  61. ll : tasmlabel;
  62. s,sorg : string;
  63. c : char;
  64. ca : pchar;
  65. tmpguid : tguid;
  66. aktpos : longint;
  67. obj : tobjectdef;
  68. recsym,
  69. srsym : tsym;
  70. symt : tsymtable;
  71. value : bestreal;
  72. intvalue : tconstexprint;
  73. strval : pchar;
  74. pw : pcompilerwidestring;
  75. error : boolean;
  76. old_block_type : tblock_type;
  77. procedure check_range(def:torddef);
  78. begin
  79. if ((tordconstnode(p).value>def.high) or
  80. (tordconstnode(p).value<def.low)) then
  81. begin
  82. if (cs_check_range in aktlocalswitches) then
  83. Message(parser_e_range_check_error)
  84. else
  85. Message(parser_w_range_check_error);
  86. end;
  87. end;
  88. begin
  89. old_block_type:=block_type;
  90. block_type:=bt_const;
  91. if writable then
  92. curconstsegment:=datasegment
  93. else
  94. curconstsegment:=consts;
  95. case t.def.deftype of
  96. orddef:
  97. begin
  98. p:=comp_expr(true);
  99. case torddef(t.def).typ of
  100. bool8bit :
  101. begin
  102. if is_constboolnode(p) then
  103. curconstSegment.concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)))
  104. else
  105. Message(parser_e_illegal_expression);
  106. end;
  107. bool16bit :
  108. begin
  109. if is_constboolnode(p) then
  110. curconstSegment.concat(Tai_const.Create_16bit(word(tordconstnode(p).value)))
  111. else
  112. Message(parser_e_illegal_expression);
  113. end;
  114. bool32bit :
  115. begin
  116. if is_constboolnode(p) then
  117. curconstSegment.concat(Tai_const.Create_32bit(longint(tordconstnode(p).value)))
  118. else
  119. Message(parser_e_illegal_expression);
  120. end;
  121. uchar :
  122. begin
  123. if is_constcharnode(p) then
  124. curconstSegment.concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)))
  125. else
  126. Message(parser_e_illegal_expression);
  127. end;
  128. uwidechar :
  129. begin
  130. if is_constcharnode(p) then
  131. inserttypeconv(p,cwidechartype);
  132. if is_constwidecharnode(p) then
  133. curconstSegment.concat(Tai_const.Create_16bit(word(tordconstnode(p).value)))
  134. else
  135. Message(parser_e_illegal_expression);
  136. end;
  137. s8bit,
  138. u8bit :
  139. begin
  140. if is_constintnode(p) then
  141. begin
  142. curconstSegment.concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)));
  143. check_range(torddef(t.def));
  144. end
  145. else
  146. Message(parser_e_illegal_expression);
  147. end;
  148. u16bit,
  149. s16bit :
  150. begin
  151. if is_constintnode(p) then
  152. begin
  153. curconstSegment.concat(Tai_const.Create_16bit(word(tordconstnode(p).value)));
  154. check_range(torddef(t.def));
  155. end
  156. else
  157. Message(parser_e_illegal_expression);
  158. end;
  159. s32bit,
  160. u32bit :
  161. begin
  162. if is_constintnode(p) then
  163. begin
  164. curconstSegment.concat(Tai_const.Create_32bit(longint(tordconstnode(p).value)));
  165. if torddef(t.def).typ<>u32bit then
  166. check_range(torddef(t.def));
  167. end
  168. else
  169. Message(parser_e_illegal_expression);
  170. end;
  171. s64bit,
  172. u64bit,
  173. scurrency:
  174. begin
  175. if is_constintnode(p) then
  176. intvalue := tordconstnode(p).value
  177. else if is_constrealnode(p) and
  178. (torddef(t.def).typ=scurrency)
  179. { allow bootstrapping }
  180. {$ifdef VER1_0}
  181. and (trealconstnode(p).value_real*10000 >= low(int64)) and
  182. (trealconstnode(p).value_real*10000 <= high(int64))
  183. {$endif VER1_0}
  184. then
  185. begin
  186. {$ifdef VER1_0}
  187. { only trunc is 64 bit in 1.0.x so use trunc here to allow bootstrapping }
  188. intvalue:=trunc(trealconstnode(p).value_real*10000);
  189. {$else VER1_0}
  190. intvalue:=round(trealconstnode(p).value_real*10000);
  191. {$endif VER1_0}
  192. end
  193. else
  194. begin
  195. intvalue:=0;
  196. Message(parser_e_illegal_expression);
  197. end;
  198. curconstSegment.concat(Tai_const.Create_64bit(intvalue));
  199. end;
  200. else
  201. internalerror(3799);
  202. end;
  203. p.free;
  204. end;
  205. floatdef:
  206. begin
  207. p:=comp_expr(true);
  208. if is_constrealnode(p) then
  209. value:=trealconstnode(p).value_real
  210. else if is_constintnode(p) then
  211. value:=tordconstnode(p).value
  212. else
  213. Message(parser_e_illegal_expression);
  214. case tfloatdef(t.def).typ of
  215. s32real :
  216. curconstSegment.concat(Tai_real_32bit.Create(ts32real(value)));
  217. s64real :
  218. {$ifdef ARM}
  219. if aktfputype in [fpu_fpa,fpu_fpa10,fpu_fpa11] then
  220. curconstSegment.concat(Tai_real_64bit.Create_hiloswapped(ts64real(value)))
  221. else
  222. {$endif ARM}
  223. curconstSegment.concat(Tai_real_64bit.Create(ts64real(value)));
  224. s80real :
  225. curconstSegment.concat(Tai_real_80bit.Create(value));
  226. {$ifdef ver1_0}
  227. s64comp :
  228. curconstSegment.concat(Tai_comp_64bit.Create(value));
  229. s64currency:
  230. curconstSegment.concat(Tai_comp_64bit.Create(value*10000));
  231. {$else ver1_0}
  232. { the round is necessary for native compilers where comp isn't a float }
  233. s64comp :
  234. curconstSegment.concat(Tai_comp_64bit.Create(round(value)));
  235. s64currency:
  236. curconstSegment.concat(Tai_comp_64bit.Create(round(value*10000)));
  237. {$endif ver1_0}
  238. s128real:
  239. curconstSegment.concat(Tai_real_128bit.Create(value));
  240. else
  241. internalerror(18);
  242. end;
  243. p.free;
  244. end;
  245. classrefdef:
  246. begin
  247. p:=comp_expr(true);
  248. case p.nodetype of
  249. loadvmtaddrn:
  250. with Tclassrefdef(p.resulttype.def) do
  251. begin
  252. if not Tobjectdef(pointertype.def).is_related(Tobjectdef(pointertype.def)) then
  253. message(parser_e_illegal_expression);
  254. curconstSegment.concat(Tai_const.Create_sym(objectlibrary.newasmsymbol(
  255. Tobjectdef(pointertype.def).vmt_mangledname,AB_EXTERNAL,AT_DATA)));
  256. end;
  257. niln:
  258. curconstSegment.concat(Tai_const.Create_sym(nil));
  259. else Message(parser_e_illegal_expression);
  260. end;
  261. p.free;
  262. end;
  263. pointerdef:
  264. begin
  265. p:=comp_expr(true);
  266. if (p.nodetype=typeconvn) then
  267. with Ttypeconvnode(p) do
  268. if (left.nodetype in [addrn,niln]) and equal_defs(t.def,p.resulttype.def) then
  269. begin
  270. hp:=left;
  271. left:=nil;
  272. p.free;
  273. p:=hp;
  274. end;
  275. { allows horrible ofs(typeof(TButton)^) code !! }
  276. if (p.nodetype=addrn) then
  277. with Taddrnode(p) do
  278. if left.nodetype=derefn then
  279. begin
  280. hp:=tderefnode(left).left;
  281. tderefnode(left).left:=nil;
  282. p.free;
  283. p:=hp;
  284. end;
  285. { const pointer ? }
  286. if (p.nodetype = pointerconstn) then
  287. begin
  288. if sizeof(TConstPtrUInt)=8 then
  289. curconstsegment.concat(Tai_const.Create_64bit(TConstPtrUInt(tpointerconstnode(p).value)))
  290. else
  291. if sizeof(TConstPtrUInt)=4 then
  292. curconstsegment.concat(Tai_const.Create_32bit(TConstPtrUInt(tpointerconstnode(p).value)))
  293. else
  294. internalerror(200404122);
  295. end
  296. { nil pointer ? }
  297. else if p.nodetype=niln then
  298. curconstSegment.concat(Tai_const.Create_sym(nil))
  299. { maybe pchar ? }
  300. else
  301. if is_char(tpointerdef(t.def).pointertype.def) and
  302. (p.nodetype<>addrn) then
  303. begin
  304. objectlibrary.getdatalabel(ll);
  305. curconstSegment.concat(Tai_const.Create_sym(ll));
  306. if p.nodetype=stringconstn then
  307. varalign:=tstringconstnode(p).len
  308. else
  309. varalign:=0;
  310. varalign:=const_align(varalign);
  311. Consts.concat(Tai_align.Create(varalign));
  312. Consts.concat(Tai_label.Create(ll));
  313. if p.nodetype=stringconstn then
  314. begin
  315. len:=tstringconstnode(p).len;
  316. { For tp7 the maximum lentgh can be 255 }
  317. if (m_tp7 in aktmodeswitches) and
  318. (len>255) then
  319. len:=255;
  320. getmem(ca,len+2);
  321. move(tstringconstnode(p).value_str^,ca^,len+1);
  322. Consts.concat(Tai_string.Create_length_pchar(ca,len+1));
  323. end
  324. else
  325. if is_constcharnode(p) then
  326. Consts.concat(Tai_string.Create(char(byte(tordconstnode(p).value))+#0))
  327. else
  328. Message(parser_e_illegal_expression);
  329. end
  330. { maybe pwidechar ? }
  331. else
  332. if is_widechar(tpointerdef(t.def).pointertype.def) and
  333. (p.nodetype<>addrn) then
  334. begin
  335. objectlibrary.getdatalabel(ll);
  336. curconstSegment.concat(Tai_const.Create_sym(ll));
  337. Consts.concat(tai_align.create(const_align(sizeof(aint))));
  338. Consts.concat(Tai_label.Create(ll));
  339. if (p.nodetype in [stringconstn,ordconstn]) then
  340. begin
  341. { convert to widestring stringconstn }
  342. inserttypeconv(p,cwidestringtype);
  343. if (p.nodetype=stringconstn) and
  344. (tstringconstnode(p).st_type=st_widestring) then
  345. begin
  346. pw:=pcompilerwidestring(tstringconstnode(p).value_str);
  347. for i:=0 to tstringconstnode(p).len-1 do
  348. Consts.concat(Tai_const.Create_16bit(pw^.data[i]));
  349. { ending #0 }
  350. Consts.concat(Tai_const.Create_16bit(0))
  351. end;
  352. end
  353. else
  354. Message(parser_e_illegal_expression);
  355. end
  356. else
  357. if p.nodetype=addrn then
  358. begin
  359. { support @@procvar in tp mode }
  360. if (m_tp_procvar in aktmodeswitches) and
  361. (taddrnode(p).left.nodetype=addrn) then
  362. p:=taddrnode(p).left;
  363. { insert typeconv }
  364. inserttypeconv(p,t);
  365. { if a typeconv node was inserted then check if it was an tc_equal. If
  366. true then we remove the node. If not tc_equal then we leave the typeconvn
  367. and the nodetype=loadn will always be false and generate the error (PFV) }
  368. if (p.nodetype=typeconvn) then
  369. begin
  370. if (ttypeconvnode(p).convtype=tc_equal) then
  371. hpstart:=taddrnode(ttypeconvnode(p).left).left
  372. else
  373. hpstart:=p;
  374. end
  375. else
  376. hpstart:=taddrnode(p).left;
  377. hp:=hpstart;
  378. while assigned(hp) and (hp.nodetype in [subscriptn,vecn]) do
  379. hp:=tunarynode(hp).left;
  380. if (hp.nodetype=loadn) then
  381. begin
  382. hp:=hpstart;
  383. offset:=0;
  384. while assigned(hp) and (hp.nodetype<>loadn) do
  385. begin
  386. case hp.nodetype of
  387. vecn :
  388. begin
  389. case tvecnode(hp).left.resulttype.def.deftype of
  390. stringdef :
  391. begin
  392. { this seems OK for shortstring and ansistrings PM }
  393. { it is wrong for widestrings !! }
  394. len:=1;
  395. base:=0;
  396. end;
  397. arraydef :
  398. begin
  399. len:=tarraydef(tvecnode(hp).left.resulttype.def).elesize;
  400. base:=tarraydef(tvecnode(hp).left.resulttype.def).lowrange;
  401. end
  402. else
  403. Message(parser_e_illegal_expression);
  404. end;
  405. if is_constintnode(tvecnode(hp).right) then
  406. inc(offset,len*(get_ordinal_value(tvecnode(hp).right)-base))
  407. else
  408. Message(parser_e_illegal_expression);
  409. end;
  410. subscriptn :
  411. inc(offset,tsubscriptnode(hp).vs.fieldoffset)
  412. else
  413. Message(parser_e_illegal_expression);
  414. end;
  415. hp:=tbinarynode(hp).left;
  416. end;
  417. srsym:=tloadnode(hp).symtableentry;
  418. case srsym.typ of
  419. procsym :
  420. begin
  421. if Tprocsym(srsym).procdef_count>1 then
  422. Message(parser_e_no_overloaded_procvars);
  423. if po_abstractmethod in tprocsym(srsym).first_procdef.procoptions then
  424. Message(type_e_cant_take_address_of_abstract_method)
  425. else
  426. curconstSegment.concat(Tai_const.Createname(tprocsym(srsym).first_procdef.mangledname,AT_FUNCTION,offset));
  427. end;
  428. varsym :
  429. curconstSegment.concat(Tai_const.Createname(tvarsym(srsym).mangledname,AT_DATA,offset));
  430. typedconstsym :
  431. curconstSegment.concat(Tai_const.Createname(ttypedconstsym(srsym).mangledname,AT_DATA,offset));
  432. else
  433. Message(type_e_variable_id_expected);
  434. end;
  435. end
  436. else
  437. Message(parser_e_illegal_expression);
  438. end
  439. else
  440. { allow typeof(Object type)}
  441. if (p.nodetype=inlinen) and
  442. (tinlinenode(p).inlinenumber=in_typeof_x) then
  443. begin
  444. if (tinlinenode(p).left.nodetype=typen) then
  445. begin
  446. curconstSegment.concat(Tai_const.createname(
  447. tobjectdef(tinlinenode(p).left.resulttype.def).vmt_mangledname,AT_DATA,0));
  448. end
  449. else
  450. Message(parser_e_illegal_expression);
  451. end
  452. else
  453. Message(parser_e_illegal_expression);
  454. p.free;
  455. end;
  456. setdef:
  457. begin
  458. p:=comp_expr(true);
  459. if p.nodetype=setconstn then
  460. begin
  461. { be sure to convert to the correct result, else
  462. it can generate smallset data instead of normalset (PFV) }
  463. inserttypeconv(p,t);
  464. { we only allow const sets }
  465. if assigned(tsetconstnode(p).left) then
  466. Message(parser_e_illegal_expression)
  467. else
  468. begin
  469. { this writing is endian independant }
  470. { untrue - because they are considered }
  471. { arrays of 32-bit values CEC }
  472. if source_info.endian = target_info.endian then
  473. begin
  474. for l:=0 to p.resulttype.def.size-1 do
  475. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[l]));
  476. end
  477. else
  478. begin
  479. { store as longint values in swaped format }
  480. j:=0;
  481. for l:=0 to ((p.resulttype.def.size-1) div 4) do
  482. begin
  483. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+3]));
  484. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+2]));
  485. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+1]));
  486. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j]));
  487. Inc(j,4);
  488. end;
  489. end;
  490. end;
  491. end
  492. else
  493. Message(parser_e_illegal_expression);
  494. p.free;
  495. end;
  496. enumdef:
  497. begin
  498. p:=comp_expr(true);
  499. if p.nodetype=ordconstn then
  500. begin
  501. if equal_defs(p.resulttype.def,t.def) or
  502. is_subequal(p.resulttype.def,t.def) then
  503. begin
  504. case p.resulttype.def.size of
  505. 1 : curconstSegment.concat(Tai_const.Create_8bit(Byte(tordconstnode(p).value)));
  506. 2 : curconstSegment.concat(Tai_const.Create_16bit(Word(tordconstnode(p).value)));
  507. 4 : curconstSegment.concat(Tai_const.Create_32bit(Longint(tordconstnode(p).value)));
  508. end;
  509. end
  510. else
  511. IncompatibleTypes(p.resulttype.def,t.def);
  512. end
  513. else
  514. Message(parser_e_illegal_expression);
  515. p.free;
  516. end;
  517. stringdef:
  518. begin
  519. p:=comp_expr(true);
  520. { load strval and strlength of the constant tree }
  521. if (p.nodetype=stringconstn) or is_widestring(t.def) then
  522. begin
  523. { convert to the expected string type so that
  524. for widestrings strval is a pcompilerwidestring }
  525. inserttypeconv(p,t);
  526. strlength:=tstringconstnode(p).len;
  527. strval:=tstringconstnode(p).value_str;
  528. end
  529. else if is_constcharnode(p) then
  530. begin
  531. { strval:=pchar(@tordconstnode(p).value);
  532. THIS FAIL on BIG_ENDIAN MACHINES PM }
  533. c:=chr(tordconstnode(p).value and $ff);
  534. strval:=@c;
  535. strlength:=1
  536. end
  537. else if is_constresourcestringnode(p) then
  538. begin
  539. strval:=pchar(tconstsym(tloadnode(p).symtableentry).value.valueptr);
  540. strlength:=tconstsym(tloadnode(p).symtableentry).value.len;
  541. end
  542. else
  543. begin
  544. Message(parser_e_illegal_expression);
  545. strlength:=-1;
  546. end;
  547. if strlength>=0 then
  548. begin
  549. case tstringdef(t.def).string_typ of
  550. st_shortstring:
  551. begin
  552. if strlength>=t.def.size then
  553. begin
  554. message2(parser_w_string_too_long,strpas(strval),tostr(t.def.size-1));
  555. strlength:=t.def.size-1;
  556. end;
  557. curconstSegment.concat(Tai_const.Create_8bit(strlength));
  558. { this can also handle longer strings }
  559. getmem(ca,strlength+1);
  560. move(strval^,ca^,strlength);
  561. ca[strlength]:=#0;
  562. curconstSegment.concat(Tai_string.Create_length_pchar(ca,strlength));
  563. { fillup with spaces if size is shorter }
  564. if t.def.size>strlength then
  565. begin
  566. getmem(ca,t.def.size-strlength);
  567. { def.size contains also the leading length, so we }
  568. { we have to subtract one }
  569. fillchar(ca[0],t.def.size-strlength-1,' ');
  570. ca[t.def.size-strlength-1]:=#0;
  571. { this can also handle longer strings }
  572. curconstSegment.concat(Tai_string.Create_length_pchar(ca,t.def.size-strlength-1));
  573. end;
  574. end;
  575. {$ifdef ansistrings_bits}
  576. st_ansistring16:
  577. begin
  578. { an empty ansi string is nil! }
  579. if (strlength=0) then
  580. curconstSegment.concat(Tai_const.Create_ptr(0))
  581. else
  582. begin
  583. objectlibrary.getdatalabel(ll);
  584. curconstSegment.concat(Tai_const_symbol.Create(ll));
  585. { the actual structure starts at -12 from start label - CEC }
  586. Consts.concat(tai_align.create(const_align(pointer_size)));
  587. { first write the maximum size }
  588. Consts.concat(Tai_const.Create_16bit(strlength));
  589. { second write the real length }
  590. Consts.concat(Tai_const.Create_16bit(strlength));
  591. { redondent with maxlength but who knows ... (PM) }
  592. { third write use count (set to -1 for safety ) }
  593. Consts.concat(Tai_const.Create_16bit(-1));
  594. Consts.concat(Tai_label.Create(ll));
  595. getmem(ca,strlength+2);
  596. move(strval^,ca^,strlength);
  597. { The terminating #0 to be stored in the .data section (JM) }
  598. ca[strlength]:=#0;
  599. { End of the PChar. The memory has to be allocated because in }
  600. { tai_string.done, there is a freemem(len+1) (JM) }
  601. ca[strlength+1]:=#0;
  602. Consts.concat(Tai_string.Create_length_pchar(ca,strlength+1));
  603. end;
  604. end;
  605. {$endif}
  606. {$ifdef ansistring_bits}st_ansistring32{$else}st_ansistring{$endif}:
  607. begin
  608. { an empty ansi string is nil! }
  609. if (strlength=0) then
  610. curconstSegment.concat(Tai_const.Create_sym(nil))
  611. else
  612. begin
  613. objectlibrary.getdatalabel(ll);
  614. curconstSegment.concat(Tai_const.Create_sym(ll));
  615. { the actual structure starts at -12 from start label - CEC }
  616. Consts.concat(tai_align.create(const_align(sizeof(aint))));
  617. { first write the maximum size }
  618. Consts.concat(Tai_const.Create_aint(strlength));
  619. { second write the real length }
  620. Consts.concat(Tai_const.Create_aint(strlength));
  621. { redondent with maxlength but who knows ... (PM) }
  622. { third write use count (set to -1 for safety ) }
  623. Consts.concat(Tai_const.Create_aint(-1));
  624. Consts.concat(Tai_label.Create(ll));
  625. getmem(ca,strlength+2);
  626. move(strval^,ca^,strlength);
  627. { The terminating #0 to be stored in the .data section (JM) }
  628. ca[strlength]:=#0;
  629. { End of the PChar. The memory has to be allocated because in }
  630. { tai_string.done, there is a freemem(len+1) (JM) }
  631. ca[strlength+1]:=#0;
  632. Consts.concat(Tai_string.Create_length_pchar(ca,strlength+1));
  633. end;
  634. end;
  635. {$ifdef ansistring_bits}
  636. st_ansistring64:
  637. begin
  638. { an empty ansi string is nil! }
  639. if (strlength=0) then
  640. curconstSegment.concat(Tai_const.Create_ptr(0))
  641. else
  642. begin
  643. objectlibrary.getdatalabel(ll);
  644. curconstSegment.concat(Tai_const_symbol.Create(ll));
  645. { the actual structure starts at -12 from start label - CEC }
  646. Consts.concat(tai_align.create(const_align(pointer_size)));
  647. { first write the maximum size }
  648. Consts.concat(Tai_const.Create_64bit(strlength));
  649. { second write the real length }
  650. Consts.concat(Tai_const.Create_64bit(strlength));
  651. { redondent with maxlength but who knows ... (PM) }
  652. { third write use count (set to -1 for safety ) }
  653. Consts.concat(Tai_const.Create_64bit(-1));
  654. Consts.concat(Tai_label.Create(ll));
  655. getmem(ca,strlength+2);
  656. move(strval^,ca^,strlength);
  657. { The terminating #0 to be stored in the .data section (JM) }
  658. ca[strlength]:=#0;
  659. { End of the PChar. The memory has to be allocated because in }
  660. { tai_string.done, there is a freemem(len+1) (JM) }
  661. ca[strlength+1]:=#0;
  662. Consts.concat(Tai_string.Create_length_pchar(ca,strlength+1));
  663. end;
  664. end;
  665. {$endif}
  666. st_widestring:
  667. begin
  668. { an empty ansi string is nil! }
  669. if (strlength=0) then
  670. curconstSegment.concat(Tai_const.Create_sym(nil))
  671. else
  672. begin
  673. objectlibrary.getdatalabel(ll);
  674. curconstSegment.concat(Tai_const.Create_sym(ll));
  675. { the actual structure starts at -12 from start label - CEC }
  676. Consts.concat(tai_align.create(const_align(sizeof(aint))));
  677. Consts.concat(Tai_const.Create_aint(strlength));
  678. Consts.concat(Tai_const.Create_aint(strlength));
  679. Consts.concat(Tai_const.Create_aint(-1));
  680. Consts.concat(Tai_label.Create(ll));
  681. for i:=0 to strlength-1 do
  682. Consts.concat(Tai_const.Create_16bit(pcompilerwidestring(strval)^.data[i]));
  683. { ending #0 }
  684. Consts.concat(Tai_const.Create_16bit(0))
  685. end;
  686. end;
  687. st_longstring:
  688. begin
  689. internalerror(200107081);
  690. {curconstSegment.concat(Tai_const.Create_32bit(strlength))));
  691. curconstSegment.concat(Tai_const.Create_8bit(0));
  692. getmem(ca,strlength+1);
  693. move(strval^,ca^,strlength);
  694. ca[strlength]:=#0;
  695. generate_pascii(consts,ca,strlength);
  696. curconstSegment.concat(Tai_const.Create_8bit(0));}
  697. end;
  698. end;
  699. end;
  700. p.free;
  701. end;
  702. arraydef:
  703. begin
  704. if try_to_consume(_LKLAMMER) then
  705. begin
  706. for l:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange-1 do
  707. begin
  708. readtypedconst(tarraydef(t.def).elementtype,nil,writable);
  709. consume(_COMMA);
  710. end;
  711. readtypedconst(tarraydef(t.def).elementtype,nil,writable);
  712. consume(_RKLAMMER);
  713. end
  714. else
  715. { if array of char then we allow also a string }
  716. if is_char(tarraydef(t.def).elementtype.def) then
  717. begin
  718. p:=comp_expr(true);
  719. if p.nodetype=stringconstn then
  720. begin
  721. len:=tstringconstnode(p).len;
  722. { For tp7 the maximum lentgh can be 255 }
  723. if (m_tp7 in aktmodeswitches) and
  724. (len>255) then
  725. len:=255;
  726. ca:=tstringconstnode(p).value_str;
  727. end
  728. else
  729. if is_constcharnode(p) then
  730. begin
  731. c:=chr(tordconstnode(p).value and $ff);
  732. ca:=@c;
  733. len:=1;
  734. end
  735. else
  736. begin
  737. Message(parser_e_illegal_expression);
  738. len:=0;
  739. end;
  740. if len>(tarraydef(t.def).highrange-tarraydef(t.def).lowrange+1) then
  741. Message(parser_e_string_larger_array);
  742. for i:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange do
  743. begin
  744. if i+1-tarraydef(t.def).lowrange<=len then
  745. begin
  746. curconstSegment.concat(Tai_const.Create_8bit(byte(ca^)));
  747. inc(ca);
  748. end
  749. else
  750. {Fill the remaining positions with #0.}
  751. curconstSegment.concat(Tai_const.Create_8bit(0));
  752. end;
  753. p.free;
  754. end
  755. else
  756. { dynamic array nil }
  757. if is_dynamic_array(t.def) then
  758. begin
  759. { Only allow nil initialization }
  760. consume(_NIL);
  761. curconstSegment.concat(Tai_const.Create_sym(nil));
  762. end
  763. else
  764. begin
  765. { we want the ( }
  766. consume(_LKLAMMER);
  767. end;
  768. end;
  769. procvardef:
  770. begin
  771. { Procvars and pointers are no longer compatible. }
  772. { under tp: =nil or =var under fpc: =nil or =@var }
  773. if token=_NIL then
  774. begin
  775. curconstSegment.concat(Tai_const.Create_sym(nil));
  776. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  777. curconstSegment.concat(Tai_const.Create_sym(nil));
  778. consume(_NIL);
  779. exit;
  780. end;
  781. { you can't assign a value other than NIL to a typed constant }
  782. { which is a "procedure of object", because this also requires }
  783. { address of an object/class instance, which is not known at }
  784. { compile time (JM) }
  785. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  786. Message(parser_e_no_procvarobj_const);
  787. { parse the rest too, so we can continue with error checking }
  788. getprocvardef:=tprocvardef(t.def);
  789. p:=comp_expr(true);
  790. getprocvardef:=nil;
  791. if codegenerror then
  792. begin
  793. p.free;
  794. exit;
  795. end;
  796. { let type conversion check everything needed }
  797. inserttypeconv(p,t);
  798. if codegenerror then
  799. begin
  800. p.free;
  801. exit;
  802. end;
  803. { remove typeconvn, that will normally insert a lea
  804. instruction which is not necessary for us }
  805. if p.nodetype=typeconvn then
  806. begin
  807. hp:=ttypeconvnode(p).left;
  808. ttypeconvnode(p).left:=nil;
  809. p.free;
  810. p:=hp;
  811. end;
  812. { remove addrn which we also don't need here }
  813. if p.nodetype=addrn then
  814. begin
  815. hp:=taddrnode(p).left;
  816. taddrnode(p).left:=nil;
  817. p.free;
  818. p:=hp;
  819. end;
  820. { we now need to have a loadn with a procsym }
  821. if (p.nodetype=loadn) and
  822. (tloadnode(p).symtableentry.typ=procsym) then
  823. begin
  824. curconstSegment.concat(Tai_const.createname(
  825. tprocsym(tloadnode(p).symtableentry).first_procdef.mangledname,AT_FUNCTION,0));
  826. end
  827. else
  828. Message(parser_e_illegal_expression);
  829. p.free;
  830. end;
  831. { reads a typed constant record }
  832. recorddef:
  833. begin
  834. { KAZ }
  835. if (trecorddef(t.def)=rec_tguid) and
  836. ((token=_CSTRING) or (token=_CCHAR) or (token=_ID)) then
  837. begin
  838. p:=comp_expr(true);
  839. inserttypeconv(p,cshortstringtype);
  840. if p.nodetype=stringconstn then
  841. begin
  842. s:=strpas(tstringconstnode(p).value_str);
  843. p.free;
  844. if string2guid(s,tmpguid) then
  845. begin
  846. curconstSegment.concat(Tai_const.Create_32bit(tmpguid.D1));
  847. curconstSegment.concat(Tai_const.Create_16bit(tmpguid.D2));
  848. curconstSegment.concat(Tai_const.Create_16bit(tmpguid.D3));
  849. for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
  850. curconstSegment.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
  851. end
  852. else
  853. Message(parser_e_improper_guid_syntax);
  854. end
  855. else
  856. begin
  857. p.free;
  858. Message(parser_e_illegal_expression);
  859. exit;
  860. end;
  861. end
  862. else
  863. begin
  864. consume(_LKLAMMER);
  865. sorg:='';
  866. aktpos:=0;
  867. srsym := tsym(trecorddef(t.def).symtable.symindex.first);
  868. recsym := nil;
  869. while token<>_RKLAMMER do
  870. begin
  871. s:=pattern;
  872. sorg:=orgpattern;
  873. consume(_ID);
  874. consume(_COLON);
  875. error := false;
  876. recsym := tsym(trecorddef(t.def).symtable.search(s));
  877. if not assigned(recsym) then
  878. begin
  879. Message1(sym_e_illegal_field,sorg);
  880. error := true;
  881. end;
  882. if (not error) and
  883. (not assigned(srsym) or
  884. (s <> srsym.name)) then
  885. { possible variant record (JM) }
  886. begin
  887. { All parts of a variant start at the same offset }
  888. { Also allow jumping from one variant part to another, }
  889. { as long as the offsets match }
  890. if (assigned(srsym) and
  891. (tvarsym(recsym).fieldoffset = tvarsym(srsym).fieldoffset)) or
  892. { srsym is not assigned after parsing w2 in the }
  893. { typed const in the next example: }
  894. { type tr = record case byte of }
  895. { 1: (l1,l2: dword); }
  896. { 2: (w1,w2: word); }
  897. { end; }
  898. { const r: tr = (w1:1;w2:1;l2:5); }
  899. (tvarsym(recsym).fieldoffset = aktpos) then
  900. srsym := recsym
  901. { going backwards isn't allowed in any mode }
  902. else if (tvarsym(recsym).fieldoffset<aktpos) then
  903. begin
  904. Message(parser_e_invalid_record_const);
  905. error := true;
  906. end
  907. { Delphi allows you to skip fields }
  908. else if (m_delphi in aktmodeswitches) then
  909. begin
  910. Message1(parser_w_skipped_fields_before,sorg);
  911. srsym := recsym;
  912. end
  913. { FPC and TP don't }
  914. else
  915. begin
  916. Message1(parser_e_skipped_fields_before,sorg);
  917. error := true;
  918. end;
  919. end;
  920. if error then
  921. consume_all_until(_SEMICOLON)
  922. else
  923. begin
  924. { if needed fill (alignment) }
  925. if tvarsym(srsym).fieldoffset>aktpos then
  926. for i:=1 to tvarsym(srsym).fieldoffset-aktpos do
  927. curconstSegment.concat(Tai_const.Create_8bit(0));
  928. { new position }
  929. aktpos:=tvarsym(srsym).fieldoffset+tvarsym(srsym).vartype.def.size;
  930. { read the data }
  931. readtypedconst(tvarsym(srsym).vartype,nil,writable);
  932. { keep previous field for checking whether whole }
  933. { record was initialized (JM) }
  934. recsym := srsym;
  935. { goto next field }
  936. srsym := tsym(srsym.indexnext);
  937. if token=_SEMICOLON then
  938. consume(_SEMICOLON)
  939. else break;
  940. end;
  941. end;
  942. { are there any fields left? }
  943. if assigned(srsym) and
  944. { don't complain if there only come other variant parts }
  945. { after the last initialized field }
  946. ((recsym=nil) or
  947. (tvarsym(srsym).fieldoffset > tvarsym(recsym).fieldoffset)) then
  948. Message1(parser_w_skipped_fields_after,sorg);
  949. for i:=1 to t.def.size-aktpos do
  950. curconstSegment.concat(Tai_const.Create_8bit(0));
  951. consume(_RKLAMMER);
  952. end;
  953. end;
  954. { reads a typed object }
  955. objectdef:
  956. begin
  957. if is_class_or_interface(t.def) then
  958. begin
  959. p:=comp_expr(true);
  960. if p.nodetype<>niln then
  961. begin
  962. Message(parser_e_type_const_not_possible);
  963. consume_all_until(_RKLAMMER);
  964. end
  965. else
  966. begin
  967. curconstSegment.concat(Tai_const.Create_sym(nil));
  968. end;
  969. p.free;
  970. end
  971. { for objects we allow it only if it doesn't contain a vmt }
  972. else if (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  973. (m_fpc in aktmodeswitches) then
  974. Message(parser_e_type_const_not_possible)
  975. else
  976. begin
  977. consume(_LKLAMMER);
  978. aktpos:=0;
  979. while token<>_RKLAMMER do
  980. begin
  981. s:=pattern;
  982. sorg:=orgpattern;
  983. consume(_ID);
  984. consume(_COLON);
  985. srsym:=nil;
  986. obj:=tobjectdef(t.def);
  987. symt:=obj.symtable;
  988. while (srsym=nil) and assigned(symt) do
  989. begin
  990. srsym:=tsym(symt.search(s));
  991. if assigned(obj) then
  992. obj:=obj.childof;
  993. if assigned(obj) then
  994. symt:=obj.symtable
  995. else
  996. symt:=nil;
  997. end;
  998. if srsym=nil then
  999. begin
  1000. Message1(sym_e_id_not_found,sorg);
  1001. consume_all_until(_SEMICOLON);
  1002. end
  1003. else
  1004. with Tvarsym(srsym) do
  1005. begin
  1006. { check position }
  1007. if fieldoffset<aktpos then
  1008. message(parser_e_invalid_record_const);
  1009. { check in VMT needs to be added for TP mode }
  1010. with Tobjectdef(t.def) do
  1011. if not(m_fpc in aktmodeswitches) and
  1012. (oo_has_vmt in objectoptions) and
  1013. (vmt_offset<fieldoffset) then
  1014. begin
  1015. for i:=1 to vmt_offset-aktpos do
  1016. curconstsegment.concat(tai_const.create_8bit(0));
  1017. curconstsegment.concat(tai_const.createname(vmt_mangledname,AT_DATA,0));
  1018. { this is more general }
  1019. aktpos:=vmt_offset + sizeof(aint);
  1020. end;
  1021. { if needed fill }
  1022. if fieldoffset>aktpos then
  1023. for i:=1 to fieldoffset-aktpos do
  1024. curconstSegment.concat(Tai_const.Create_8bit(0));
  1025. { new position }
  1026. aktpos:=fieldoffset+vartype.def.size;
  1027. { read the data }
  1028. readtypedconst(vartype,nil,writable);
  1029. if token=_SEMICOLON then
  1030. consume(_SEMICOLON)
  1031. else break;
  1032. end;
  1033. end;
  1034. if not(m_fpc in aktmodeswitches) and
  1035. (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  1036. (tobjectdef(t.def).vmt_offset>=aktpos) then
  1037. begin
  1038. for i:=1 to tobjectdef(t.def).vmt_offset-aktpos do
  1039. curconstsegment.concat(tai_const.create_8bit(0));
  1040. curconstsegment.concat(tai_const.createname(tobjectdef(t.def).vmt_mangledname,AT_DATA,0));
  1041. { this is more general }
  1042. aktpos:=tobjectdef(t.def).vmt_offset + sizeof(aint);
  1043. end;
  1044. for i:=1 to t.def.size-aktpos do
  1045. curconstSegment.concat(Tai_const.Create_8bit(0));
  1046. consume(_RKLAMMER);
  1047. end;
  1048. end;
  1049. errordef:
  1050. begin
  1051. { try to consume something useful }
  1052. if token=_LKLAMMER then
  1053. consume_all_until(_RKLAMMER)
  1054. else
  1055. consume_all_until(_SEMICOLON);
  1056. end;
  1057. else Message(parser_e_type_const_not_possible);
  1058. end;
  1059. block_type:=old_block_type;
  1060. end;
  1061. {$ifdef fpc}
  1062. {$maxfpuregisters default}
  1063. {$endif fpc}
  1064. end.
  1065. {
  1066. $Log$
  1067. Revision 1.89 2004-06-20 20:41:47 florian
  1068. * fixed bootstrapping problems
  1069. Revision 1.88 2004/06/20 08:55:30 florian
  1070. * logs truncated
  1071. Revision 1.87 2004/06/18 15:16:46 peter
  1072. * remove obsolete cardinal() typecasts
  1073. Revision 1.86 2004/06/16 20:07:09 florian
  1074. * dwarf branch merged
  1075. Revision 1.85 2004/05/23 15:23:30 peter
  1076. * fixed qword(longint) that removed sign from the number
  1077. * removed code in the compiler that relied on wrong qword(longint)
  1078. code generation
  1079. Revision 1.84 2004/04/29 19:56:37 daniel
  1080. * Prepare compiler infrastructure for multiple ansistring types
  1081. Revision 1.83 2004/04/11 10:44:23 peter
  1082. * block_type is bt_const when parsing typed consts
  1083. }