ptconst.pas 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Reads typed constants
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ptconst;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses symtype,symsym;
  21. { this procedure reads typed constants }
  22. { sym is only needed for ansi strings }
  23. { the assembler label is in the middle (PM) }
  24. procedure readtypedconst(const t:ttype;sym : ttypedconstsym;writable : boolean);
  25. implementation
  26. uses
  27. strings,
  28. globtype,systems,tokens,verbose,
  29. cutils,globals,widestr,scanner,
  30. symconst,symbase,symdef,symtable,
  31. aasmbase,aasmtai,aasmcpu,defutil,defcmp,
  32. { pass 1 }
  33. node,htypechk,
  34. nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  35. { parser specific stuff }
  36. pbase,pexpr,
  37. { codegen }
  38. cpuinfo,cgbase
  39. ;
  40. {$ifdef fpc}
  41. {$maxfpuregisters 0}
  42. {$endif fpc}
  43. { this procedure reads typed constants }
  44. procedure readtypedconst(const t:ttype;sym : ttypedconstsym;writable : boolean);
  45. type
  46. setbytes = array[0..31] of byte;
  47. Psetbytes = ^setbytes;
  48. var
  49. len,base : longint;
  50. p,hp : tnode;
  51. i,j,l,
  52. varalign : longint;
  53. offset,
  54. strlength : aint;
  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. intvalue : tconstexprint;
  68. strval : pchar;
  69. pw : pcompilerwidestring;
  70. error : boolean;
  71. old_block_type : tblock_type;
  72. procedure check_range(def:torddef);
  73. begin
  74. if ((tordconstnode(p).value>def.high) or
  75. (tordconstnode(p).value<def.low)) then
  76. begin
  77. if (cs_check_range in aktlocalswitches) then
  78. Message(parser_e_range_check_error)
  79. else
  80. Message(parser_w_range_check_error);
  81. end;
  82. end;
  83. begin
  84. old_block_type:=block_type;
  85. block_type:=bt_const;
  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(byte(tordconstnode(p).value)))
  99. else
  100. Message(parser_e_illegal_expression);
  101. end;
  102. bool16bit :
  103. begin
  104. if is_constboolnode(p) then
  105. curconstSegment.concat(Tai_const.Create_16bit(word(tordconstnode(p).value)))
  106. else
  107. Message(parser_e_illegal_expression);
  108. end;
  109. bool32bit :
  110. begin
  111. if is_constboolnode(p) then
  112. curconstSegment.concat(Tai_const.Create_32bit(longint(tordconstnode(p).value)))
  113. else
  114. Message(parser_e_illegal_expression);
  115. end;
  116. uchar :
  117. begin
  118. if is_constcharnode(p) then
  119. curconstSegment.concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)))
  120. else
  121. Message(parser_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(word(tordconstnode(p).value)))
  129. else
  130. Message(parser_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(byte(tordconstnode(p).value)));
  138. check_range(torddef(t.def));
  139. end
  140. else
  141. Message(parser_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(word(tordconstnode(p).value)));
  149. check_range(torddef(t.def));
  150. end
  151. else
  152. Message(parser_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(longint(tordconstnode(p).value)));
  160. if torddef(t.def).typ<>u32bit then
  161. check_range(torddef(t.def));
  162. end
  163. else
  164. Message(parser_e_illegal_expression);
  165. end;
  166. s64bit,
  167. u64bit,
  168. scurrency:
  169. begin
  170. if is_constintnode(p) then
  171. intvalue := tordconstnode(p).value
  172. else if is_constrealnode(p) and
  173. (torddef(t.def).typ=scurrency)
  174. { allow bootstrapping }
  175. {$ifdef VER1_0}
  176. { I get IE 10 here. I guess it's no problem if a 1.0 bootstrapped
  177. compiler doesn't display the error here.
  178. and (trealconstnode(p).value_real*10000 >= real(low(int64))) and
  179. (trealconstnode(p).value_real*10000 <= real(high(int64)))}
  180. {$endif VER1_0}
  181. then
  182. begin
  183. {$ifdef VER1_0}
  184. { only trunc is 64 bit in 1.0.x so use trunc here to allow bootstrapping }
  185. intvalue:=trunc(trealconstnode(p).value_real*10000);
  186. {$else VER1_0}
  187. intvalue:=round(trealconstnode(p).value_real*10000);
  188. {$endif VER1_0}
  189. end
  190. else
  191. begin
  192. intvalue:=0;
  193. Message(parser_e_illegal_expression);
  194. end;
  195. curconstSegment.concat(Tai_const.Create_64bit(intvalue));
  196. end;
  197. else
  198. internalerror(3799);
  199. end;
  200. p.free;
  201. end;
  202. floatdef:
  203. begin
  204. p:=comp_expr(true);
  205. if is_constrealnode(p) then
  206. value:=trealconstnode(p).value_real
  207. else if is_constintnode(p) then
  208. value:=tordconstnode(p).value
  209. else
  210. Message(parser_e_illegal_expression);
  211. case tfloatdef(t.def).typ of
  212. s32real :
  213. curconstSegment.concat(Tai_real_32bit.Create(ts32real(value)));
  214. s64real :
  215. {$ifdef ARM}
  216. if aktfputype in [fpu_fpa,fpu_fpa10,fpu_fpa11] then
  217. curconstSegment.concat(Tai_real_64bit.Create_hiloswapped(ts64real(value)))
  218. else
  219. {$endif ARM}
  220. curconstSegment.concat(Tai_real_64bit.Create(ts64real(value)));
  221. s80real :
  222. curconstSegment.concat(Tai_real_80bit.Create(value));
  223. {$ifdef ver1_0}
  224. s64comp :
  225. curconstSegment.concat(Tai_comp_64bit.Create(value));
  226. s64currency:
  227. curconstSegment.concat(Tai_comp_64bit.Create(value*10000));
  228. {$else ver1_0}
  229. { the round is necessary for native compilers where comp isn't a float }
  230. s64comp :
  231. curconstSegment.concat(Tai_comp_64bit.Create(round(value)));
  232. s64currency:
  233. curconstSegment.concat(Tai_comp_64bit.Create(round(value*10000)));
  234. {$endif ver1_0}
  235. s128real:
  236. curconstSegment.concat(Tai_real_128bit.Create(value));
  237. else
  238. internalerror(18);
  239. end;
  240. p.free;
  241. end;
  242. classrefdef:
  243. begin
  244. p:=comp_expr(true);
  245. case p.nodetype of
  246. loadvmtaddrn:
  247. with Tclassrefdef(p.resulttype.def) do
  248. begin
  249. if not Tobjectdef(pointertype.def).is_related(Tobjectdef(pointertype.def)) then
  250. message(parser_e_illegal_expression);
  251. curconstSegment.concat(Tai_const.Create_sym(objectlibrary.newasmsymbol(
  252. Tobjectdef(pointertype.def).vmt_mangledname,AB_EXTERNAL,AT_DATA)));
  253. end;
  254. niln:
  255. curconstSegment.concat(Tai_const.Create_sym(nil));
  256. else Message(parser_e_illegal_expression);
  257. end;
  258. p.free;
  259. end;
  260. pointerdef:
  261. begin
  262. p:=comp_expr(true);
  263. if (p.nodetype=typeconvn) then
  264. with Ttypeconvnode(p) do
  265. if (left.nodetype in [addrn,niln]) and equal_defs(t.def,p.resulttype.def) then
  266. begin
  267. hp:=left;
  268. left:=nil;
  269. p.free;
  270. p:=hp;
  271. end;
  272. { allows horrible ofs(typeof(TButton)^) code !! }
  273. if (p.nodetype=addrn) then
  274. with Taddrnode(p) do
  275. if left.nodetype=derefn then
  276. begin
  277. hp:=tderefnode(left).left;
  278. tderefnode(left).left:=nil;
  279. p.free;
  280. p:=hp;
  281. end;
  282. { const pointer ? }
  283. if (p.nodetype = pointerconstn) then
  284. begin
  285. if sizeof(TConstPtrUInt)=8 then
  286. curconstsegment.concat(Tai_const.Create_64bit(TConstPtrUInt(tpointerconstnode(p).value)))
  287. else
  288. if sizeof(TConstPtrUInt)=4 then
  289. curconstsegment.concat(Tai_const.Create_32bit(TConstPtrUInt(tpointerconstnode(p).value)))
  290. else
  291. internalerror(200404122);
  292. end
  293. { nil pointer ? }
  294. else if p.nodetype=niln then
  295. curconstSegment.concat(Tai_const.Create_sym(nil))
  296. { maybe pchar ? }
  297. else
  298. if is_char(tpointerdef(t.def).pointertype.def) and
  299. (p.nodetype<>addrn) then
  300. begin
  301. objectlibrary.getdatalabel(ll);
  302. curconstSegment.concat(Tai_const.Create_sym(ll));
  303. if p.nodetype=stringconstn then
  304. varalign:=tstringconstnode(p).len
  305. else
  306. varalign:=0;
  307. varalign:=const_align(varalign);
  308. Consts.concat(Tai_align.Create(varalign));
  309. Consts.concat(Tai_label.Create(ll));
  310. if p.nodetype=stringconstn then
  311. begin
  312. len:=tstringconstnode(p).len;
  313. { For tp7 the maximum lentgh can be 255 }
  314. if (m_tp7 in aktmodeswitches) and
  315. (len>255) then
  316. len:=255;
  317. getmem(ca,len+2);
  318. move(tstringconstnode(p).value_str^,ca^,len+1);
  319. Consts.concat(Tai_string.Create_length_pchar(ca,len+1));
  320. end
  321. else
  322. if is_constcharnode(p) then
  323. Consts.concat(Tai_string.Create(char(byte(tordconstnode(p).value))+#0))
  324. else
  325. Message(parser_e_illegal_expression);
  326. end
  327. { maybe pwidechar ? }
  328. else
  329. if is_widechar(tpointerdef(t.def).pointertype.def) and
  330. (p.nodetype<>addrn) then
  331. begin
  332. objectlibrary.getdatalabel(ll);
  333. curconstSegment.concat(Tai_const.Create_sym(ll));
  334. Consts.concat(tai_align.create(const_align(sizeof(aint))));
  335. Consts.concat(Tai_label.Create(ll));
  336. if (p.nodetype in [stringconstn,ordconstn]) then
  337. begin
  338. { convert to widestring stringconstn }
  339. inserttypeconv(p,cwidestringtype);
  340. if (p.nodetype=stringconstn) and
  341. (tstringconstnode(p).st_type=st_widestring) then
  342. begin
  343. pw:=pcompilerwidestring(tstringconstnode(p).value_str);
  344. for i:=0 to tstringconstnode(p).len-1 do
  345. Consts.concat(Tai_const.Create_16bit(pw^.data[i]));
  346. { ending #0 }
  347. Consts.concat(Tai_const.Create_16bit(0))
  348. end;
  349. end
  350. else
  351. Message(parser_e_illegal_expression);
  352. end
  353. else
  354. if (p.nodetype=addrn) or
  355. is_procvar_load(p) then
  356. begin
  357. { insert typeconv }
  358. inserttypeconv(p,t);
  359. hp:=p;
  360. while assigned(hp) and (hp.nodetype in [addrn,typeconvn,subscriptn,vecn]) do
  361. hp:=tunarynode(hp).left;
  362. if (hp.nodetype=loadn) then
  363. begin
  364. hp:=p;
  365. offset:=0;
  366. while assigned(hp) and (hp.nodetype<>loadn) do
  367. begin
  368. case hp.nodetype of
  369. vecn :
  370. begin
  371. case tvecnode(hp).left.resulttype.def.deftype of
  372. stringdef :
  373. begin
  374. { this seems OK for shortstring and ansistrings PM }
  375. { it is wrong for widestrings !! }
  376. len:=1;
  377. base:=0;
  378. end;
  379. arraydef :
  380. begin
  381. len:=tarraydef(tvecnode(hp).left.resulttype.def).elesize;
  382. base:=tarraydef(tvecnode(hp).left.resulttype.def).lowrange;
  383. end
  384. else
  385. Message(parser_e_illegal_expression);
  386. end;
  387. if is_constintnode(tvecnode(hp).right) then
  388. inc(offset,len*(get_ordinal_value(tvecnode(hp).right)-base))
  389. else
  390. Message(parser_e_illegal_expression);
  391. end;
  392. subscriptn :
  393. inc(offset,tsubscriptnode(hp).vs.fieldoffset);
  394. typeconvn :
  395. begin
  396. if not(ttypeconvnode(hp).convtype in [tc_equal,tc_proc_2_procvar]) then
  397. Message(parser_e_illegal_expression);
  398. end;
  399. addrn :
  400. ;
  401. else
  402. Message(parser_e_illegal_expression);
  403. end;
  404. hp:=tunarynode(hp).left;
  405. end;
  406. srsym:=tloadnode(hp).symtableentry;
  407. case srsym.typ of
  408. procsym :
  409. begin
  410. if Tprocsym(srsym).procdef_count>1 then
  411. Message(parser_e_no_overloaded_procvars);
  412. if po_abstractmethod in tprocsym(srsym).first_procdef.procoptions then
  413. Message(type_e_cant_take_address_of_abstract_method)
  414. else
  415. curconstSegment.concat(Tai_const.Createname(tprocsym(srsym).first_procdef.mangledname,AT_FUNCTION,offset));
  416. end;
  417. globalvarsym :
  418. curconstSegment.concat(Tai_const.Createname(tglobalvarsym(srsym).mangledname,AT_DATA,offset));
  419. typedconstsym :
  420. curconstSegment.concat(Tai_const.Createname(ttypedconstsym(srsym).mangledname,AT_DATA,offset));
  421. labelsym :
  422. curconstSegment.concat(Tai_const.Createname(tlabelsym(srsym).mangledname,AT_FUNCTION,offset));
  423. constsym :
  424. if tconstsym(srsym).consttyp=constresourcestring then
  425. curconstSegment.concat(Tai_const.Createname(make_mangledname('RESOURCESTRINGLIST',tconstsym(srsym).owner,''),AT_DATA,tconstsym(srsym).resstrindex*(4+sizeof(aint)*3)+4+sizeof(aint)))
  426. else
  427. Message(type_e_variable_id_expected);
  428. else
  429. Message(type_e_variable_id_expected);
  430. end;
  431. end
  432. else
  433. Message(parser_e_illegal_expression);
  434. end
  435. else
  436. { allow typeof(Object type)}
  437. if (p.nodetype=inlinen) and
  438. (tinlinenode(p).inlinenumber=in_typeof_x) then
  439. begin
  440. if (tinlinenode(p).left.nodetype=typen) then
  441. begin
  442. curconstSegment.concat(Tai_const.createname(
  443. tobjectdef(tinlinenode(p).left.resulttype.def).vmt_mangledname,AT_DATA,0));
  444. end
  445. else
  446. Message(parser_e_illegal_expression);
  447. end
  448. else
  449. Message(parser_e_illegal_expression);
  450. p.free;
  451. end;
  452. setdef:
  453. begin
  454. p:=comp_expr(true);
  455. if p.nodetype=setconstn then
  456. begin
  457. { be sure to convert to the correct result, else
  458. it can generate smallset data instead of normalset (PFV) }
  459. inserttypeconv(p,t);
  460. { we only allow const sets }
  461. if assigned(tsetconstnode(p).left) then
  462. Message(parser_e_illegal_expression)
  463. else
  464. begin
  465. { this writing is endian independant }
  466. { untrue - because they are considered }
  467. { arrays of 32-bit values CEC }
  468. if source_info.endian = target_info.endian then
  469. begin
  470. for l:=0 to p.resulttype.def.size-1 do
  471. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[l]));
  472. end
  473. else
  474. begin
  475. { store as longint values in swaped format }
  476. j:=0;
  477. for l:=0 to ((p.resulttype.def.size-1) div 4) do
  478. begin
  479. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+3]));
  480. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+2]));
  481. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+1]));
  482. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j]));
  483. Inc(j,4);
  484. end;
  485. end;
  486. end;
  487. end
  488. else
  489. Message(parser_e_illegal_expression);
  490. p.free;
  491. end;
  492. enumdef:
  493. begin
  494. p:=comp_expr(true);
  495. if p.nodetype=ordconstn then
  496. begin
  497. if equal_defs(p.resulttype.def,t.def) or
  498. is_subequal(p.resulttype.def,t.def) then
  499. begin
  500. case longint(p.resulttype.def.size) of
  501. 1 : curconstSegment.concat(Tai_const.Create_8bit(Byte(tordconstnode(p).value)));
  502. 2 : curconstSegment.concat(Tai_const.Create_16bit(Word(tordconstnode(p).value)));
  503. 4 : curconstSegment.concat(Tai_const.Create_32bit(Longint(tordconstnode(p).value)));
  504. end;
  505. end
  506. else
  507. IncompatibleTypes(p.resulttype.def,t.def);
  508. end
  509. else
  510. Message(parser_e_illegal_expression);
  511. p.free;
  512. end;
  513. stringdef:
  514. begin
  515. p:=comp_expr(true);
  516. { load strval and strlength of the constant tree }
  517. if (p.nodetype=stringconstn) or is_widestring(t.def) then
  518. begin
  519. { convert to the expected string type so that
  520. for widestrings strval is a pcompilerwidestring }
  521. inserttypeconv(p,t);
  522. strlength:=tstringconstnode(p).len;
  523. strval:=tstringconstnode(p).value_str;
  524. end
  525. else if is_constcharnode(p) then
  526. begin
  527. { strval:=pchar(@tordconstnode(p).value);
  528. THIS FAIL on BIG_ENDIAN MACHINES PM }
  529. c:=chr(tordconstnode(p).value and $ff);
  530. strval:=@c;
  531. strlength:=1
  532. end
  533. else if is_constresourcestringnode(p) then
  534. begin
  535. strval:=pchar(tconstsym(tloadnode(p).symtableentry).value.valueptr);
  536. strlength:=tconstsym(tloadnode(p).symtableentry).value.len;
  537. end
  538. else
  539. begin
  540. Message(parser_e_illegal_expression);
  541. strlength:=-1;
  542. end;
  543. if strlength>=0 then
  544. begin
  545. case tstringdef(t.def).string_typ of
  546. st_shortstring:
  547. begin
  548. if strlength>=t.def.size then
  549. begin
  550. message2(parser_w_string_too_long,strpas(strval),tostr(t.def.size-1));
  551. strlength:=t.def.size-1;
  552. end;
  553. curconstSegment.concat(Tai_const.Create_8bit(strlength));
  554. { this can also handle longer strings }
  555. getmem(ca,strlength+1);
  556. move(strval^,ca^,strlength);
  557. ca[strlength]:=#0;
  558. curconstSegment.concat(Tai_string.Create_length_pchar(ca,strlength));
  559. { fillup with spaces if size is shorter }
  560. if t.def.size>strlength then
  561. begin
  562. getmem(ca,t.def.size-strlength);
  563. { def.size contains also the leading length, so we }
  564. { we have to subtract one }
  565. fillchar(ca[0],t.def.size-strlength-1,' ');
  566. ca[t.def.size-strlength-1]:=#0;
  567. { this can also handle longer strings }
  568. curconstSegment.concat(Tai_string.Create_length_pchar(ca,t.def.size-strlength-1));
  569. end;
  570. end;
  571. {$ifdef ansistrings_bits}
  572. st_ansistring16:
  573. begin
  574. { an empty ansi string is nil! }
  575. if (strlength=0) then
  576. curconstSegment.concat(Tai_const.Create_ptr(0))
  577. else
  578. begin
  579. objectlibrary.getdatalabel(ll);
  580. curconstSegment.concat(Tai_const_symbol.Create(ll));
  581. { the actual structure starts at -12 from start label - CEC }
  582. Consts.concat(tai_align.create(const_align(pointer_size)));
  583. { first write the maximum size }
  584. Consts.concat(Tai_const.Create_16bit(strlength));
  585. { second write the real length }
  586. Consts.concat(Tai_const.Create_16bit(strlength));
  587. { redondent with maxlength but who knows ... (PM) }
  588. { third write use count (set to -1 for safety ) }
  589. Consts.concat(Tai_const.Create_16bit(-1));
  590. Consts.concat(Tai_label.Create(ll));
  591. getmem(ca,strlength+2);
  592. move(strval^,ca^,strlength);
  593. { The terminating #0 to be stored in the .data section (JM) }
  594. ca[strlength]:=#0;
  595. { End of the PChar. The memory has to be allocated because in }
  596. { tai_string.done, there is a freemem(len+1) (JM) }
  597. ca[strlength+1]:=#0;
  598. Consts.concat(Tai_string.Create_length_pchar(ca,strlength+1));
  599. end;
  600. end;
  601. {$endif}
  602. {$ifdef ansistring_bits}st_ansistring32{$else}st_ansistring{$endif}:
  603. begin
  604. { an empty ansi string is nil! }
  605. if (strlength=0) then
  606. curconstSegment.concat(Tai_const.Create_sym(nil))
  607. else
  608. begin
  609. objectlibrary.getdatalabel(ll);
  610. curconstSegment.concat(Tai_const.Create_sym(ll));
  611. Consts.concat(tai_align.create(const_align(sizeof(aint))));
  612. Consts.concat(Tai_const.Create_aint(-1));
  613. Consts.concat(Tai_const.Create_aint(strlength));
  614. Consts.concat(Tai_label.Create(ll));
  615. getmem(ca,strlength+2);
  616. move(strval^,ca^,strlength);
  617. { The terminating #0 to be stored in the .data section (JM) }
  618. ca[strlength]:=#0;
  619. { End of the PChar. The memory has to be allocated because in }
  620. { tai_string.done, there is a freemem(len+1) (JM) }
  621. ca[strlength+1]:=#0;
  622. Consts.concat(Tai_string.Create_length_pchar(ca,strlength+1));
  623. end;
  624. end;
  625. {$ifdef ansistring_bits}
  626. st_ansistring64:
  627. begin
  628. { an empty ansi string is nil! }
  629. if (strlength=0) then
  630. curconstSegment.concat(Tai_const.Create_ptr(0))
  631. else
  632. begin
  633. objectlibrary.getdatalabel(ll);
  634. curconstSegment.concat(Tai_const_symbol.Create(ll));
  635. { the actual structure starts at -12 from start label - CEC }
  636. Consts.concat(tai_align.create(const_align(pointer_size)));
  637. { first write the maximum size }
  638. Consts.concat(Tai_const.Create_64bit(strlength));
  639. { second write the real length }
  640. Consts.concat(Tai_const.Create_64bit(strlength));
  641. { redondent with maxlength but who knows ... (PM) }
  642. { third write use count (set to -1 for safety ) }
  643. Consts.concat(Tai_const.Create_64bit(-1));
  644. Consts.concat(Tai_label.Create(ll));
  645. getmem(ca,strlength+2);
  646. move(strval^,ca^,strlength);
  647. { The terminating #0 to be stored in the .data section (JM) }
  648. ca[strlength]:=#0;
  649. { End of the PChar. The memory has to be allocated because in }
  650. { tai_string.done, there is a freemem(len+1) (JM) }
  651. ca[strlength+1]:=#0;
  652. Consts.concat(Tai_string.Create_length_pchar(ca,strlength+1));
  653. end;
  654. end;
  655. {$endif}
  656. st_widestring:
  657. begin
  658. { an empty ansi string is nil! }
  659. if (strlength=0) then
  660. curconstSegment.concat(Tai_const.Create_sym(nil))
  661. else
  662. begin
  663. objectlibrary.getdatalabel(ll);
  664. curconstSegment.concat(Tai_const.Create_sym(ll));
  665. Consts.concat(tai_align.create(const_align(sizeof(aint))));
  666. Consts.concat(Tai_const.Create_aint(-1));
  667. Consts.concat(Tai_const.Create_aint(strlength));
  668. Consts.concat(Tai_label.Create(ll));
  669. for i:=0 to strlength-1 do
  670. Consts.concat(Tai_const.Create_16bit(pcompilerwidestring(strval)^.data[i]));
  671. { ending #0 }
  672. Consts.concat(Tai_const.Create_16bit(0))
  673. end;
  674. end;
  675. st_longstring:
  676. begin
  677. internalerror(200107081);
  678. {curconstSegment.concat(Tai_const.Create_32bit(strlength))));
  679. curconstSegment.concat(Tai_const.Create_8bit(0));
  680. getmem(ca,strlength+1);
  681. move(strval^,ca^,strlength);
  682. ca[strlength]:=#0;
  683. generate_pascii(consts,ca,strlength);
  684. curconstSegment.concat(Tai_const.Create_8bit(0));}
  685. end;
  686. end;
  687. end;
  688. p.free;
  689. end;
  690. arraydef:
  691. begin
  692. { dynamic array nil }
  693. if is_dynamic_array(t.def) then
  694. begin
  695. { Only allow nil initialization }
  696. consume(_NIL);
  697. curconstSegment.concat(Tai_const.Create_sym(nil));
  698. end
  699. else
  700. if try_to_consume(_LKLAMMER) then
  701. begin
  702. for l:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange-1 do
  703. begin
  704. readtypedconst(tarraydef(t.def).elementtype,nil,writable);
  705. consume(_COMMA);
  706. end;
  707. readtypedconst(tarraydef(t.def).elementtype,nil,writable);
  708. consume(_RKLAMMER);
  709. end
  710. else
  711. { if array of char then we allow also a string }
  712. if is_char(tarraydef(t.def).elementtype.def) then
  713. begin
  714. p:=comp_expr(true);
  715. if p.nodetype=stringconstn then
  716. begin
  717. len:=tstringconstnode(p).len;
  718. { For tp7 the maximum lentgh can be 255 }
  719. if (m_tp7 in aktmodeswitches) and
  720. (len>255) then
  721. len:=255;
  722. ca:=tstringconstnode(p).value_str;
  723. end
  724. else
  725. if is_constcharnode(p) then
  726. begin
  727. c:=chr(tordconstnode(p).value and $ff);
  728. ca:=@c;
  729. len:=1;
  730. end
  731. else
  732. begin
  733. Message(parser_e_illegal_expression);
  734. len:=0;
  735. end;
  736. if len>(tarraydef(t.def).highrange-tarraydef(t.def).lowrange+1) then
  737. Message(parser_e_string_larger_array);
  738. for i:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange do
  739. begin
  740. if i+1-tarraydef(t.def).lowrange<=len then
  741. begin
  742. curconstSegment.concat(Tai_const.Create_8bit(byte(ca^)));
  743. inc(ca);
  744. end
  745. else
  746. {Fill the remaining positions with #0.}
  747. curconstSegment.concat(Tai_const.Create_8bit(0));
  748. end;
  749. p.free;
  750. end
  751. else
  752. begin
  753. { we want the ( }
  754. consume(_LKLAMMER);
  755. end;
  756. end;
  757. procvardef:
  758. begin
  759. { Procvars and pointers are no longer compatible. }
  760. { under tp: =nil or =var under fpc: =nil or =@var }
  761. if token=_NIL then
  762. begin
  763. curconstSegment.concat(Tai_const.Create_sym(nil));
  764. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  765. curconstSegment.concat(Tai_const.Create_sym(nil));
  766. consume(_NIL);
  767. exit;
  768. end;
  769. { you can't assign a value other than NIL to a typed constant }
  770. { which is a "procedure of object", because this also requires }
  771. { address of an object/class instance, which is not known at }
  772. { compile time (JM) }
  773. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  774. Message(parser_e_no_procvarobj_const);
  775. { parse the rest too, so we can continue with error checking }
  776. getprocvardef:=tprocvardef(t.def);
  777. p:=comp_expr(true);
  778. getprocvardef:=nil;
  779. if codegenerror then
  780. begin
  781. p.free;
  782. exit;
  783. end;
  784. { let type conversion check everything needed }
  785. inserttypeconv(p,t);
  786. if codegenerror then
  787. begin
  788. p.free;
  789. exit;
  790. end;
  791. { remove typeconvs, that will normally insert a lea
  792. instruction which is not necessary for us }
  793. while p.nodetype=typeconvn do
  794. begin
  795. hp:=ttypeconvnode(p).left;
  796. ttypeconvnode(p).left:=nil;
  797. p.free;
  798. p:=hp;
  799. end;
  800. { remove addrn which we also don't need here }
  801. if p.nodetype=addrn then
  802. begin
  803. hp:=taddrnode(p).left;
  804. taddrnode(p).left:=nil;
  805. p.free;
  806. p:=hp;
  807. end;
  808. { we now need to have a loadn with a procsym }
  809. if (p.nodetype=loadn) and
  810. (tloadnode(p).symtableentry.typ=procsym) then
  811. begin
  812. curconstSegment.concat(Tai_const.createname(
  813. tprocsym(tloadnode(p).symtableentry).first_procdef.mangledname,AT_FUNCTION,0));
  814. end
  815. else
  816. Message(parser_e_illegal_expression);
  817. p.free;
  818. end;
  819. { reads a typed constant record }
  820. recorddef:
  821. begin
  822. { KAZ }
  823. if (trecorddef(t.def)=rec_tguid) and
  824. ((token=_CSTRING) or (token=_CCHAR) or (token=_ID)) then
  825. begin
  826. p:=comp_expr(true);
  827. inserttypeconv(p,cshortstringtype);
  828. if p.nodetype=stringconstn then
  829. begin
  830. s:=strpas(tstringconstnode(p).value_str);
  831. p.free;
  832. if string2guid(s,tmpguid) then
  833. begin
  834. curconstSegment.concat(Tai_const.Create_32bit(longint(tmpguid.D1)));
  835. curconstSegment.concat(Tai_const.Create_16bit(tmpguid.D2));
  836. curconstSegment.concat(Tai_const.Create_16bit(tmpguid.D3));
  837. for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
  838. curconstSegment.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
  839. end
  840. else
  841. Message(parser_e_improper_guid_syntax);
  842. end
  843. else
  844. begin
  845. p.free;
  846. Message(parser_e_illegal_expression);
  847. exit;
  848. end;
  849. end
  850. else
  851. begin
  852. consume(_LKLAMMER);
  853. sorg:='';
  854. aktpos:=0;
  855. srsym := tsym(trecorddef(t.def).symtable.symindex.first);
  856. recsym := nil;
  857. while token<>_RKLAMMER do
  858. begin
  859. s:=pattern;
  860. sorg:=orgpattern;
  861. consume(_ID);
  862. consume(_COLON);
  863. error := false;
  864. recsym := tsym(trecorddef(t.def).symtable.search(s));
  865. if not assigned(recsym) then
  866. begin
  867. Message1(sym_e_illegal_field,sorg);
  868. error := true;
  869. end;
  870. if (not error) and
  871. (not assigned(srsym) or
  872. (s <> srsym.name)) then
  873. { possible variant record (JM) }
  874. begin
  875. { All parts of a variant start at the same offset }
  876. { Also allow jumping from one variant part to another, }
  877. { as long as the offsets match }
  878. if (assigned(srsym) and
  879. (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
  880. { srsym is not assigned after parsing w2 in the }
  881. { typed const in the next example: }
  882. { type tr = record case byte of }
  883. { 1: (l1,l2: dword); }
  884. { 2: (w1,w2: word); }
  885. { end; }
  886. { const r: tr = (w1:1;w2:1;l2:5); }
  887. (tfieldvarsym(recsym).fieldoffset = aktpos) then
  888. srsym := recsym
  889. { going backwards isn't allowed in any mode }
  890. else if (tfieldvarsym(recsym).fieldoffset<aktpos) then
  891. begin
  892. Message(parser_e_invalid_record_const);
  893. error := true;
  894. end
  895. { Delphi allows you to skip fields }
  896. else if (m_delphi in aktmodeswitches) then
  897. begin
  898. Message1(parser_w_skipped_fields_before,sorg);
  899. srsym := recsym;
  900. end
  901. { FPC and TP don't }
  902. else
  903. begin
  904. Message1(parser_e_skipped_fields_before,sorg);
  905. error := true;
  906. end;
  907. end;
  908. if error then
  909. consume_all_until(_SEMICOLON)
  910. else
  911. begin
  912. { if needed fill (alignment) }
  913. if tfieldvarsym(srsym).fieldoffset>aktpos then
  914. for i:=1 to tfieldvarsym(srsym).fieldoffset-aktpos do
  915. curconstSegment.concat(Tai_const.Create_8bit(0));
  916. { new position }
  917. aktpos:=tfieldvarsym(srsym).fieldoffset+tfieldvarsym(srsym).vartype.def.size;
  918. { read the data }
  919. readtypedconst(tfieldvarsym(srsym).vartype,nil,writable);
  920. { keep previous field for checking whether whole }
  921. { record was initialized (JM) }
  922. recsym := srsym;
  923. { goto next field }
  924. srsym := tsym(srsym.indexnext);
  925. if token=_SEMICOLON then
  926. consume(_SEMICOLON)
  927. else break;
  928. end;
  929. end;
  930. { are there any fields left? }
  931. if assigned(srsym) and
  932. { don't complain if there only come other variant parts }
  933. { after the last initialized field }
  934. ((recsym=nil) or
  935. (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)) then
  936. Message1(parser_w_skipped_fields_after,sorg);
  937. for i:=1 to t.def.size-aktpos do
  938. curconstSegment.concat(Tai_const.Create_8bit(0));
  939. consume(_RKLAMMER);
  940. end;
  941. end;
  942. { reads a typed object }
  943. objectdef:
  944. begin
  945. if is_class_or_interface(t.def) then
  946. begin
  947. p:=comp_expr(true);
  948. if p.nodetype<>niln then
  949. begin
  950. Message(parser_e_type_const_not_possible);
  951. consume_all_until(_RKLAMMER);
  952. end
  953. else
  954. begin
  955. curconstSegment.concat(Tai_const.Create_sym(nil));
  956. end;
  957. p.free;
  958. end
  959. { for objects we allow it only if it doesn't contain a vmt }
  960. else if (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  961. (m_fpc in aktmodeswitches) then
  962. Message(parser_e_type_const_not_possible)
  963. else
  964. begin
  965. consume(_LKLAMMER);
  966. aktpos:=0;
  967. while token<>_RKLAMMER do
  968. begin
  969. s:=pattern;
  970. sorg:=orgpattern;
  971. consume(_ID);
  972. consume(_COLON);
  973. srsym:=nil;
  974. obj:=tobjectdef(t.def);
  975. symt:=obj.symtable;
  976. while (srsym=nil) and assigned(symt) do
  977. begin
  978. srsym:=tsym(symt.search(s));
  979. if assigned(obj) then
  980. obj:=obj.childof;
  981. if assigned(obj) then
  982. symt:=obj.symtable
  983. else
  984. symt:=nil;
  985. end;
  986. if srsym=nil then
  987. begin
  988. Message1(sym_e_id_not_found,sorg);
  989. consume_all_until(_SEMICOLON);
  990. end
  991. else
  992. with tfieldvarsym(srsym) do
  993. begin
  994. { check position }
  995. if fieldoffset<aktpos then
  996. message(parser_e_invalid_record_const);
  997. { check in VMT needs to be added for TP mode }
  998. with Tobjectdef(t.def) do
  999. if not(m_fpc in aktmodeswitches) and
  1000. (oo_has_vmt in objectoptions) and
  1001. (vmt_offset<fieldoffset) then
  1002. begin
  1003. for i:=1 to vmt_offset-aktpos do
  1004. curconstsegment.concat(tai_const.create_8bit(0));
  1005. curconstsegment.concat(tai_const.createname(vmt_mangledname,AT_DATA,0));
  1006. { this is more general }
  1007. aktpos:=vmt_offset + sizeof(aint);
  1008. end;
  1009. { if needed fill }
  1010. if fieldoffset>aktpos then
  1011. for i:=1 to fieldoffset-aktpos do
  1012. curconstSegment.concat(Tai_const.Create_8bit(0));
  1013. { new position }
  1014. aktpos:=fieldoffset+vartype.def.size;
  1015. { read the data }
  1016. readtypedconst(vartype,nil,writable);
  1017. if token=_SEMICOLON then
  1018. consume(_SEMICOLON)
  1019. else break;
  1020. end;
  1021. end;
  1022. if not(m_fpc in aktmodeswitches) and
  1023. (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  1024. (tobjectdef(t.def).vmt_offset>=aktpos) then
  1025. begin
  1026. for i:=1 to tobjectdef(t.def).vmt_offset-aktpos do
  1027. curconstsegment.concat(tai_const.create_8bit(0));
  1028. curconstsegment.concat(tai_const.createname(tobjectdef(t.def).vmt_mangledname,AT_DATA,0));
  1029. { this is more general }
  1030. aktpos:=tobjectdef(t.def).vmt_offset + sizeof(aint);
  1031. end;
  1032. for i:=1 to t.def.size-aktpos do
  1033. curconstSegment.concat(Tai_const.Create_8bit(0));
  1034. consume(_RKLAMMER);
  1035. end;
  1036. end;
  1037. errordef:
  1038. begin
  1039. { try to consume something useful }
  1040. if token=_LKLAMMER then
  1041. consume_all_until(_RKLAMMER)
  1042. else
  1043. consume_all_until(_SEMICOLON);
  1044. end;
  1045. else Message(parser_e_type_const_not_possible);
  1046. end;
  1047. block_type:=old_block_type;
  1048. end;
  1049. {$ifdef fpc}
  1050. {$maxfpuregisters default}
  1051. {$endif fpc}
  1052. end.