ptconst.pas 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Reads typed constants
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ptconst;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses symtype,symsym,aasmdata;
  21. { this procedure reads typed constants }
  22. { sym is only needed for ansi strings }
  23. { the assembler label is in the middle (PM) }
  24. procedure readtypedconst(list:tasmlist;const t:ttype;sym : ttypedconstsym;writable : boolean);
  25. implementation
  26. uses
  27. strings,
  28. globtype,systems,tokens,verbose,
  29. cutils,globals,widestr,scanner,
  30. symconst,symbase,symdef,symtable,
  31. aasmbase,aasmtai,aasmcpu,defutil,defcmp,
  32. { pass 1 }
  33. node,htypechk,procinfo,
  34. nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  35. { parser specific stuff }
  36. pbase,pexpr,
  37. { codegen }
  38. cpuinfo,cgbase,dbgbase
  39. ;
  40. {$ifdef fpc}
  41. {$maxfpuregisters 0}
  42. {$endif fpc}
  43. { this procedure reads typed constants }
  44. procedure readtypedconst(list:tasmlist;const t:ttype;sym : ttypedconstsym;writable : boolean);
  45. label
  46. myexit;
  47. type
  48. setbytes = array[0..31] of byte;
  49. Psetbytes = ^setbytes;
  50. var
  51. len,base : longint;
  52. p,hp : tnode;
  53. i,j,l : longint;
  54. varalign : shortint;
  55. offset,
  56. strlength : aint;
  57. ll : tasmlabel;
  58. c_name,
  59. s,sorg : string;
  60. c : char;
  61. ca : pchar;
  62. tmpguid : tguid;
  63. aktpos : longint;
  64. obj : tobjectdef;
  65. recsym,
  66. srsym : tsym;
  67. symt : tsymtable;
  68. value : bestreal;
  69. intvalue : tconstexprint;
  70. strval : pchar;
  71. pw : pcompilerwidestring;
  72. error : boolean;
  73. old_block_type : tblock_type;
  74. storefilepos : tfileposinfo;
  75. cursectype : TAsmSectiontype;
  76. datalist : tasmlist;
  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. datalist:=tasmlist.create;
  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. datalist.concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)))
  101. else
  102. Message(parser_e_illegal_expression);
  103. end;
  104. bool16bit :
  105. begin
  106. if is_constboolnode(p) then
  107. datalist.concat(Tai_const.Create_16bit(word(tordconstnode(p).value)))
  108. else
  109. Message(parser_e_illegal_expression);
  110. end;
  111. bool32bit :
  112. begin
  113. if is_constboolnode(p) then
  114. datalist.concat(Tai_const.Create_32bit(longint(tordconstnode(p).value)))
  115. else
  116. Message(parser_e_illegal_expression);
  117. end;
  118. uchar :
  119. begin
  120. if is_constcharnode(p) then
  121. datalist.concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)))
  122. else
  123. Message(parser_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. datalist.concat(Tai_const.Create_16bit(word(tordconstnode(p).value)))
  131. else
  132. Message(parser_e_illegal_expression);
  133. end;
  134. s8bit,
  135. u8bit :
  136. begin
  137. if is_constintnode(p) then
  138. begin
  139. datalist.concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)));
  140. check_range(torddef(t.def));
  141. end
  142. else
  143. Message(parser_e_illegal_expression);
  144. end;
  145. u16bit,
  146. s16bit :
  147. begin
  148. if is_constintnode(p) then
  149. begin
  150. datalist.concat(Tai_const.Create_16bit(word(tordconstnode(p).value)));
  151. check_range(torddef(t.def));
  152. end
  153. else
  154. Message(parser_e_illegal_expression);
  155. end;
  156. s32bit,
  157. u32bit :
  158. begin
  159. if is_constintnode(p) then
  160. begin
  161. datalist.concat(Tai_const.Create_32bit(longint(tordconstnode(p).value)));
  162. if torddef(t.def).typ<>u32bit then
  163. check_range(torddef(t.def));
  164. end
  165. else
  166. Message(parser_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. else if is_constrealnode(p) and
  175. (torddef(t.def).typ=scurrency)
  176. { allow bootstrapping }
  177. then
  178. begin
  179. intvalue:=round(trealconstnode(p).value_real*10000);
  180. end
  181. else
  182. begin
  183. intvalue:=0;
  184. Message(parser_e_illegal_expression);
  185. end;
  186. datalist.concat(Tai_const.Create_64bit(intvalue));
  187. end;
  188. else
  189. internalerror(3799);
  190. end;
  191. p.free;
  192. end;
  193. floatdef:
  194. begin
  195. p:=comp_expr(true);
  196. if is_constrealnode(p) then
  197. value:=trealconstnode(p).value_real
  198. else if is_constintnode(p) then
  199. value:=tordconstnode(p).value
  200. else
  201. Message(parser_e_illegal_expression);
  202. case tfloatdef(t.def).typ of
  203. s32real :
  204. datalist.concat(Tai_real_32bit.Create(ts32real(value)));
  205. s64real :
  206. {$ifdef ARM}
  207. if aktfputype in [fpu_fpa,fpu_fpa10,fpu_fpa11] then
  208. datalist.concat(Tai_real_64bit.Create_hiloswapped(ts64real(value)))
  209. else
  210. {$endif ARM}
  211. datalist.concat(Tai_real_64bit.Create(ts64real(value)));
  212. s80real :
  213. datalist.concat(Tai_real_80bit.Create(value));
  214. { the round is necessary for native compilers where comp isn't a float }
  215. s64comp :
  216. datalist.concat(Tai_comp_64bit.Create(round(value)));
  217. s64currency:
  218. datalist.concat(Tai_comp_64bit.Create(round(value*10000)));
  219. s128real:
  220. datalist.concat(Tai_real_128bit.Create(value));
  221. else
  222. internalerror(18);
  223. end;
  224. p.free;
  225. end;
  226. classrefdef:
  227. begin
  228. p:=comp_expr(true);
  229. case p.nodetype of
  230. loadvmtaddrn:
  231. with Tclassrefdef(p.resulttype.def) do
  232. begin
  233. if not Tobjectdef(pointertype.def).is_related(Tobjectdef(pointertype.def)) then
  234. message(parser_e_illegal_expression);
  235. datalist.concat(Tai_const.Create_sym(current_asmdata.RefAsmSymbol(
  236. Tobjectdef(pointertype.def).vmt_mangledname)));
  237. end;
  238. niln:
  239. datalist.concat(Tai_const.Create_sym(nil));
  240. else Message(parser_e_illegal_expression);
  241. end;
  242. p.free;
  243. end;
  244. pointerdef:
  245. begin
  246. p:=comp_expr(true);
  247. if (p.nodetype=typeconvn) then
  248. with Ttypeconvnode(p) do
  249. if (left.nodetype in [addrn,niln]) and equal_defs(t.def,p.resulttype.def) then
  250. begin
  251. hp:=left;
  252. left:=nil;
  253. p.free;
  254. p:=hp;
  255. end;
  256. { allows horrible ofs(typeof(TButton)^) code !! }
  257. if (p.nodetype=addrn) then
  258. with Taddrnode(p) do
  259. if left.nodetype=derefn then
  260. begin
  261. hp:=tderefnode(left).left;
  262. tderefnode(left).left:=nil;
  263. p.free;
  264. p:=hp;
  265. end;
  266. { const pointer ? }
  267. if (p.nodetype = pointerconstn) then
  268. begin
  269. if sizeof(TConstPtrUInt)=8 then
  270. datalist.concat(Tai_const.Create_64bit(TConstPtrUInt(tpointerconstnode(p).value)))
  271. else
  272. if sizeof(TConstPtrUInt)=4 then
  273. datalist.concat(Tai_const.Create_32bit(TConstPtrUInt(tpointerconstnode(p).value)))
  274. else
  275. internalerror(200404122);
  276. end
  277. { nil pointer ? }
  278. else if p.nodetype=niln then
  279. datalist.concat(Tai_const.Create_sym(nil))
  280. { maybe pchar ? }
  281. else
  282. if is_char(tpointerdef(t.def).pointertype.def) and
  283. (p.nodetype<>addrn) then
  284. begin
  285. current_asmdata.getdatalabel(ll);
  286. datalist.concat(Tai_const.Create_sym(ll));
  287. if p.nodetype=stringconstn then
  288. varalign:=size_2_align(tstringconstnode(p).len)
  289. else
  290. varalign:=0;
  291. varalign:=const_align(varalign);
  292. current_asmdata.asmlists[al_const].concat(Tai_align.Create(varalign));
  293. current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
  294. if p.nodetype=stringconstn then
  295. begin
  296. len:=tstringconstnode(p).len;
  297. { For tp7 the maximum lentgh can be 255 }
  298. if (m_tp7 in aktmodeswitches) and
  299. (len>255) then
  300. len:=255;
  301. getmem(ca,len+2);
  302. move(tstringconstnode(p).value_str^,ca^,len+1);
  303. current_asmdata.asmlists[al_const].concat(Tai_string.Create_pchar(ca,len+1));
  304. end
  305. else
  306. if is_constcharnode(p) then
  307. current_asmdata.asmlists[al_const].concat(Tai_string.Create(char(byte(tordconstnode(p).value))+#0))
  308. else
  309. message(parser_e_illegal_expression);
  310. end
  311. { maybe pwidechar ? }
  312. else
  313. if is_widechar(tpointerdef(t.def).pointertype.def) and
  314. (p.nodetype<>addrn) then
  315. begin
  316. current_asmdata.getdatalabel(ll);
  317. datalist.concat(Tai_const.Create_sym(ll));
  318. current_asmdata.asmlists[al_typedconsts].concat(tai_align.create(const_align(sizeof(aint))));
  319. current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(ll));
  320. if (p.nodetype in [stringconstn,ordconstn]) then
  321. begin
  322. { convert to widestring stringconstn }
  323. inserttypeconv(p,cwidestringtype);
  324. if (p.nodetype=stringconstn) and
  325. (tstringconstnode(p).cst_type=cst_widestring) then
  326. begin
  327. pw:=pcompilerwidestring(tstringconstnode(p).value_str);
  328. for i:=0 to tstringconstnode(p).len-1 do
  329. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(pw^.data[i]));
  330. { ending #0 }
  331. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(0))
  332. end;
  333. end
  334. else
  335. Message(parser_e_illegal_expression);
  336. end
  337. else
  338. if (p.nodetype=addrn) or
  339. is_procvar_load(p) then
  340. begin
  341. { insert typeconv }
  342. inserttypeconv(p,t);
  343. hp:=p;
  344. while assigned(hp) and (hp.nodetype in [addrn,typeconvn,subscriptn,vecn]) do
  345. hp:=tunarynode(hp).left;
  346. if (hp.nodetype=loadn) then
  347. begin
  348. hp:=p;
  349. offset:=0;
  350. while assigned(hp) and (hp.nodetype<>loadn) do
  351. begin
  352. case hp.nodetype of
  353. vecn :
  354. begin
  355. case tvecnode(hp).left.resulttype.def.deftype of
  356. stringdef :
  357. begin
  358. { this seems OK for shortstring and ansistrings PM }
  359. { it is wrong for widestrings !! }
  360. len:=1;
  361. base:=0;
  362. end;
  363. arraydef :
  364. begin
  365. len:=tarraydef(tvecnode(hp).left.resulttype.def).elesize;
  366. base:=tarraydef(tvecnode(hp).left.resulttype.def).lowrange;
  367. end
  368. else
  369. Message(parser_e_illegal_expression);
  370. end;
  371. if is_constintnode(tvecnode(hp).right) then
  372. inc(offset,len*(get_ordinal_value(tvecnode(hp).right)-base))
  373. else
  374. Message(parser_e_illegal_expression);
  375. end;
  376. subscriptn :
  377. inc(offset,tsubscriptnode(hp).vs.fieldoffset);
  378. typeconvn :
  379. begin
  380. if not(ttypeconvnode(hp).convtype in [tc_equal,tc_proc_2_procvar]) then
  381. Message(parser_e_illegal_expression);
  382. end;
  383. addrn :
  384. ;
  385. else
  386. Message(parser_e_illegal_expression);
  387. end;
  388. hp:=tunarynode(hp).left;
  389. end;
  390. srsym:=tloadnode(hp).symtableentry;
  391. case srsym.typ of
  392. procsym :
  393. begin
  394. if Tprocsym(srsym).procdef_count>1 then
  395. Message(parser_e_no_overloaded_procvars);
  396. if po_abstractmethod in tprocsym(srsym).first_procdef.procoptions then
  397. Message(type_e_cant_take_address_of_abstract_method)
  398. else
  399. datalist.concat(Tai_const.Createname(tprocsym(srsym).first_procdef.mangledname,offset));
  400. end;
  401. globalvarsym :
  402. datalist.concat(Tai_const.Createname(tglobalvarsym(srsym).mangledname,offset));
  403. typedconstsym :
  404. datalist.concat(Tai_const.Createname(ttypedconstsym(srsym).mangledname,offset));
  405. labelsym :
  406. datalist.concat(Tai_const.Createname(tlabelsym(srsym).mangledname,offset));
  407. constsym :
  408. if tconstsym(srsym).consttyp=constresourcestring then
  409. datalist.concat(Tai_const.Createname(make_mangledname('RESOURCESTRINGLIST',tconstsym(srsym).owner,''),tconstsym(srsym).resstrindex*(4+sizeof(aint)*3)+4+sizeof(aint)))
  410. else
  411. Message(type_e_variable_id_expected);
  412. else
  413. Message(type_e_variable_id_expected);
  414. end;
  415. end
  416. else
  417. Message(parser_e_illegal_expression);
  418. end
  419. else
  420. { allow typeof(Object type)}
  421. if (p.nodetype=inlinen) and
  422. (tinlinenode(p).inlinenumber=in_typeof_x) then
  423. begin
  424. if (tinlinenode(p).left.nodetype=typen) then
  425. begin
  426. datalist.concat(Tai_const.createname(
  427. tobjectdef(tinlinenode(p).left.resulttype.def).vmt_mangledname,0));
  428. end
  429. else
  430. Message(parser_e_illegal_expression);
  431. end
  432. else
  433. Message(parser_e_illegal_expression);
  434. p.free;
  435. end;
  436. setdef:
  437. begin
  438. p:=comp_expr(true);
  439. if p.nodetype=setconstn then
  440. begin
  441. { be sure to convert to the correct result, else
  442. it can generate smallset data instead of normalset (PFV) }
  443. inserttypeconv(p,t);
  444. { we only allow const sets }
  445. if assigned(tsetconstnode(p).left) then
  446. Message(parser_e_illegal_expression)
  447. else
  448. begin
  449. { this writing is endian independant }
  450. { untrue - because they are considered }
  451. { arrays of 32-bit values CEC }
  452. if source_info.endian = target_info.endian then
  453. begin
  454. for l:=0 to p.resulttype.def.size-1 do
  455. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[l]));
  456. end
  457. else
  458. begin
  459. { store as longint values in swaped format }
  460. j:=0;
  461. for l:=0 to ((p.resulttype.def.size-1) div 4) do
  462. begin
  463. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+3]));
  464. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+2]));
  465. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+1]));
  466. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j]));
  467. Inc(j,4);
  468. end;
  469. end;
  470. end;
  471. end
  472. else
  473. Message(parser_e_illegal_expression);
  474. p.free;
  475. end;
  476. enumdef:
  477. begin
  478. p:=comp_expr(true);
  479. if p.nodetype=ordconstn then
  480. begin
  481. if equal_defs(p.resulttype.def,t.def) or
  482. is_subequal(p.resulttype.def,t.def) then
  483. begin
  484. case longint(p.resulttype.def.size) of
  485. 1 : datalist.concat(Tai_const.Create_8bit(Byte(tordconstnode(p).value)));
  486. 2 : datalist.concat(Tai_const.Create_16bit(Word(tordconstnode(p).value)));
  487. 4 : datalist.concat(Tai_const.Create_32bit(Longint(tordconstnode(p).value)));
  488. end;
  489. end
  490. else
  491. IncompatibleTypes(p.resulttype.def,t.def);
  492. end
  493. else
  494. Message(parser_e_illegal_expression);
  495. p.free;
  496. end;
  497. stringdef:
  498. begin
  499. p:=comp_expr(true);
  500. { load strval and strlength of the constant tree }
  501. if (p.nodetype=stringconstn) or is_widestring(t.def) then
  502. begin
  503. { convert to the expected string type so that
  504. for widestrings strval is a pcompilerwidestring }
  505. inserttypeconv(p,t);
  506. strlength:=tstringconstnode(p).len;
  507. strval:=tstringconstnode(p).value_str;
  508. end
  509. else if is_constcharnode(p) then
  510. begin
  511. { strval:=pchar(@tordconstnode(p).value);
  512. THIS FAIL on BIG_ENDIAN MACHINES PM }
  513. c:=chr(tordconstnode(p).value and $ff);
  514. strval:=@c;
  515. strlength:=1
  516. end
  517. else if is_constresourcestringnode(p) then
  518. begin
  519. strval:=pchar(tconstsym(tloadnode(p).symtableentry).value.valueptr);
  520. strlength:=tconstsym(tloadnode(p).symtableentry).value.len;
  521. end
  522. else
  523. begin
  524. Message(parser_e_illegal_expression);
  525. strlength:=-1;
  526. end;
  527. if strlength>=0 then
  528. begin
  529. case tstringdef(t.def).string_typ of
  530. st_shortstring:
  531. begin
  532. if strlength>=t.def.size then
  533. begin
  534. message2(parser_w_string_too_long,strpas(strval),tostr(t.def.size-1));
  535. strlength:=t.def.size-1;
  536. end;
  537. datalist.concat(Tai_const.Create_8bit(strlength));
  538. { this can also handle longer strings }
  539. getmem(ca,strlength+1);
  540. move(strval^,ca^,strlength);
  541. ca[strlength]:=#0;
  542. datalist.concat(Tai_string.Create_pchar(ca,strlength));
  543. { fillup with spaces if size is shorter }
  544. if t.def.size>strlength then
  545. begin
  546. getmem(ca,t.def.size-strlength);
  547. { def.size contains also the leading length, so we }
  548. { we have to subtract one }
  549. fillchar(ca[0],t.def.size-strlength-1,' ');
  550. ca[t.def.size-strlength-1]:=#0;
  551. { this can also handle longer strings }
  552. datalist.concat(Tai_string.Create_pchar(ca,t.def.size-strlength-1));
  553. end;
  554. end;
  555. st_ansistring:
  556. begin
  557. { an empty ansi string is nil! }
  558. if (strlength=0) then
  559. datalist.concat(Tai_const.Create_sym(nil))
  560. else
  561. begin
  562. current_asmdata.getdatalabel(ll);
  563. datalist.concat(Tai_const.Create_sym(ll));
  564. current_asmdata.asmlists[al_const].concat(tai_align.create(const_align(sizeof(aint))));
  565. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(-1));
  566. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(strlength));
  567. current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
  568. getmem(ca,strlength+1);
  569. move(strval^,ca^,strlength);
  570. { The terminating #0 to be stored in the .data section (JM) }
  571. ca[strlength]:=#0;
  572. current_asmdata.asmlists[al_const].concat(Tai_string.Create_pchar(ca,strlength+1));
  573. end;
  574. end;
  575. st_widestring:
  576. begin
  577. { an empty ansi string is nil! }
  578. if (strlength=0) then
  579. datalist.concat(Tai_const.Create_sym(nil))
  580. else
  581. begin
  582. current_asmdata.getdatalabel(ll);
  583. datalist.concat(Tai_const.Create_sym(ll));
  584. current_asmdata.asmlists[al_const].concat(tai_align.create(const_align(sizeof(aint))));
  585. if tf_winlikewidestring in target_info.flags then
  586. current_asmdata.asmlists[al_const].concat(Tai_const.Create_32bit(strlength*cwidechartype.def.size))
  587. else
  588. begin
  589. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(-1));
  590. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(strlength*cwidechartype.def.size));
  591. end;
  592. current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
  593. for i:=0 to strlength-1 do
  594. current_asmdata.asmlists[al_const].concat(Tai_const.Create_16bit(pcompilerwidestring(strval)^.data[i]));
  595. { ending #0 }
  596. current_asmdata.asmlists[al_const].concat(Tai_const.Create_16bit(0))
  597. end;
  598. end;
  599. st_longstring:
  600. begin
  601. internalerror(200107081);
  602. end;
  603. end;
  604. end;
  605. p.free;
  606. end;
  607. arraydef:
  608. begin
  609. { dynamic array nil }
  610. if is_dynamic_array(t.def) then
  611. begin
  612. { Only allow nil initialization }
  613. consume(_NIL);
  614. datalist.concat(Tai_const.Create_sym(nil));
  615. end
  616. else
  617. if try_to_consume(_LKLAMMER) then
  618. begin
  619. for l:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange-1 do
  620. begin
  621. readtypedconst(datalist,tarraydef(t.def).elementtype,nil,writable);
  622. consume(_COMMA);
  623. end;
  624. readtypedconst(datalist,tarraydef(t.def).elementtype,nil,writable);
  625. consume(_RKLAMMER);
  626. end
  627. else
  628. { if array of char then we allow also a string }
  629. if is_char(tarraydef(t.def).elementtype.def) then
  630. begin
  631. p:=comp_expr(true);
  632. if p.nodetype=stringconstn then
  633. begin
  634. len:=tstringconstnode(p).len;
  635. { For tp7 the maximum lentgh can be 255 }
  636. if (m_tp7 in aktmodeswitches) and
  637. (len>255) then
  638. len:=255;
  639. ca:=tstringconstnode(p).value_str;
  640. end
  641. else
  642. if is_constcharnode(p) then
  643. begin
  644. c:=chr(tordconstnode(p).value and $ff);
  645. ca:=@c;
  646. len:=1;
  647. end
  648. else
  649. begin
  650. Message(parser_e_illegal_expression);
  651. len:=0;
  652. end;
  653. if len>(tarraydef(t.def).highrange-tarraydef(t.def).lowrange+1) then
  654. Message(parser_e_string_larger_array);
  655. for i:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange do
  656. begin
  657. if i+1-tarraydef(t.def).lowrange<=len then
  658. begin
  659. datalist.concat(Tai_const.Create_8bit(byte(ca^)));
  660. inc(ca);
  661. end
  662. else
  663. {Fill the remaining positions with #0.}
  664. datalist.concat(Tai_const.Create_8bit(0));
  665. end;
  666. p.free;
  667. end
  668. else
  669. begin
  670. { we want the ( }
  671. consume(_LKLAMMER);
  672. end;
  673. end;
  674. procvardef:
  675. begin
  676. { Procvars and pointers are no longer compatible. }
  677. { under tp: =nil or =var under fpc: =nil or =@var }
  678. if token=_NIL then
  679. begin
  680. datalist.concat(Tai_const.Create_sym(nil));
  681. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  682. datalist.concat(Tai_const.Create_sym(nil));
  683. consume(_NIL);
  684. goto myexit;
  685. end;
  686. { you can't assign a value other than NIL to a typed constant }
  687. { which is a "procedure of object", because this also requires }
  688. { address of an object/class instance, which is not known at }
  689. { compile time (JM) }
  690. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  691. Message(parser_e_no_procvarobj_const);
  692. { parse the rest too, so we can continue with error checking }
  693. getprocvardef:=tprocvardef(t.def);
  694. p:=comp_expr(true);
  695. getprocvardef:=nil;
  696. if codegenerror then
  697. begin
  698. p.free;
  699. goto myexit;
  700. end;
  701. { let type conversion check everything needed }
  702. inserttypeconv(p,t);
  703. if codegenerror then
  704. begin
  705. p.free;
  706. goto myexit;
  707. end;
  708. { remove typeconvs, that will normally insert a lea
  709. instruction which is not necessary for us }
  710. while p.nodetype=typeconvn do
  711. begin
  712. hp:=ttypeconvnode(p).left;
  713. ttypeconvnode(p).left:=nil;
  714. p.free;
  715. p:=hp;
  716. end;
  717. { remove addrn which we also don't need here }
  718. if p.nodetype=addrn then
  719. begin
  720. hp:=taddrnode(p).left;
  721. taddrnode(p).left:=nil;
  722. p.free;
  723. p:=hp;
  724. end;
  725. { we now need to have a loadn with a procsym }
  726. if (p.nodetype=loadn) and
  727. (tloadnode(p).symtableentry.typ=procsym) then
  728. begin
  729. datalist.concat(Tai_const.createname(
  730. tprocsym(tloadnode(p).symtableentry).first_procdef.mangledname,0));
  731. end
  732. else
  733. Message(parser_e_illegal_expression);
  734. p.free;
  735. end;
  736. { reads a typed constant record }
  737. recorddef:
  738. begin
  739. { KAZ }
  740. if (trecorddef(t.def)=rec_tguid) and
  741. ((token=_CSTRING) or (token=_CCHAR) or (token=_ID)) then
  742. begin
  743. p:=comp_expr(true);
  744. inserttypeconv(p,cshortstringtype);
  745. if p.nodetype=stringconstn then
  746. begin
  747. s:=strpas(tstringconstnode(p).value_str);
  748. p.free;
  749. if string2guid(s,tmpguid) then
  750. begin
  751. datalist.concat(Tai_const.Create_32bit(longint(tmpguid.D1)));
  752. datalist.concat(Tai_const.Create_16bit(tmpguid.D2));
  753. datalist.concat(Tai_const.Create_16bit(tmpguid.D3));
  754. for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
  755. datalist.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
  756. end
  757. else
  758. Message(parser_e_improper_guid_syntax);
  759. end
  760. else
  761. begin
  762. p.free;
  763. Message(parser_e_illegal_expression);
  764. goto myexit;
  765. end;
  766. end
  767. else
  768. begin
  769. consume(_LKLAMMER);
  770. sorg:='';
  771. aktpos:=0;
  772. srsym := tsym(trecorddef(t.def).symtable.symindex.first);
  773. recsym := nil;
  774. while token<>_RKLAMMER do
  775. begin
  776. s:=pattern;
  777. sorg:=orgpattern;
  778. consume(_ID);
  779. consume(_COLON);
  780. error := false;
  781. recsym := tsym(trecorddef(t.def).symtable.search(s));
  782. if not assigned(recsym) then
  783. begin
  784. Message1(sym_e_illegal_field,sorg);
  785. error := true;
  786. end;
  787. if (not error) and
  788. (not assigned(srsym) or
  789. (s <> srsym.name)) then
  790. { possible variant record (JM) }
  791. begin
  792. { All parts of a variant start at the same offset }
  793. { Also allow jumping from one variant part to another, }
  794. { as long as the offsets match }
  795. if (assigned(srsym) and
  796. (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
  797. { srsym is not assigned after parsing w2 in the }
  798. { typed const in the next example: }
  799. { type tr = record case byte of }
  800. { 1: (l1,l2: dword); }
  801. { 2: (w1,w2: word); }
  802. { end; }
  803. { const r: tr = (w1:1;w2:1;l2:5); }
  804. (tfieldvarsym(recsym).fieldoffset = aktpos) then
  805. srsym := recsym
  806. { going backwards isn't allowed in any mode }
  807. else if (tfieldvarsym(recsym).fieldoffset<aktpos) then
  808. begin
  809. Message(parser_e_invalid_record_const);
  810. error := true;
  811. end
  812. { Delphi allows you to skip fields }
  813. else if (m_delphi in aktmodeswitches) then
  814. begin
  815. Message1(parser_w_skipped_fields_before,sorg);
  816. srsym := recsym;
  817. end
  818. { FPC and TP don't }
  819. else
  820. begin
  821. Message1(parser_e_skipped_fields_before,sorg);
  822. error := true;
  823. end;
  824. end;
  825. if error then
  826. consume_all_until(_SEMICOLON)
  827. else
  828. begin
  829. { if needed fill (alignment) }
  830. if tfieldvarsym(srsym).fieldoffset>aktpos then
  831. for i:=1 to tfieldvarsym(srsym).fieldoffset-aktpos do
  832. datalist.concat(Tai_const.Create_8bit(0));
  833. { new position }
  834. aktpos:=tfieldvarsym(srsym).fieldoffset+tfieldvarsym(srsym).vartype.def.size;
  835. { read the data }
  836. readtypedconst(datalist,tfieldvarsym(srsym).vartype,nil,writable);
  837. { keep previous field for checking whether whole }
  838. { record was initialized (JM) }
  839. recsym := srsym;
  840. { goto next field }
  841. srsym := tsym(srsym.indexnext);
  842. if token=_SEMICOLON then
  843. consume(_SEMICOLON)
  844. else break;
  845. end;
  846. end;
  847. { are there any fields left? }
  848. if assigned(srsym) and
  849. { don't complain if there only come other variant parts }
  850. { after the last initialized field }
  851. ((recsym=nil) or
  852. (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)) then
  853. Message1(parser_w_skipped_fields_after,sorg);
  854. for i:=1 to t.def.size-aktpos do
  855. datalist.concat(Tai_const.Create_8bit(0));
  856. consume(_RKLAMMER);
  857. end;
  858. end;
  859. { reads a typed object }
  860. objectdef:
  861. begin
  862. if is_class_or_interface(t.def) then
  863. begin
  864. p:=comp_expr(true);
  865. if p.nodetype<>niln then
  866. begin
  867. Message(parser_e_type_const_not_possible);
  868. consume_all_until(_RKLAMMER);
  869. end
  870. else
  871. begin
  872. datalist.concat(Tai_const.Create_sym(nil));
  873. end;
  874. p.free;
  875. end
  876. { for objects we allow it only if it doesn't contain a vmt }
  877. else if (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  878. (m_fpc in aktmodeswitches) then
  879. Message(parser_e_type_const_not_possible)
  880. else
  881. begin
  882. consume(_LKLAMMER);
  883. aktpos:=0;
  884. while token<>_RKLAMMER do
  885. begin
  886. s:=pattern;
  887. sorg:=orgpattern;
  888. consume(_ID);
  889. consume(_COLON);
  890. srsym:=nil;
  891. obj:=tobjectdef(t.def);
  892. symt:=obj.symtable;
  893. while (srsym=nil) and assigned(symt) do
  894. begin
  895. srsym:=tsym(symt.search(s));
  896. if assigned(obj) then
  897. obj:=obj.childof;
  898. if assigned(obj) then
  899. symt:=obj.symtable
  900. else
  901. symt:=nil;
  902. end;
  903. if srsym=nil then
  904. begin
  905. Message1(sym_e_id_not_found,sorg);
  906. consume_all_until(_SEMICOLON);
  907. end
  908. else
  909. with tfieldvarsym(srsym) do
  910. begin
  911. { check position }
  912. if fieldoffset<aktpos then
  913. message(parser_e_invalid_record_const);
  914. { check in VMT needs to be added for TP mode }
  915. with Tobjectdef(t.def) do
  916. if not(m_fpc in aktmodeswitches) and
  917. (oo_has_vmt in objectoptions) and
  918. (vmt_offset<fieldoffset) then
  919. begin
  920. for i:=1 to vmt_offset-aktpos do
  921. datalist.concat(tai_const.create_8bit(0));
  922. datalist.concat(tai_const.createname(vmt_mangledname,0));
  923. { this is more general }
  924. aktpos:=vmt_offset + sizeof(aint);
  925. end;
  926. { if needed fill }
  927. if fieldoffset>aktpos then
  928. for i:=1 to fieldoffset-aktpos do
  929. datalist.concat(Tai_const.Create_8bit(0));
  930. { new position }
  931. aktpos:=fieldoffset+vartype.def.size;
  932. { read the data }
  933. readtypedconst(datalist,vartype,nil,writable);
  934. if not try_to_consume(_SEMICOLON) then
  935. break;
  936. end;
  937. end;
  938. if not(m_fpc in aktmodeswitches) and
  939. (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  940. (tobjectdef(t.def).vmt_offset>=aktpos) then
  941. begin
  942. for i:=1 to tobjectdef(t.def).vmt_offset-aktpos do
  943. datalist.concat(tai_const.create_8bit(0));
  944. datalist.concat(tai_const.createname(tobjectdef(t.def).vmt_mangledname,0));
  945. { this is more general }
  946. aktpos:=tobjectdef(t.def).vmt_offset + sizeof(aint);
  947. end;
  948. for i:=1 to t.def.size-aktpos do
  949. datalist.concat(Tai_const.Create_8bit(0));
  950. consume(_RKLAMMER);
  951. end;
  952. end;
  953. errordef:
  954. begin
  955. { try to consume something useful }
  956. if token=_LKLAMMER then
  957. consume_all_until(_RKLAMMER)
  958. else
  959. consume_all_until(_SEMICOLON);
  960. end;
  961. else Message(parser_e_type_const_not_possible);
  962. end;
  963. { Parse hints and public directive }
  964. if assigned(sym) then
  965. begin
  966. try_consume_hintdirective(sym.symoptions);
  967. { Support public name directive }
  968. if try_to_consume(_PUBLIC) then
  969. begin
  970. if try_to_consume(_NAME) then
  971. C_name:=get_stringconst
  972. else
  973. C_name:=sorg;
  974. sym.set_mangledname(C_Name);
  975. end;
  976. end;
  977. myexit:
  978. block_type:=old_block_type;
  979. { Add symbol name if this is specified. For array
  980. elements sym=nil and we should skip this }
  981. if assigned(sym) then
  982. begin
  983. storefilepos:=aktfilepos;
  984. aktfilepos:=sym.fileinfo;
  985. { insert cut for smartlinking or alignment }
  986. if writable then
  987. cursectype:=sec_data
  988. else
  989. cursectype:=sec_rodata;
  990. maybe_new_object_file(list);
  991. new_section(list,cursectype,lower(sym.mangledname),const_align(t.def.alignment));
  992. if (sym.owner.symtabletype=globalsymtable) or
  993. maybe_smartlink_symbol or
  994. (assigned(current_procinfo) and
  995. (po_inline in current_procinfo.procdef.procoptions)) or
  996. DLLSource then
  997. list.concat(Tai_symbol.Createname_global(sym.mangledname,AT_DATA,0))
  998. else
  999. list.concat(Tai_symbol.Createname(sym.mangledname,AT_DATA,0));
  1000. list.concatlist(datalist);
  1001. list.concat(tai_symbol_end.Createname(sym.mangledname));
  1002. aktfilepos:=storefilepos;
  1003. end
  1004. else
  1005. list.concatlist(datalist);
  1006. datalist.free;
  1007. end;
  1008. {$ifdef fpc}
  1009. {$maxfpuregisters default}
  1010. {$endif fpc}
  1011. end.