ptconst.pas 52 KB

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