ptconst.pas 47 KB

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