ptconst.pas 51 KB

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