ptconst.pas 49 KB

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