ptconst.pas 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076
  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. bool64bit :
  119. begin
  120. if is_constboolnode(p) then
  121. datalist.concat(Tai_const.Create_64bit(int64(tordconstnode(p).value)))
  122. else
  123. Message(parser_e_illegal_expression);
  124. end;
  125. uchar :
  126. begin
  127. if is_constcharnode(p) then
  128. datalist.concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)))
  129. else
  130. Message(parser_e_illegal_expression);
  131. end;
  132. uwidechar :
  133. begin
  134. if is_constcharnode(p) then
  135. inserttypeconv(p,cwidechartype);
  136. if is_constwidecharnode(p) then
  137. datalist.concat(Tai_const.Create_16bit(word(tordconstnode(p).value)))
  138. else
  139. Message(parser_e_illegal_expression);
  140. end;
  141. s8bit,
  142. u8bit :
  143. begin
  144. if is_constintnode(p) then
  145. begin
  146. datalist.concat(Tai_const.Create_8bit(byte(tordconstnode(p).value)));
  147. check_range(torddef(t.def));
  148. end
  149. else
  150. Message(parser_e_illegal_expression);
  151. end;
  152. u16bit,
  153. s16bit :
  154. begin
  155. if is_constintnode(p) then
  156. begin
  157. datalist.concat(Tai_const.Create_16bit(word(tordconstnode(p).value)));
  158. check_range(torddef(t.def));
  159. end
  160. else
  161. Message(parser_e_illegal_expression);
  162. end;
  163. s32bit,
  164. u32bit :
  165. begin
  166. if is_constintnode(p) then
  167. begin
  168. datalist.concat(Tai_const.Create_32bit(longint(tordconstnode(p).value)));
  169. if torddef(t.def).typ<>u32bit then
  170. check_range(torddef(t.def));
  171. end
  172. else
  173. Message(parser_e_illegal_expression);
  174. end;
  175. s64bit,
  176. u64bit,
  177. scurrency:
  178. begin
  179. if is_constintnode(p) then
  180. intvalue := tordconstnode(p).value
  181. else if is_constrealnode(p) and
  182. (torddef(t.def).typ=scurrency)
  183. { allow bootstrapping }
  184. then
  185. begin
  186. intvalue:=round(trealconstnode(p).value_real*10000);
  187. end
  188. else
  189. begin
  190. intvalue:=0;
  191. Message(parser_e_illegal_expression);
  192. end;
  193. datalist.concat(Tai_const.Create_64bit(intvalue));
  194. end;
  195. else
  196. internalerror(3799);
  197. end;
  198. p.free;
  199. end;
  200. floatdef:
  201. begin
  202. p:=comp_expr(true);
  203. if is_constrealnode(p) then
  204. value:=trealconstnode(p).value_real
  205. else if is_constintnode(p) then
  206. value:=tordconstnode(p).value
  207. else
  208. Message(parser_e_illegal_expression);
  209. case tfloatdef(t.def).typ of
  210. s32real :
  211. datalist.concat(Tai_real_32bit.Create(ts32real(value)));
  212. s64real :
  213. {$ifdef ARM}
  214. if aktfputype in [fpu_fpa,fpu_fpa10,fpu_fpa11] then
  215. datalist.concat(Tai_real_64bit.Create_hiloswapped(ts64real(value)))
  216. else
  217. {$endif ARM}
  218. datalist.concat(Tai_real_64bit.Create(ts64real(value)));
  219. s80real :
  220. datalist.concat(Tai_real_80bit.Create(value));
  221. { the round is necessary for native compilers where comp isn't a float }
  222. s64comp :
  223. datalist.concat(Tai_comp_64bit.Create(round(value)));
  224. s64currency:
  225. datalist.concat(Tai_comp_64bit.Create(round(value*10000)));
  226. s128real:
  227. datalist.concat(Tai_real_128bit.Create(value));
  228. else
  229. internalerror(18);
  230. end;
  231. p.free;
  232. end;
  233. classrefdef:
  234. begin
  235. p:=comp_expr(true);
  236. case p.nodetype of
  237. loadvmtaddrn:
  238. with Tclassrefdef(p.resulttype.def) do
  239. begin
  240. if not Tobjectdef(pointertype.def).is_related(Tobjectdef(pointertype.def)) then
  241. message(parser_e_illegal_expression);
  242. datalist.concat(Tai_const.Create_sym(current_asmdata.RefAsmSymbol(
  243. Tobjectdef(pointertype.def).vmt_mangledname)));
  244. end;
  245. niln:
  246. datalist.concat(Tai_const.Create_sym(nil));
  247. else Message(parser_e_illegal_expression);
  248. end;
  249. p.free;
  250. end;
  251. pointerdef:
  252. begin
  253. p:=comp_expr(true);
  254. if (p.nodetype=typeconvn) then
  255. with Ttypeconvnode(p) do
  256. if (left.nodetype in [addrn,niln]) and equal_defs(t.def,p.resulttype.def) then
  257. begin
  258. hp:=left;
  259. left:=nil;
  260. p.free;
  261. p:=hp;
  262. end;
  263. { allows horrible ofs(typeof(TButton)^) code !! }
  264. if (p.nodetype=addrn) then
  265. with Taddrnode(p) do
  266. if left.nodetype=derefn then
  267. begin
  268. hp:=tderefnode(left).left;
  269. tderefnode(left).left:=nil;
  270. p.free;
  271. p:=hp;
  272. end;
  273. { const pointer ? }
  274. if (p.nodetype = pointerconstn) then
  275. begin
  276. if sizeof(TConstPtrUInt)=8 then
  277. datalist.concat(Tai_const.Create_64bit(TConstPtrUInt(tpointerconstnode(p).value)))
  278. else
  279. if sizeof(TConstPtrUInt)=4 then
  280. datalist.concat(Tai_const.Create_32bit(TConstPtrUInt(tpointerconstnode(p).value)))
  281. else
  282. internalerror(200404122);
  283. end
  284. { nil pointer ? }
  285. else if p.nodetype=niln then
  286. datalist.concat(Tai_const.Create_sym(nil))
  287. { maybe pchar ? }
  288. else
  289. if is_char(tpointerdef(t.def).pointertype.def) and
  290. (p.nodetype<>addrn) then
  291. begin
  292. current_asmdata.getdatalabel(ll);
  293. datalist.concat(Tai_const.Create_sym(ll));
  294. if p.nodetype=stringconstn then
  295. varalign:=size_2_align(tstringconstnode(p).len)
  296. else
  297. varalign:=0;
  298. varalign:=const_align(varalign);
  299. current_asmdata.asmlists[al_const].concat(Tai_align.Create(varalign));
  300. current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
  301. if p.nodetype=stringconstn then
  302. begin
  303. len:=tstringconstnode(p).len;
  304. { For tp7 the maximum lentgh can be 255 }
  305. if (m_tp7 in aktmodeswitches) and
  306. (len>255) then
  307. len:=255;
  308. getmem(ca,len+2);
  309. move(tstringconstnode(p).value_str^,ca^,len+1);
  310. current_asmdata.asmlists[al_const].concat(Tai_string.Create_pchar(ca,len+1));
  311. end
  312. else
  313. if is_constcharnode(p) then
  314. current_asmdata.asmlists[al_const].concat(Tai_string.Create(char(byte(tordconstnode(p).value))+#0))
  315. else
  316. message(parser_e_illegal_expression);
  317. end
  318. { maybe pwidechar ? }
  319. else
  320. if is_widechar(tpointerdef(t.def).pointertype.def) and
  321. (p.nodetype<>addrn) then
  322. begin
  323. current_asmdata.getdatalabel(ll);
  324. datalist.concat(Tai_const.Create_sym(ll));
  325. current_asmdata.asmlists[al_typedconsts].concat(tai_align.create(const_align(sizeof(aint))));
  326. current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(ll));
  327. if (p.nodetype in [stringconstn,ordconstn]) then
  328. begin
  329. { convert to widestring stringconstn }
  330. inserttypeconv(p,cwidestringtype);
  331. if (p.nodetype=stringconstn) and
  332. (tstringconstnode(p).cst_type=cst_widestring) then
  333. begin
  334. pw:=pcompilerwidestring(tstringconstnode(p).value_str);
  335. for i:=0 to tstringconstnode(p).len-1 do
  336. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(pw^.data[i]));
  337. { ending #0 }
  338. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(0))
  339. end;
  340. end
  341. else
  342. Message(parser_e_illegal_expression);
  343. end
  344. else
  345. if (p.nodetype=addrn) or
  346. is_procvar_load(p) then
  347. begin
  348. { insert typeconv }
  349. inserttypeconv(p,t);
  350. hp:=p;
  351. while assigned(hp) and (hp.nodetype in [addrn,typeconvn,subscriptn,vecn]) do
  352. hp:=tunarynode(hp).left;
  353. if (hp.nodetype=loadn) then
  354. begin
  355. hp:=p;
  356. offset:=0;
  357. while assigned(hp) and (hp.nodetype<>loadn) do
  358. begin
  359. case hp.nodetype of
  360. vecn :
  361. begin
  362. case tvecnode(hp).left.resulttype.def.deftype of
  363. stringdef :
  364. begin
  365. { this seems OK for shortstring and ansistrings PM }
  366. { it is wrong for widestrings !! }
  367. len:=1;
  368. base:=0;
  369. end;
  370. arraydef :
  371. begin
  372. if not is_packed_array(tvecnode(hp).left.resulttype.def) then
  373. begin
  374. len:=tarraydef(tvecnode(hp).left.resulttype.def).elesize;
  375. base:=tarraydef(tvecnode(hp).left.resulttype.def).lowrange;
  376. end
  377. else
  378. begin
  379. Message(parser_e_packed_dynamic_open_array);
  380. len:=1;
  381. base:=0;
  382. end;
  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. datalist.concat(Tai_const.Createname(tprocsym(srsym).first_procdef.mangledname,offset));
  416. end;
  417. globalvarsym :
  418. datalist.concat(Tai_const.Createname(tglobalvarsym(srsym).mangledname,offset));
  419. typedconstsym :
  420. datalist.concat(Tai_const.Createname(ttypedconstsym(srsym).mangledname,offset));
  421. labelsym :
  422. datalist.concat(Tai_const.Createname(tlabelsym(srsym).mangledname,offset));
  423. constsym :
  424. if tconstsym(srsym).consttyp=constresourcestring then
  425. datalist.concat(Tai_const.Createname(make_mangledname('RESOURCESTRINGLIST',tconstsym(srsym).owner,''),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. datalist.concat(Tai_const.createname(
  443. tobjectdef(tinlinenode(p).left.resulttype.def).vmt_mangledname,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. datalist.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. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+3]));
  480. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+2]));
  481. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+1]));
  482. datalist.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 : datalist.concat(Tai_const.Create_8bit(Byte(tordconstnode(p).value)));
  502. 2 : datalist.concat(Tai_const.Create_16bit(Word(tordconstnode(p).value)));
  503. 4 : datalist.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. datalist.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. datalist.concat(Tai_string.Create_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. datalist.concat(Tai_string.Create_pchar(ca,t.def.size-strlength-1));
  569. end;
  570. end;
  571. st_ansistring:
  572. begin
  573. { an empty ansi string is nil! }
  574. if (strlength=0) then
  575. datalist.concat(Tai_const.Create_sym(nil))
  576. else
  577. begin
  578. current_asmdata.getdatalabel(ll);
  579. datalist.concat(Tai_const.Create_sym(ll));
  580. current_asmdata.asmlists[al_const].concat(tai_align.create(const_align(sizeof(aint))));
  581. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(-1));
  582. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(strlength));
  583. current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
  584. getmem(ca,strlength+1);
  585. move(strval^,ca^,strlength);
  586. { The terminating #0 to be stored in the .data section (JM) }
  587. ca[strlength]:=#0;
  588. current_asmdata.asmlists[al_const].concat(Tai_string.Create_pchar(ca,strlength+1));
  589. end;
  590. end;
  591. st_widestring:
  592. begin
  593. { an empty ansi string is nil! }
  594. if (strlength=0) then
  595. datalist.concat(Tai_const.Create_sym(nil))
  596. else
  597. begin
  598. current_asmdata.getdatalabel(ll);
  599. datalist.concat(Tai_const.Create_sym(ll));
  600. current_asmdata.asmlists[al_const].concat(tai_align.create(const_align(sizeof(aint))));
  601. if tf_winlikewidestring in target_info.flags then
  602. current_asmdata.asmlists[al_const].concat(Tai_const.Create_32bit(strlength*cwidechartype.def.size))
  603. else
  604. begin
  605. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(-1));
  606. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(strlength*cwidechartype.def.size));
  607. end;
  608. current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
  609. for i:=0 to strlength-1 do
  610. current_asmdata.asmlists[al_const].concat(Tai_const.Create_16bit(pcompilerwidestring(strval)^.data[i]));
  611. { ending #0 }
  612. current_asmdata.asmlists[al_const].concat(Tai_const.Create_16bit(0))
  613. end;
  614. end;
  615. st_longstring:
  616. begin
  617. internalerror(200107081);
  618. end;
  619. end;
  620. end;
  621. p.free;
  622. end;
  623. arraydef:
  624. begin
  625. { dynamic array nil }
  626. if is_dynamic_array(t.def) then
  627. begin
  628. { Only allow nil initialization }
  629. consume(_NIL);
  630. datalist.concat(Tai_const.Create_sym(nil));
  631. end
  632. { no packed array constants supported }
  633. else if is_packed_array(t.def) then
  634. begin
  635. Message(type_e_no_const_packed_array);
  636. consume_all_until(_RKLAMMER);
  637. end
  638. else
  639. if try_to_consume(_LKLAMMER) then
  640. begin
  641. for l:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange-1 do
  642. begin
  643. readtypedconst(datalist,tarraydef(t.def).elementtype,nil,writable);
  644. consume(_COMMA);
  645. end;
  646. readtypedconst(datalist,tarraydef(t.def).elementtype,nil,writable);
  647. consume(_RKLAMMER);
  648. end
  649. else
  650. { if array of char then we allow also a string }
  651. if is_char(tarraydef(t.def).elementtype.def) then
  652. begin
  653. p:=comp_expr(true);
  654. if p.nodetype=stringconstn then
  655. begin
  656. len:=tstringconstnode(p).len;
  657. { For tp7 the maximum lentgh can be 255 }
  658. if (m_tp7 in aktmodeswitches) and
  659. (len>255) then
  660. len:=255;
  661. ca:=tstringconstnode(p).value_str;
  662. end
  663. else
  664. if is_constcharnode(p) then
  665. begin
  666. c:=chr(tordconstnode(p).value and $ff);
  667. ca:=@c;
  668. len:=1;
  669. end
  670. else
  671. begin
  672. Message(parser_e_illegal_expression);
  673. len:=0;
  674. end;
  675. if len>(tarraydef(t.def).highrange-tarraydef(t.def).lowrange+1) then
  676. Message(parser_e_string_larger_array);
  677. for i:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange do
  678. begin
  679. if i+1-tarraydef(t.def).lowrange<=len then
  680. begin
  681. datalist.concat(Tai_const.Create_8bit(byte(ca^)));
  682. inc(ca);
  683. end
  684. else
  685. {Fill the remaining positions with #0.}
  686. datalist.concat(Tai_const.Create_8bit(0));
  687. end;
  688. p.free;
  689. end
  690. else
  691. begin
  692. { we want the ( }
  693. consume(_LKLAMMER);
  694. end;
  695. end;
  696. procvardef:
  697. begin
  698. { Procvars and pointers are no longer compatible. }
  699. { under tp: =nil or =var under fpc: =nil or =@var }
  700. if token=_NIL then
  701. begin
  702. datalist.concat(Tai_const.Create_sym(nil));
  703. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  704. datalist.concat(Tai_const.Create_sym(nil));
  705. consume(_NIL);
  706. goto myexit;
  707. end;
  708. { you can't assign a value other than NIL to a typed constant }
  709. { which is a "procedure of object", because this also requires }
  710. { address of an object/class instance, which is not known at }
  711. { compile time (JM) }
  712. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  713. Message(parser_e_no_procvarobj_const);
  714. { parse the rest too, so we can continue with error checking }
  715. getprocvardef:=tprocvardef(t.def);
  716. p:=comp_expr(true);
  717. getprocvardef:=nil;
  718. if codegenerror then
  719. begin
  720. p.free;
  721. goto myexit;
  722. end;
  723. { let type conversion check everything needed }
  724. inserttypeconv(p,t);
  725. if codegenerror then
  726. begin
  727. p.free;
  728. goto myexit;
  729. end;
  730. { remove typeconvs, that will normally insert a lea
  731. instruction which is not necessary for us }
  732. while p.nodetype=typeconvn do
  733. begin
  734. hp:=ttypeconvnode(p).left;
  735. ttypeconvnode(p).left:=nil;
  736. p.free;
  737. p:=hp;
  738. end;
  739. { remove addrn which we also don't need here }
  740. if p.nodetype=addrn then
  741. begin
  742. hp:=taddrnode(p).left;
  743. taddrnode(p).left:=nil;
  744. p.free;
  745. p:=hp;
  746. end;
  747. { we now need to have a loadn with a procsym }
  748. if (p.nodetype=loadn) and
  749. (tloadnode(p).symtableentry.typ=procsym) then
  750. begin
  751. datalist.concat(Tai_const.createname(
  752. tprocsym(tloadnode(p).symtableentry).first_procdef.mangledname,0));
  753. end
  754. else
  755. Message(parser_e_illegal_expression);
  756. p.free;
  757. end;
  758. { reads a typed constant record }
  759. recorddef:
  760. begin
  761. { packed record }
  762. if is_packed_record_or_object(t.def) then
  763. Message(type_e_no_const_packed_record)
  764. { KAZ }
  765. else if (trecorddef(t.def)=rec_tguid) and
  766. ((token=_CSTRING) or (token=_CCHAR) or (token=_ID)) then
  767. begin
  768. p:=comp_expr(true);
  769. inserttypeconv(p,cshortstringtype);
  770. if p.nodetype=stringconstn then
  771. begin
  772. s:=strpas(tstringconstnode(p).value_str);
  773. p.free;
  774. if string2guid(s,tmpguid) then
  775. begin
  776. datalist.concat(Tai_const.Create_32bit(longint(tmpguid.D1)));
  777. datalist.concat(Tai_const.Create_16bit(tmpguid.D2));
  778. datalist.concat(Tai_const.Create_16bit(tmpguid.D3));
  779. for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
  780. datalist.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
  781. end
  782. else
  783. Message(parser_e_improper_guid_syntax);
  784. end
  785. else
  786. begin
  787. p.free;
  788. Message(parser_e_illegal_expression);
  789. goto myexit;
  790. end;
  791. end
  792. else
  793. begin
  794. consume(_LKLAMMER);
  795. sorg:='';
  796. aktpos:=0;
  797. srsym := tsym(trecorddef(t.def).symtable.symindex.first);
  798. recsym := nil;
  799. while token<>_RKLAMMER do
  800. begin
  801. s:=pattern;
  802. sorg:=orgpattern;
  803. consume(_ID);
  804. consume(_COLON);
  805. error := false;
  806. recsym := tsym(trecorddef(t.def).symtable.search(s));
  807. if not assigned(recsym) then
  808. begin
  809. Message1(sym_e_illegal_field,sorg);
  810. error := true;
  811. end;
  812. if (not error) and
  813. (not assigned(srsym) or
  814. (s <> srsym.name)) then
  815. { possible variant record (JM) }
  816. begin
  817. { All parts of a variant start at the same offset }
  818. { Also allow jumping from one variant part to another, }
  819. { as long as the offsets match }
  820. if (assigned(srsym) and
  821. (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
  822. { srsym is not assigned after parsing w2 in the }
  823. { typed const in the next example: }
  824. { type tr = record case byte of }
  825. { 1: (l1,l2: dword); }
  826. { 2: (w1,w2: word); }
  827. { end; }
  828. { const r: tr = (w1:1;w2:1;l2:5); }
  829. (tfieldvarsym(recsym).fieldoffset = aktpos) then
  830. srsym := recsym
  831. { going backwards isn't allowed in any mode }
  832. else if (tfieldvarsym(recsym).fieldoffset<aktpos) then
  833. begin
  834. Message(parser_e_invalid_record_const);
  835. error := true;
  836. end
  837. { Delphi allows you to skip fields }
  838. else if (m_delphi in aktmodeswitches) then
  839. begin
  840. Message1(parser_w_skipped_fields_before,sorg);
  841. srsym := recsym;
  842. end
  843. { FPC and TP don't }
  844. else
  845. begin
  846. Message1(parser_e_skipped_fields_before,sorg);
  847. error := true;
  848. end;
  849. end;
  850. if error then
  851. consume_all_until(_SEMICOLON)
  852. else
  853. begin
  854. { if needed fill (alignment) }
  855. if tfieldvarsym(srsym).fieldoffset>aktpos then
  856. for i:=1 to tfieldvarsym(srsym).fieldoffset-aktpos do
  857. datalist.concat(Tai_const.Create_8bit(0));
  858. { new position }
  859. aktpos:=tfieldvarsym(srsym).fieldoffset+tfieldvarsym(srsym).vartype.def.size;
  860. { read the data }
  861. readtypedconst(datalist,tfieldvarsym(srsym).vartype,nil,writable);
  862. { keep previous field for checking whether whole }
  863. { record was initialized (JM) }
  864. recsym := srsym;
  865. { goto next field }
  866. srsym := tsym(srsym.indexnext);
  867. if token=_SEMICOLON then
  868. consume(_SEMICOLON)
  869. else break;
  870. end;
  871. end;
  872. { are there any fields left? }
  873. if assigned(srsym) and
  874. { don't complain if there only come other variant parts }
  875. { after the last initialized field }
  876. ((recsym=nil) or
  877. (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)) then
  878. Message1(parser_w_skipped_fields_after,sorg);
  879. for i:=1 to t.def.size-aktpos do
  880. datalist.concat(Tai_const.Create_8bit(0));
  881. consume(_RKLAMMER);
  882. end;
  883. end;
  884. { reads a typed object }
  885. objectdef:
  886. begin
  887. if is_class_or_interface(t.def) then
  888. begin
  889. p:=comp_expr(true);
  890. if p.nodetype<>niln then
  891. begin
  892. Message(type_e_no_const_packed_array);
  893. consume_all_until(_SEMICOLON);
  894. end
  895. else
  896. begin
  897. datalist.concat(Tai_const.Create_sym(nil));
  898. end;
  899. p.free;
  900. end
  901. { for objects we allow it only if it doesn't contain a vmt }
  902. else if (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  903. (m_fpc in aktmodeswitches) then
  904. Message(parser_e_type_const_not_possible)
  905. { packed object }
  906. else if is_packed_record_or_object(t.def) then
  907. Message(type_e_no_const_packed_record)
  908. else
  909. begin
  910. consume(_LKLAMMER);
  911. aktpos:=0;
  912. while token<>_RKLAMMER do
  913. begin
  914. s:=pattern;
  915. sorg:=orgpattern;
  916. consume(_ID);
  917. consume(_COLON);
  918. srsym:=nil;
  919. obj:=tobjectdef(t.def);
  920. symt:=obj.symtable;
  921. while (srsym=nil) and assigned(symt) do
  922. begin
  923. srsym:=tsym(symt.search(s));
  924. if assigned(obj) then
  925. obj:=obj.childof;
  926. if assigned(obj) then
  927. symt:=obj.symtable
  928. else
  929. symt:=nil;
  930. end;
  931. if srsym=nil then
  932. begin
  933. Message1(sym_e_id_not_found,sorg);
  934. consume_all_until(_SEMICOLON);
  935. end
  936. else
  937. with tfieldvarsym(srsym) do
  938. begin
  939. { check position }
  940. if fieldoffset<aktpos then
  941. message(parser_e_invalid_record_const);
  942. { check in VMT needs to be added for TP mode }
  943. with Tobjectdef(t.def) do
  944. if not(m_fpc in aktmodeswitches) and
  945. (oo_has_vmt in objectoptions) and
  946. (vmt_offset<fieldoffset) then
  947. begin
  948. for i:=1 to vmt_offset-aktpos do
  949. datalist.concat(tai_const.create_8bit(0));
  950. datalist.concat(tai_const.createname(vmt_mangledname,0));
  951. { this is more general }
  952. aktpos:=vmt_offset + sizeof(aint);
  953. end;
  954. { if needed fill }
  955. if fieldoffset>aktpos then
  956. for i:=1 to fieldoffset-aktpos do
  957. datalist.concat(Tai_const.Create_8bit(0));
  958. { new position }
  959. aktpos:=fieldoffset+vartype.def.size;
  960. { read the data }
  961. readtypedconst(datalist,vartype,nil,writable);
  962. if not try_to_consume(_SEMICOLON) then
  963. break;
  964. end;
  965. end;
  966. if not(m_fpc in aktmodeswitches) and
  967. (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  968. (tobjectdef(t.def).vmt_offset>=aktpos) then
  969. begin
  970. for i:=1 to tobjectdef(t.def).vmt_offset-aktpos do
  971. datalist.concat(tai_const.create_8bit(0));
  972. datalist.concat(tai_const.createname(tobjectdef(t.def).vmt_mangledname,0));
  973. { this is more general }
  974. aktpos:=tobjectdef(t.def).vmt_offset + sizeof(aint);
  975. end;
  976. for i:=1 to t.def.size-aktpos do
  977. datalist.concat(Tai_const.Create_8bit(0));
  978. consume(_RKLAMMER);
  979. end;
  980. end;
  981. errordef:
  982. begin
  983. { try to consume something useful }
  984. if token=_LKLAMMER then
  985. consume_all_until(_RKLAMMER)
  986. else
  987. consume_all_until(_SEMICOLON);
  988. end;
  989. else Message(parser_e_type_const_not_possible);
  990. end;
  991. { Parse hints and public directive }
  992. if assigned(sym) then
  993. begin
  994. try_consume_hintdirective(sym.symoptions);
  995. { Support public name directive }
  996. if try_to_consume(_PUBLIC) then
  997. begin
  998. if try_to_consume(_NAME) then
  999. C_name:=get_stringconst
  1000. else
  1001. C_name:=sorg;
  1002. sym.set_mangledname(C_Name);
  1003. end;
  1004. end;
  1005. myexit:
  1006. block_type:=old_block_type;
  1007. { Add symbol name if this is specified. For array
  1008. elements sym=nil and we should skip this }
  1009. if assigned(sym) then
  1010. begin
  1011. storefilepos:=aktfilepos;
  1012. aktfilepos:=sym.fileinfo;
  1013. { insert cut for smartlinking or alignment }
  1014. if writable then
  1015. cursectype:=sec_data
  1016. else
  1017. cursectype:=sec_rodata;
  1018. maybe_new_object_file(list);
  1019. new_section(list,cursectype,lower(sym.mangledname),const_align(t.def.alignment));
  1020. if (sym.owner.symtabletype=globalsymtable) or
  1021. maybe_smartlink_symbol or
  1022. (assigned(current_procinfo) and
  1023. (po_inline in current_procinfo.procdef.procoptions)) or
  1024. DLLSource then
  1025. list.concat(Tai_symbol.Createname_global(sym.mangledname,AT_DATA,0))
  1026. else
  1027. list.concat(Tai_symbol.Createname(sym.mangledname,AT_DATA,0));
  1028. list.concatlist(datalist);
  1029. list.concat(tai_symbol_end.Createname(sym.mangledname));
  1030. aktfilepos:=storefilepos;
  1031. end
  1032. else
  1033. list.concatlist(datalist);
  1034. datalist.free;
  1035. end;
  1036. {$ifdef fpc}
  1037. {$maxfpuregisters default}
  1038. {$endif fpc}
  1039. end.