ptconst.pas 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  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;def:tdef;sym : ttypedconstsym;writable : boolean);
  25. implementation
  26. uses
  27. SysUtils,
  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. {$maxfpuregisters 0}
  41. { this procedure reads typed constants }
  42. procedure readtypedconst(list:tasmlist;def:tdef;sym : ttypedconstsym;writable : boolean);
  43. label
  44. myexit;
  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 : longint;
  52. varalign : shortint;
  53. offset,
  54. strlength : aint;
  55. ll : tasmlabel;
  56. c_name,
  57. s,sorg : string;
  58. c : char;
  59. ca : pchar;
  60. tmpguid : tguid;
  61. symidx,
  62. aktpos : longint;
  63. pd : tprocdef;
  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 current_settings.localswitches) 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 def.typ of
  93. orddef:
  94. begin
  95. p:=comp_expr(true);
  96. case torddef(def).ordtype 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(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(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(def).ordtype<>u32bit then
  170. check_range(torddef(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(def).ordtype=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(def).floattype of
  210. s32real :
  211. datalist.concat(Tai_real_32bit.Create(ts32real(value)));
  212. s64real :
  213. {$ifdef ARM}
  214. if current_settings.fputype 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.resultdef) do
  239. begin
  240. if not Tobjectdef(pointeddef).is_related(Tobjectdef(tclassrefdef(def).pointeddef)) then
  241. message(parser_e_illegal_expression);
  242. datalist.concat(Tai_const.Create_sym(current_asmdata.RefAsmSymbol(
  243. Tobjectdef(pointeddef).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(def,p.resultdef) 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(def).pointeddef) 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 current_settings.modeswitches) 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(def).pointeddef) 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,def);
  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.resultdef.typ 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.resultdef) then
  373. begin
  374. len:=tarraydef(tvecnode(hp).left.resultdef).elesize;
  375. base:=tarraydef(tvecnode(hp).left.resultdef).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. pd:=tprocdef(tprocsym(srsym).ProcdefList[0]);
  411. if Tprocsym(srsym).ProcdefList.Count>1 then
  412. Message(parser_e_no_overloaded_procvars);
  413. if po_abstractmethod in pd.procoptions then
  414. Message(type_e_cant_take_address_of_abstract_method)
  415. else
  416. datalist.concat(Tai_const.Createname(pd.mangledname,offset));
  417. end;
  418. globalvarsym :
  419. datalist.concat(Tai_const.Createname(tglobalvarsym(srsym).mangledname,offset));
  420. typedconstsym :
  421. datalist.concat(Tai_const.Createname(ttypedconstsym(srsym).mangledname,offset));
  422. labelsym :
  423. datalist.concat(Tai_const.Createname(tlabelsym(srsym).mangledname,offset));
  424. constsym :
  425. if tconstsym(srsym).consttyp=constresourcestring then
  426. datalist.concat(Tai_const.Createname(make_mangledname('RESOURCESTRINGLIST',tconstsym(srsym).owner,''),tconstsym(srsym).resstrindex*(4+sizeof(aint)*3)+4+sizeof(aint)))
  427. else
  428. Message(type_e_variable_id_expected);
  429. else
  430. Message(type_e_variable_id_expected);
  431. end;
  432. end
  433. else
  434. Message(parser_e_illegal_expression);
  435. end
  436. else
  437. { allow typeof(Object type)}
  438. if (p.nodetype=inlinen) and
  439. (tinlinenode(p).inlinenumber=in_typeof_x) then
  440. begin
  441. if (tinlinenode(p).left.nodetype=typen) then
  442. begin
  443. datalist.concat(Tai_const.createname(
  444. tobjectdef(tinlinenode(p).left.resultdef).vmt_mangledname,0));
  445. end
  446. else
  447. Message(parser_e_illegal_expression);
  448. end
  449. else
  450. Message(parser_e_illegal_expression);
  451. p.free;
  452. end;
  453. setdef:
  454. begin
  455. p:=comp_expr(true);
  456. if p.nodetype=setconstn then
  457. begin
  458. { be sure to convert to the correct result, else
  459. it can generate smallset data instead of normalset (PFV) }
  460. inserttypeconv(p,def);
  461. { we only allow const sets }
  462. if assigned(tsetconstnode(p).left) then
  463. Message(parser_e_illegal_expression)
  464. else
  465. begin
  466. { this writing is endian independant }
  467. { untrue - because they are considered }
  468. { arrays of 32-bit values CEC }
  469. if source_info.endian = target_info.endian then
  470. begin
  471. for l:=0 to p.resultdef.size-1 do
  472. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[l]));
  473. end
  474. else
  475. begin
  476. { store as longint values in swaped format }
  477. j:=0;
  478. for l:=0 to ((p.resultdef.size-1) div 4) do
  479. begin
  480. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+3]));
  481. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+2]));
  482. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+1]));
  483. datalist.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j]));
  484. Inc(j,4);
  485. end;
  486. end;
  487. end;
  488. end
  489. else
  490. Message(parser_e_illegal_expression);
  491. p.free;
  492. end;
  493. enumdef:
  494. begin
  495. p:=comp_expr(true);
  496. if p.nodetype=ordconstn then
  497. begin
  498. if equal_defs(p.resultdef,def) or
  499. is_subequal(p.resultdef,def) then
  500. begin
  501. case longint(p.resultdef.size) of
  502. 1 : datalist.concat(Tai_const.Create_8bit(Byte(tordconstnode(p).value)));
  503. 2 : datalist.concat(Tai_const.Create_16bit(Word(tordconstnode(p).value)));
  504. 4 : datalist.concat(Tai_const.Create_32bit(Longint(tordconstnode(p).value)));
  505. end;
  506. end
  507. else
  508. IncompatibleTypes(p.resultdef,def);
  509. end
  510. else
  511. Message(parser_e_illegal_expression);
  512. p.free;
  513. end;
  514. stringdef:
  515. begin
  516. p:=comp_expr(true);
  517. { load strval and strlength of the constant tree }
  518. if (p.nodetype=stringconstn) or is_widestring(def) then
  519. begin
  520. { convert to the expected string type so that
  521. for widestrings strval is a pcompilerwidestring }
  522. inserttypeconv(p,def);
  523. strlength:=tstringconstnode(p).len;
  524. strval:=tstringconstnode(p).value_str;
  525. end
  526. else if is_constcharnode(p) then
  527. begin
  528. { strval:=pchar(@tordconstnode(p).value);
  529. THIS FAIL on BIG_ENDIAN MACHINES PM }
  530. c:=chr(tordconstnode(p).value and $ff);
  531. strval:=@c;
  532. strlength:=1
  533. end
  534. else if is_constresourcestringnode(p) then
  535. begin
  536. strval:=pchar(tconstsym(tloadnode(p).symtableentry).value.valueptr);
  537. strlength:=tconstsym(tloadnode(p).symtableentry).value.len;
  538. end
  539. else
  540. begin
  541. Message(parser_e_illegal_expression);
  542. strlength:=-1;
  543. end;
  544. if strlength>=0 then
  545. begin
  546. case tstringdef(def).stringtype of
  547. st_shortstring:
  548. begin
  549. if strlength>=def.size then
  550. begin
  551. message2(parser_w_string_too_long,strpas(strval),tostr(def.size-1));
  552. strlength:=def.size-1;
  553. end;
  554. datalist.concat(Tai_const.Create_8bit(strlength));
  555. { this can also handle longer strings }
  556. getmem(ca,strlength+1);
  557. move(strval^,ca^,strlength);
  558. ca[strlength]:=#0;
  559. datalist.concat(Tai_string.Create_pchar(ca,strlength));
  560. { fillup with spaces if size is shorter }
  561. if def.size>strlength then
  562. begin
  563. getmem(ca,def.size-strlength);
  564. { def.size contains also the leading length, so we }
  565. { we have to subtract one }
  566. fillchar(ca[0],def.size-strlength-1,' ');
  567. ca[def.size-strlength-1]:=#0;
  568. { this can also handle longer strings }
  569. datalist.concat(Tai_string.Create_pchar(ca,def.size-strlength-1));
  570. end;
  571. end;
  572. st_ansistring:
  573. begin
  574. { an empty ansi string is nil! }
  575. if (strlength=0) then
  576. datalist.concat(Tai_const.Create_sym(nil))
  577. else
  578. begin
  579. current_asmdata.getdatalabel(ll);
  580. datalist.concat(Tai_const.Create_sym(ll));
  581. current_asmdata.asmlists[al_const].concat(tai_align.create(const_align(sizeof(aint))));
  582. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(-1));
  583. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(strlength));
  584. current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
  585. getmem(ca,strlength+1);
  586. move(strval^,ca^,strlength);
  587. { The terminating #0 to be stored in the .data section (JM) }
  588. ca[strlength]:=#0;
  589. current_asmdata.asmlists[al_const].concat(Tai_string.Create_pchar(ca,strlength+1));
  590. end;
  591. end;
  592. st_widestring:
  593. begin
  594. { an empty ansi string is nil! }
  595. if (strlength=0) then
  596. datalist.concat(Tai_const.Create_sym(nil))
  597. else
  598. begin
  599. current_asmdata.getdatalabel(ll);
  600. datalist.concat(Tai_const.Create_sym(ll));
  601. current_asmdata.asmlists[al_const].concat(tai_align.create(const_align(sizeof(aint))));
  602. if tf_winlikewidestring in target_info.flags then
  603. current_asmdata.asmlists[al_const].concat(Tai_const.Create_32bit(strlength*cwidechartype.size))
  604. else
  605. begin
  606. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(-1));
  607. current_asmdata.asmlists[al_const].concat(Tai_const.Create_aint(strlength*cwidechartype.size));
  608. end;
  609. current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
  610. for i:=0 to strlength-1 do
  611. current_asmdata.asmlists[al_const].concat(Tai_const.Create_16bit(pcompilerwidestring(strval)^.data[i]));
  612. { ending #0 }
  613. current_asmdata.asmlists[al_const].concat(Tai_const.Create_16bit(0))
  614. end;
  615. end;
  616. st_longstring:
  617. begin
  618. internalerror(200107081);
  619. end;
  620. end;
  621. end;
  622. p.free;
  623. end;
  624. arraydef:
  625. begin
  626. { dynamic array nil }
  627. if is_dynamic_array(def) then
  628. begin
  629. { Only allow nil initialization }
  630. consume(_NIL);
  631. datalist.concat(Tai_const.Create_sym(nil));
  632. end
  633. { no packed array constants supported }
  634. else if is_packed_array(def) then
  635. begin
  636. Message(type_e_no_const_packed_array);
  637. consume_all_until(_RKLAMMER);
  638. end
  639. else
  640. if try_to_consume(_LKLAMMER) then
  641. begin
  642. for l:=tarraydef(def).lowrange to tarraydef(def).highrange-1 do
  643. begin
  644. readtypedconst(datalist,tarraydef(def).elementdef,nil,writable);
  645. consume(_COMMA);
  646. end;
  647. readtypedconst(datalist,tarraydef(def).elementdef,nil,writable);
  648. consume(_RKLAMMER);
  649. end
  650. else
  651. { if array of char then we allow also a string }
  652. if is_char(tarraydef(def).elementdef) then
  653. begin
  654. p:=comp_expr(true);
  655. if p.nodetype=stringconstn then
  656. begin
  657. len:=tstringconstnode(p).len;
  658. { For tp7 the maximum lentgh can be 255 }
  659. if (m_tp7 in current_settings.modeswitches) and
  660. (len>255) then
  661. len:=255;
  662. ca:=tstringconstnode(p).value_str;
  663. end
  664. else
  665. if is_constcharnode(p) then
  666. begin
  667. c:=chr(tordconstnode(p).value and $ff);
  668. ca:=@c;
  669. len:=1;
  670. end
  671. else
  672. begin
  673. Message(parser_e_illegal_expression);
  674. len:=0;
  675. end;
  676. if len>(tarraydef(def).highrange-tarraydef(def).lowrange+1) then
  677. Message(parser_e_string_larger_array);
  678. for i:=tarraydef(def).lowrange to tarraydef(def).highrange do
  679. begin
  680. if i+1-tarraydef(def).lowrange<=len then
  681. begin
  682. datalist.concat(Tai_const.Create_8bit(byte(ca^)));
  683. inc(ca);
  684. end
  685. else
  686. {Fill the remaining positions with #0.}
  687. datalist.concat(Tai_const.Create_8bit(0));
  688. end;
  689. p.free;
  690. end
  691. else
  692. begin
  693. { we want the ( }
  694. consume(_LKLAMMER);
  695. end;
  696. end;
  697. procvardef:
  698. begin
  699. { Procvars and pointers are no longer compatible. }
  700. { under tp: =nil or =var under fpc: =nil or =@var }
  701. if token=_NIL then
  702. begin
  703. datalist.concat(Tai_const.Create_sym(nil));
  704. if (po_methodpointer in tprocvardef(def).procoptions) then
  705. datalist.concat(Tai_const.Create_sym(nil));
  706. consume(_NIL);
  707. goto myexit;
  708. end;
  709. { you can't assign a value other than NIL to a typed constant }
  710. { which is a "procedure of object", because this also requires }
  711. { address of an object/class instance, which is not known at }
  712. { compile time (JM) }
  713. if (po_methodpointer in tprocvardef(def).procoptions) then
  714. Message(parser_e_no_procvarobj_const);
  715. { parse the rest too, so we can continue with error checking }
  716. getprocvardef:=tprocvardef(def);
  717. p:=comp_expr(true);
  718. getprocvardef:=nil;
  719. if codegenerror then
  720. begin
  721. p.free;
  722. goto myexit;
  723. end;
  724. { let type conversion check everything needed }
  725. inserttypeconv(p,def);
  726. if codegenerror then
  727. begin
  728. p.free;
  729. goto myexit;
  730. end;
  731. { remove typeconvs, that will normally insert a lea
  732. instruction which is not necessary for us }
  733. while p.nodetype=typeconvn do
  734. begin
  735. hp:=ttypeconvnode(p).left;
  736. ttypeconvnode(p).left:=nil;
  737. p.free;
  738. p:=hp;
  739. end;
  740. { remove addrn which we also don't need here }
  741. if p.nodetype=addrn then
  742. begin
  743. hp:=taddrnode(p).left;
  744. taddrnode(p).left:=nil;
  745. p.free;
  746. p:=hp;
  747. end;
  748. { we now need to have a loadn with a procsym }
  749. if (p.nodetype=loadn) and
  750. (tloadnode(p).symtableentry.typ=procsym) then
  751. begin
  752. pd:=tprocdef(tprocsym(tloadnode(p).symtableentry).ProcdefList[0]);
  753. datalist.concat(Tai_const.createname(pd.mangledname,0));
  754. end
  755. else
  756. Message(parser_e_illegal_expression);
  757. p.free;
  758. end;
  759. { reads a typed constant record }
  760. recorddef:
  761. begin
  762. { packed record }
  763. if is_packed_record_or_object(def) then
  764. Message(type_e_no_const_packed_record)
  765. { KAZ }
  766. else if (trecorddef(def)=rec_tguid) and
  767. ((token=_CSTRING) or (token=_CCHAR) or (token=_ID)) then
  768. begin
  769. p:=comp_expr(true);
  770. inserttypeconv(p,cshortstringtype);
  771. if p.nodetype=stringconstn then
  772. begin
  773. s:=strpas(tstringconstnode(p).value_str);
  774. p.free;
  775. if string2guid(s,tmpguid) then
  776. begin
  777. datalist.concat(Tai_const.Create_32bit(longint(tmpguid.D1)));
  778. datalist.concat(Tai_const.Create_16bit(tmpguid.D2));
  779. datalist.concat(Tai_const.Create_16bit(tmpguid.D3));
  780. for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
  781. datalist.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
  782. end
  783. else
  784. Message(parser_e_improper_guid_syntax);
  785. end
  786. else
  787. begin
  788. p.free;
  789. Message(parser_e_illegal_expression);
  790. goto myexit;
  791. end;
  792. end
  793. else
  794. begin
  795. consume(_LKLAMMER);
  796. sorg:='';
  797. aktpos:=0;
  798. symidx:=0;
  799. srsym:=tsym(trecorddef(def).symtable.SymList[symidx]);
  800. recsym := nil;
  801. while token<>_RKLAMMER do
  802. begin
  803. s:=pattern;
  804. sorg:=orgpattern;
  805. consume(_ID);
  806. consume(_COLON);
  807. error := false;
  808. recsym := tsym(trecorddef(def).symtable.Find(s));
  809. if not assigned(recsym) then
  810. begin
  811. Message1(sym_e_illegal_field,sorg);
  812. error := true;
  813. end;
  814. if (not error) and
  815. (not assigned(srsym) or
  816. (s <> srsym.name)) then
  817. { possible variant record (JM) }
  818. begin
  819. { All parts of a variant start at the same offset }
  820. { Also allow jumping from one variant part to another, }
  821. { as long as the offsets match }
  822. if (assigned(srsym) and
  823. (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
  824. { srsym is not assigned after parsing w2 in the }
  825. { typed const in the next example: }
  826. { type tr = record case byte of }
  827. { 1: (l1,l2: dword); }
  828. { 2: (w1,w2: word); }
  829. { end; }
  830. { const r: tr = (w1:1;w2:1;l2:5); }
  831. (tfieldvarsym(recsym).fieldoffset = aktpos) then
  832. srsym := recsym
  833. { going backwards isn't allowed in any mode }
  834. else if (tfieldvarsym(recsym).fieldoffset<aktpos) then
  835. begin
  836. Message(parser_e_invalid_record_const);
  837. error := true;
  838. end
  839. { Delphi allows you to skip fields }
  840. else if (m_delphi in current_settings.modeswitches) then
  841. begin
  842. Message1(parser_w_skipped_fields_before,sorg);
  843. srsym := recsym;
  844. end
  845. { FPC and TP don't }
  846. else
  847. begin
  848. Message1(parser_e_skipped_fields_before,sorg);
  849. error := true;
  850. end;
  851. end;
  852. if error then
  853. consume_all_until(_SEMICOLON)
  854. else
  855. begin
  856. { if needed fill (alignment) }
  857. if tfieldvarsym(srsym).fieldoffset>aktpos then
  858. for i:=1 to tfieldvarsym(srsym).fieldoffset-aktpos do
  859. datalist.concat(Tai_const.Create_8bit(0));
  860. { new position }
  861. aktpos:=tfieldvarsym(srsym).fieldoffset+tfieldvarsym(srsym).vardef.size;
  862. { read the data }
  863. readtypedconst(datalist,tfieldvarsym(srsym).vardef,nil,writable);
  864. { keep previous field for checking whether whole }
  865. { record was initialized (JM) }
  866. recsym := srsym;
  867. { goto next field }
  868. inc(symidx);
  869. if symidx<trecorddef(def).symtable.SymList.Count then
  870. srsym:=tsym(trecorddef(def).symtable.SymList[symidx])
  871. else
  872. srsym:=nil;
  873. if token=_SEMICOLON then
  874. consume(_SEMICOLON)
  875. else break;
  876. end;
  877. end;
  878. { are there any fields left? }
  879. if assigned(srsym) and
  880. { don't complain if there only come other variant parts }
  881. { after the last initialized field }
  882. ((recsym=nil) or
  883. (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)) then
  884. Message1(parser_w_skipped_fields_after,sorg);
  885. for i:=1 to def.size-aktpos do
  886. datalist.concat(Tai_const.Create_8bit(0));
  887. consume(_RKLAMMER);
  888. end;
  889. end;
  890. { reads a typed object }
  891. objectdef:
  892. begin
  893. if is_class_or_interface(def) then
  894. begin
  895. p:=comp_expr(true);
  896. if p.nodetype<>niln then
  897. begin
  898. Message(type_e_no_const_packed_array);
  899. consume_all_until(_SEMICOLON);
  900. end
  901. else
  902. begin
  903. datalist.concat(Tai_const.Create_sym(nil));
  904. end;
  905. p.free;
  906. end
  907. { for objects we allow it only if it doesn't contain a vmt }
  908. else if (oo_has_vmt in tobjectdef(def).objectoptions) and
  909. (m_fpc in current_settings.modeswitches) then
  910. Message(parser_e_type_const_not_possible)
  911. { packed object }
  912. else if is_packed_record_or_object(def) then
  913. Message(type_e_no_const_packed_record)
  914. else
  915. begin
  916. consume(_LKLAMMER);
  917. aktpos:=0;
  918. while token<>_RKLAMMER do
  919. begin
  920. s:=pattern;
  921. sorg:=orgpattern;
  922. consume(_ID);
  923. consume(_COLON);
  924. srsym:=nil;
  925. obj:=tobjectdef(def);
  926. symt:=obj.symtable;
  927. while (srsym=nil) and assigned(symt) do
  928. begin
  929. srsym:=tsym(symt.Find(s));
  930. if assigned(obj) then
  931. obj:=obj.childof;
  932. if assigned(obj) then
  933. symt:=obj.symtable
  934. else
  935. symt:=nil;
  936. end;
  937. if srsym=nil then
  938. begin
  939. Message1(sym_e_id_not_found,sorg);
  940. consume_all_until(_SEMICOLON);
  941. end
  942. else
  943. with tfieldvarsym(srsym) do
  944. begin
  945. { check position }
  946. if fieldoffset<aktpos then
  947. message(parser_e_invalid_record_const);
  948. { check in VMT needs to be added for TP mode }
  949. with Tobjectdef(def) do
  950. if not(m_fpc in current_settings.modeswitches) and
  951. (oo_has_vmt in objectoptions) and
  952. (vmt_offset<fieldoffset) then
  953. begin
  954. for i:=1 to vmt_offset-aktpos do
  955. datalist.concat(tai_const.create_8bit(0));
  956. datalist.concat(tai_const.createname(vmt_mangledname,0));
  957. { this is more general }
  958. aktpos:=vmt_offset + sizeof(aint);
  959. end;
  960. { if needed fill }
  961. if fieldoffset>aktpos then
  962. for i:=1 to fieldoffset-aktpos do
  963. datalist.concat(Tai_const.Create_8bit(0));
  964. { new position }
  965. aktpos:=fieldoffset+vardef.size;
  966. { read the data }
  967. readtypedconst(datalist,vardef,nil,writable);
  968. if not try_to_consume(_SEMICOLON) then
  969. break;
  970. end;
  971. end;
  972. if not(m_fpc in current_settings.modeswitches) and
  973. (oo_has_vmt in tobjectdef(def).objectoptions) and
  974. (tobjectdef(def).vmt_offset>=aktpos) then
  975. begin
  976. for i:=1 to tobjectdef(def).vmt_offset-aktpos do
  977. datalist.concat(tai_const.create_8bit(0));
  978. datalist.concat(tai_const.createname(tobjectdef(def).vmt_mangledname,0));
  979. { this is more general }
  980. aktpos:=tobjectdef(def).vmt_offset + sizeof(aint);
  981. end;
  982. for i:=1 to def.size-aktpos do
  983. datalist.concat(Tai_const.Create_8bit(0));
  984. consume(_RKLAMMER);
  985. end;
  986. end;
  987. errordef:
  988. begin
  989. { try to consume something useful }
  990. if token=_LKLAMMER then
  991. consume_all_until(_RKLAMMER)
  992. else
  993. consume_all_until(_SEMICOLON);
  994. end;
  995. else Message(parser_e_type_const_not_possible);
  996. end;
  997. { Parse hints and public directive }
  998. if assigned(sym) then
  999. begin
  1000. try_consume_hintdirective(sym.symoptions);
  1001. { Support public name directive }
  1002. if try_to_consume(_PUBLIC) then
  1003. begin
  1004. if try_to_consume(_NAME) then
  1005. C_name:=get_stringconst
  1006. else
  1007. C_name:=sorg;
  1008. sym.set_mangledname(C_Name);
  1009. end;
  1010. end;
  1011. myexit:
  1012. block_type:=old_block_type;
  1013. { Add symbol name if this is specified. For array
  1014. elements sym=nil and we should skip this }
  1015. if assigned(sym) then
  1016. begin
  1017. storefilepos:=current_filepos;
  1018. current_filepos:=sym.fileinfo;
  1019. { insert cut for smartlinking or alignment }
  1020. if writable then
  1021. cursectype:=sec_data
  1022. else
  1023. cursectype:=sec_rodata;
  1024. maybe_new_object_file(list);
  1025. new_section(list,cursectype,lower(sym.mangledname),const_align(def.alignment));
  1026. if (sym.owner.symtabletype=globalsymtable) or
  1027. maybe_smartlink_symbol or
  1028. (assigned(current_procinfo) and
  1029. (po_inline in current_procinfo.procdef.procoptions)) or
  1030. DLLSource then
  1031. list.concat(Tai_symbol.Createname_global(sym.mangledname,AT_DATA,0))
  1032. else
  1033. list.concat(Tai_symbol.Createname(sym.mangledname,AT_DATA,0));
  1034. list.concatlist(datalist);
  1035. list.concat(tai_symbol_end.Createname(sym.mangledname));
  1036. current_filepos:=storefilepos;
  1037. end
  1038. else
  1039. list.concatlist(datalist);
  1040. datalist.free;
  1041. end;
  1042. {$maxfpuregisters default}
  1043. end.