ptconst.pas 51 KB

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