ptconst.pas 47 KB

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