ptconst.pas 46 KB

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