ptconst.pas 49 KB

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