ptconst.pas 43 KB

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