ptconst.pas 47 KB

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