ptconst.pas 46 KB

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