ptconst.pas 50 KB

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