ptconst.pas 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Reads typed constants
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ptconst;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses symtype,symsym;
  22. { this procedure reads typed constants }
  23. { sym is only needed for ansi strings }
  24. { the assembler label is in the middle (PM) }
  25. procedure readtypedconst(const t:ttype;sym : ttypedconstsym;writable : boolean);
  26. implementation
  27. uses
  28. {$ifdef Delphi}
  29. sysutils,
  30. {$else}
  31. strings,
  32. {$endif Delphi}
  33. globtype,systems,tokens,verbose,
  34. cutils,globals,widestr,scanner,
  35. symconst,symbase,symdef,symtable,
  36. aasmbase,aasmtai,aasmcpu,defutil,defcmp,
  37. { pass 1 }
  38. node,
  39. nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  40. { parser specific stuff }
  41. pbase,pexpr,
  42. { codegen }
  43. cpuinfo,cgbase
  44. ;
  45. {$ifdef fpc}
  46. {$maxfpuregisters 0}
  47. {$endif fpc}
  48. { this procedure reads typed constants }
  49. procedure readtypedconst(const t:ttype;sym : ttypedconstsym;writable : boolean);
  50. var
  51. len,base : longint;
  52. p,hp,hpstart : tnode;
  53. i,j,l,offset,
  54. varalign,
  55. strlength : longint;
  56. curconstsegment : TAAsmoutput;
  57. ll : tasmlabel;
  58. s,sorg : string;
  59. c : char;
  60. ca : pchar;
  61. tmpguid : tguid;
  62. aktpos : longint;
  63. obj : tobjectdef;
  64. recsym,
  65. srsym : tsym;
  66. symt : tsymtable;
  67. value : bestreal;
  68. strval : pchar;
  69. pw : pcompilerwidestring;
  70. error : boolean;
  71. type
  72. setbytes = array[0..31] of byte;
  73. Psetbytes = ^setbytes;
  74. procedure check_range(def:torddef);
  75. begin
  76. if ((tordconstnode(p).value>def.high) or
  77. (tordconstnode(p).value<def.low)) then
  78. begin
  79. if (cs_check_range in aktlocalswitches) then
  80. Message(parser_e_range_check_error)
  81. else
  82. Message(parser_w_range_check_error);
  83. end;
  84. end;
  85. {$R-} {Range check creates problem with init_8bit(-1) !!}
  86. begin
  87. if writable then
  88. curconstsegment:=datasegment
  89. else
  90. curconstsegment:=consts;
  91. case t.def.deftype of
  92. orddef:
  93. begin
  94. p:=comp_expr(true);
  95. case torddef(t.def).typ of
  96. bool8bit :
  97. begin
  98. if is_constboolnode(p) then
  99. curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value))
  100. else
  101. Message(cg_e_illegal_expression);
  102. end;
  103. bool16bit :
  104. begin
  105. if is_constboolnode(p) then
  106. curconstSegment.concat(Tai_const.Create_16bit(tordconstnode(p).value))
  107. else
  108. Message(cg_e_illegal_expression);
  109. end;
  110. bool32bit :
  111. begin
  112. if is_constboolnode(p) then
  113. curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value))
  114. else
  115. Message(cg_e_illegal_expression);
  116. end;
  117. uchar :
  118. begin
  119. if is_constcharnode(p) then
  120. curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value))
  121. else
  122. Message(cg_e_illegal_expression);
  123. end;
  124. uwidechar :
  125. begin
  126. if is_constcharnode(p) then
  127. inserttypeconv(p,cwidechartype);
  128. if is_constwidecharnode(p) then
  129. curconstSegment.concat(Tai_const.Create_16bit(tordconstnode(p).value))
  130. else
  131. Message(cg_e_illegal_expression);
  132. end;
  133. s8bit,
  134. u8bit :
  135. begin
  136. if is_constintnode(p) then
  137. begin
  138. curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value));
  139. check_range(torddef(t.def));
  140. end
  141. else
  142. Message(cg_e_illegal_expression);
  143. end;
  144. u16bit,
  145. s16bit :
  146. begin
  147. if is_constintnode(p) then
  148. begin
  149. curconstSegment.concat(Tai_const.Create_16bit(tordconstnode(p).value));
  150. check_range(torddef(t.def));
  151. end
  152. else
  153. Message(cg_e_illegal_expression);
  154. end;
  155. s32bit,
  156. u32bit :
  157. begin
  158. if is_constintnode(p) then
  159. begin
  160. curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value));
  161. if torddef(t.def).typ<>u32bit then
  162. check_range(torddef(t.def));
  163. end
  164. else
  165. Message(cg_e_illegal_expression);
  166. end;
  167. s64bit,
  168. u64bit:
  169. begin
  170. if is_constintnode(p) then
  171. begin
  172. if target_info.endian = endian_little then
  173. begin
  174. curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value and $ffffffff));
  175. curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value shr 32));
  176. end
  177. else
  178. begin
  179. curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value shr 32));
  180. curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value and $ffffffff));
  181. end;
  182. end
  183. else
  184. Message(cg_e_illegal_expression);
  185. end;
  186. else
  187. internalerror(3799);
  188. end;
  189. p.free;
  190. end;
  191. floatdef:
  192. begin
  193. p:=comp_expr(true);
  194. if is_constrealnode(p) then
  195. value:=trealconstnode(p).value_real
  196. else if is_constintnode(p) then
  197. value:=tordconstnode(p).value
  198. else
  199. Message(cg_e_illegal_expression);
  200. case tfloatdef(t.def).typ of
  201. s32real :
  202. curconstSegment.concat(Tai_real_32bit.Create(ts32real(value)));
  203. s64real :
  204. curconstSegment.concat(Tai_real_64bit.Create(ts64real(value)));
  205. s80real :
  206. curconstSegment.concat(Tai_real_80bit.Create(value));
  207. {$ifdef ver1_0}
  208. s64comp :
  209. curconstSegment.concat(Tai_comp_64bit.Create(value));
  210. {$else ver1_0}
  211. { the round is necessary for native compilers where comp isn't a float }
  212. s64comp :
  213. curconstSegment.concat(Tai_comp_64bit.Create(round(value)));
  214. {$endif ver1_0}
  215. else
  216. internalerror(18);
  217. end;
  218. p.free;
  219. end;
  220. classrefdef:
  221. begin
  222. p:=comp_expr(true);
  223. case p.nodetype of
  224. loadvmtaddrn:
  225. begin
  226. if not(tobjectdef(tclassrefdef(p.resulttype.def).pointertype.def).is_related(
  227. tobjectdef(tclassrefdef(t.def).pointertype.def))) then
  228. Message(cg_e_illegal_expression);
  229. curconstSegment.concat(Tai_const_symbol.Create(objectlibrary.newasmsymboldata(tobjectdef(
  230. tclassrefdef(p.resulttype.def).pointertype.def).vmt_mangledname)));
  231. end;
  232. niln:
  233. curconstSegment.concat(Tai_const.Create_32bit(0));
  234. else Message(cg_e_illegal_expression);
  235. end;
  236. p.free;
  237. end;
  238. pointerdef:
  239. begin
  240. p:=comp_expr(true);
  241. if (p.nodetype=typeconvn) and
  242. (ttypeconvnode(p).left.nodetype in [addrn,niln]) and
  243. equal_defs(t.def,p.resulttype.def) then
  244. begin
  245. hp:=ttypeconvnode(p).left;
  246. ttypeconvnode(p).left:=nil;
  247. p.free;
  248. p:=hp;
  249. end;
  250. { allows horrible ofs(typeof(TButton)^) code !! }
  251. if (p.nodetype=addrn) and
  252. (taddrnode(p).left.nodetype=derefn) then
  253. begin
  254. hp:=tderefnode(taddrnode(p).left).left;
  255. tderefnode(taddrnode(p).left).left:=nil;
  256. p.free;
  257. p:=hp;
  258. end;
  259. { const pointer ? }
  260. if (p.nodetype = pointerconstn) then
  261. curconstsegment.concat(Tai_const.Create_32bit(
  262. tpointerconstnode(p).value))
  263. { nil pointer ? }
  264. else if p.nodetype=niln then
  265. curconstSegment.concat(Tai_const.Create_32bit(0))
  266. { maybe pchar ? }
  267. else
  268. if is_char(tpointerdef(t.def).pointertype.def) and
  269. (p.nodetype<>addrn) then
  270. begin
  271. objectlibrary.getdatalabel(ll);
  272. curconstSegment.concat(Tai_const_symbol.Create(ll));
  273. if p.nodetype=stringconstn then
  274. varalign:=tstringconstnode(p).len
  275. else
  276. varalign:=0;
  277. varalign:=const_align(varalign);
  278. Consts.concat(Tai_align.Create(varalign));
  279. Consts.concat(Tai_label.Create(ll));
  280. if p.nodetype=stringconstn then
  281. begin
  282. len:=tstringconstnode(p).len;
  283. { For tp7 the maximum lentgh can be 255 }
  284. if (m_tp7 in aktmodeswitches) and
  285. (len>255) then
  286. len:=255;
  287. getmem(ca,len+2);
  288. move(tstringconstnode(p).value_str^,ca^,len+1);
  289. Consts.concat(Tai_string.Create_length_pchar(ca,len+1));
  290. end
  291. else
  292. if is_constcharnode(p) then
  293. Consts.concat(Tai_string.Create(char(byte(tordconstnode(p).value))+#0))
  294. else
  295. Message(cg_e_illegal_expression);
  296. end
  297. { maybe pwidechar ? }
  298. else
  299. if is_widechar(tpointerdef(t.def).pointertype.def) and
  300. (p.nodetype<>addrn) then
  301. begin
  302. objectlibrary.getdatalabel(ll);
  303. curconstSegment.concat(Tai_const_symbol.Create(ll));
  304. Consts.concat(tai_align.create(const_align(pointer_size)));
  305. Consts.concat(Tai_label.Create(ll));
  306. if (p.nodetype in [stringconstn,ordconstn]) then
  307. begin
  308. { convert to widestring stringconstn }
  309. inserttypeconv(p,cwidestringtype);
  310. if (p.nodetype=stringconstn) and
  311. (tstringconstnode(p).st_type=st_widestring) then
  312. begin
  313. pw:=pcompilerwidestring(tstringconstnode(p).value_str);
  314. for i:=0 to tstringconstnode(p).len-1 do
  315. Consts.concat(Tai_const.Create_16bit(pw^.data[i]));
  316. { ending #0 }
  317. Consts.concat(Tai_const.Create_16bit(0))
  318. end;
  319. end
  320. else
  321. Message(cg_e_illegal_expression);
  322. end
  323. else
  324. if p.nodetype=addrn then
  325. begin
  326. inserttypeconv(p,t);
  327. { if a typeconv node was inserted then check if it was an tc_equal. If
  328. true then we remove the node. If not tc_equal then we leave the typeconvn
  329. and the nodetype=loadn will always be false and generate the error (PFV) }
  330. if (p.nodetype=typeconvn) then
  331. begin
  332. if (ttypeconvnode(p).convtype=tc_equal) then
  333. hpstart:=taddrnode(ttypeconvnode(p).left).left
  334. else
  335. hpstart:=p;
  336. end
  337. else
  338. hpstart:=taddrnode(p).left;
  339. hp:=hpstart;
  340. while assigned(hp) and (hp.nodetype in [subscriptn,vecn]) do
  341. hp:=tunarynode(hp).left;
  342. if (hp.nodetype=loadn) then
  343. begin
  344. hp:=hpstart;
  345. offset:=0;
  346. while assigned(hp) and (hp.nodetype<>loadn) do
  347. begin
  348. case hp.nodetype of
  349. vecn :
  350. begin
  351. case tvecnode(hp).left.resulttype.def.deftype of
  352. stringdef :
  353. begin
  354. { this seems OK for shortstring and ansistrings PM }
  355. { it is wrong for widestrings !! }
  356. len:=1;
  357. base:=0;
  358. end;
  359. arraydef :
  360. begin
  361. len:=tarraydef(tvecnode(hp).left.resulttype.def).elesize;
  362. base:=tarraydef(tvecnode(hp).left.resulttype.def).lowrange;
  363. end
  364. else
  365. Message(cg_e_illegal_expression);
  366. end;
  367. if is_constintnode(tvecnode(hp).right) then
  368. inc(offset,len*(get_ordinal_value(tvecnode(hp).right)-base))
  369. else
  370. Message(cg_e_illegal_expression);
  371. end;
  372. subscriptn :
  373. inc(offset,tsubscriptnode(hp).vs.fieldoffset)
  374. else
  375. Message(cg_e_illegal_expression);
  376. end;
  377. hp:=tbinarynode(hp).left;
  378. end;
  379. srsym:=tloadnode(hp).symtableentry;
  380. case srsym.typ of
  381. procsym :
  382. begin
  383. if Tprocsym(srsym).procdef_count>1 then
  384. Message(parser_e_no_overloaded_procvars);
  385. if po_abstractmethod in tprocsym(srsym).first_procdef.procoptions then
  386. Message(type_e_cant_take_address_of_abstract_method)
  387. else
  388. curconstSegment.concat(Tai_const_symbol.Createname_offset(tprocsym(srsym).first_procdef.mangledname,offset));
  389. end;
  390. varsym :
  391. curconstSegment.concat(Tai_const_symbol.Createname_offset(tvarsym(srsym).mangledname,offset));
  392. typedconstsym :
  393. curconstSegment.concat(Tai_const_symbol.Createname_offset(ttypedconstsym(srsym).mangledname,offset));
  394. else
  395. Message(type_e_variable_id_expected);
  396. end;
  397. end
  398. else
  399. Message(cg_e_illegal_expression);
  400. end
  401. else
  402. { allow typeof(Object type)}
  403. if (p.nodetype=inlinen) and
  404. (tinlinenode(p).inlinenumber=in_typeof_x) then
  405. begin
  406. if (tinlinenode(p).left.nodetype=typen) then
  407. begin
  408. curconstSegment.concat(Tai_const_symbol.createname(
  409. tobjectdef(tinlinenode(p).left.resulttype.def).vmt_mangledname));
  410. end
  411. else
  412. Message(cg_e_illegal_expression);
  413. end
  414. else
  415. Message(cg_e_illegal_expression);
  416. p.free;
  417. end;
  418. setdef:
  419. begin
  420. p:=comp_expr(true);
  421. if p.nodetype=setconstn then
  422. begin
  423. { be sure to convert to the correct result, else
  424. it can generate smallset data instead of normalset (PFV) }
  425. inserttypeconv(p,t);
  426. { we only allow const sets }
  427. if assigned(tsetconstnode(p).left) then
  428. Message(cg_e_illegal_expression)
  429. else
  430. begin
  431. { this writing is endian independant }
  432. { untrue - because they are considered }
  433. { arrays of 32-bit values CEC }
  434. if source_info.endian = target_info.endian then
  435. begin
  436. for l:=0 to p.resulttype.def.size-1 do
  437. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[l]));
  438. end
  439. else
  440. begin
  441. { store as longint values in swaped format }
  442. j:=0;
  443. for l:=0 to ((p.resulttype.def.size-1) div 4) do
  444. begin
  445. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+3]));
  446. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+2]));
  447. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j+1]));
  448. curconstsegment.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[j]));
  449. Inc(j,4);
  450. end;
  451. end;
  452. end;
  453. end
  454. else
  455. Message(cg_e_illegal_expression);
  456. p.free;
  457. end;
  458. enumdef:
  459. begin
  460. p:=comp_expr(true);
  461. if p.nodetype=ordconstn then
  462. begin
  463. if equal_defs(p.resulttype.def,t.def) or
  464. is_subequal(p.resulttype.def,t.def) then
  465. begin
  466. case p.resulttype.def.size of
  467. 1 : curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value));
  468. 2 : curconstSegment.concat(Tai_const.Create_16bit(tordconstnode(p).value));
  469. 4 : curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value));
  470. end;
  471. end
  472. else
  473. IncompatibleTypes(t.def,p.resulttype.def);
  474. end
  475. else
  476. Message(cg_e_illegal_expression);
  477. p.free;
  478. end;
  479. stringdef:
  480. begin
  481. p:=comp_expr(true);
  482. { load strval and strlength of the constant tree }
  483. if p.nodetype=stringconstn then
  484. begin
  485. { convert to the expected string type so that
  486. for widestrings strval is a pcompilerwidestring }
  487. inserttypeconv(p,t);
  488. strlength:=tstringconstnode(p).len;
  489. strval:=tstringconstnode(p).value_str;
  490. end
  491. else if is_constcharnode(p) then
  492. begin
  493. { strval:=pchar(@tordconstnode(p).value);
  494. THIS FAIL on BIG_ENDIAN MACHINES PM }
  495. c:=chr(tordconstnode(p).value and $ff);
  496. strval:=@c;
  497. strlength:=1
  498. end
  499. else if is_constresourcestringnode(p) then
  500. begin
  501. strval:=pchar(tconstsym(tloadnode(p).symtableentry).value.valueptr);
  502. strlength:=tconstsym(tloadnode(p).symtableentry).value.len;
  503. end
  504. else
  505. begin
  506. Message(cg_e_illegal_expression);
  507. strlength:=-1;
  508. end;
  509. if strlength>=0 then
  510. begin
  511. case tstringdef(t.def).string_typ of
  512. st_shortstring:
  513. begin
  514. if strlength>=t.def.size then
  515. begin
  516. message2(parser_w_string_too_long,strpas(strval),tostr(t.def.size-1));
  517. strlength:=t.def.size-1;
  518. end;
  519. curconstSegment.concat(Tai_const.Create_8bit(strlength));
  520. { this can also handle longer strings }
  521. getmem(ca,strlength+1);
  522. move(strval^,ca^,strlength);
  523. ca[strlength]:=#0;
  524. curconstSegment.concat(Tai_string.Create_length_pchar(ca,strlength));
  525. { fillup with spaces if size is shorter }
  526. if t.def.size>strlength then
  527. begin
  528. getmem(ca,t.def.size-strlength);
  529. { def.size contains also the leading length, so we }
  530. { we have to subtract one }
  531. fillchar(ca[0],t.def.size-strlength-1,' ');
  532. ca[t.def.size-strlength-1]:=#0;
  533. { this can also handle longer strings }
  534. curconstSegment.concat(Tai_string.Create_length_pchar(ca,t.def.size-strlength-1));
  535. end;
  536. end;
  537. st_ansistring:
  538. begin
  539. { an empty ansi string is nil! }
  540. if (strlength=0) then
  541. curconstSegment.concat(Tai_const.Create_32bit(0))
  542. else
  543. begin
  544. objectlibrary.getdatalabel(ll);
  545. curconstSegment.concat(Tai_const_symbol.Create(ll));
  546. { the actual structure starts at -12 from start label - CEC }
  547. Consts.concat(tai_align.create(const_align(pointer_size)));
  548. { first write the maximum size }
  549. Consts.concat(Tai_const.Create_32bit(strlength));
  550. { second write the real length }
  551. Consts.concat(Tai_const.Create_32bit(strlength));
  552. { redondent with maxlength but who knows ... (PM) }
  553. { third write use count (set to -1 for safety ) }
  554. Consts.concat(Tai_const.Create_32bit(-1));
  555. Consts.concat(Tai_label.Create(ll));
  556. getmem(ca,strlength+2);
  557. move(strval^,ca^,strlength);
  558. { The terminating #0 to be stored in the .data section (JM) }
  559. ca[strlength]:=#0;
  560. { End of the PChar. The memory has to be allocated because in }
  561. { tai_string.done, there is a freemem(len+1) (JM) }
  562. ca[strlength+1]:=#0;
  563. Consts.concat(Tai_string.Create_length_pchar(ca,strlength+1));
  564. end;
  565. end;
  566. st_widestring:
  567. begin
  568. { an empty ansi string is nil! }
  569. if (strlength=0) then
  570. curconstSegment.concat(Tai_const.Create_32bit(0))
  571. else
  572. begin
  573. objectlibrary.getdatalabel(ll);
  574. curconstSegment.concat(Tai_const_symbol.Create(ll));
  575. { the actual structure starts at -12 from start label - CEC }
  576. Consts.concat(tai_align.create(const_align(pointer_size)));
  577. Consts.concat(Tai_const.Create_32bit(strlength));
  578. Consts.concat(Tai_const.Create_32bit(strlength));
  579. Consts.concat(Tai_const.Create_32bit(-1));
  580. Consts.concat(Tai_label.Create(ll));
  581. for i:=0 to strlength-1 do
  582. Consts.concat(Tai_const.Create_16bit(pcompilerwidestring(strval)^.data[i]));
  583. { ending #0 }
  584. Consts.concat(Tai_const.Create_16bit(0))
  585. end;
  586. end;
  587. st_longstring:
  588. begin
  589. internalerror(200107081);
  590. {curconstSegment.concat(Tai_const.Create_32bit(strlength))));
  591. curconstSegment.concat(Tai_const.Create_8bit(0));
  592. getmem(ca,strlength+1);
  593. move(strval^,ca^,strlength);
  594. ca[strlength]:=#0;
  595. generate_pascii(consts,ca,strlength);
  596. curconstSegment.concat(Tai_const.Create_8bit(0));}
  597. end;
  598. end;
  599. end;
  600. p.free;
  601. end;
  602. arraydef:
  603. begin
  604. if try_to_consume(_LKLAMMER) then
  605. begin
  606. for l:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange-1 do
  607. begin
  608. readtypedconst(tarraydef(t.def).elementtype,nil,writable);
  609. consume(_COMMA);
  610. end;
  611. readtypedconst(tarraydef(t.def).elementtype,nil,writable);
  612. consume(_RKLAMMER);
  613. end
  614. else
  615. { if array of char then we allow also a string }
  616. if is_char(tarraydef(t.def).elementtype.def) then
  617. begin
  618. p:=comp_expr(true);
  619. if p.nodetype=stringconstn then
  620. begin
  621. len:=tstringconstnode(p).len;
  622. { For tp7 the maximum lentgh can be 255 }
  623. if (m_tp7 in aktmodeswitches) and
  624. (len>255) then
  625. len:=255;
  626. ca:=tstringconstnode(p).value_str;
  627. end
  628. else
  629. if is_constcharnode(p) then
  630. begin
  631. c:=chr(tordconstnode(p).value and $ff);
  632. ca:=@c;
  633. len:=1;
  634. end
  635. else
  636. begin
  637. Message(cg_e_illegal_expression);
  638. len:=0;
  639. end;
  640. if len>(tarraydef(t.def).highrange-tarraydef(t.def).lowrange+1) then
  641. Message(parser_e_string_larger_array);
  642. for i:=tarraydef(t.def).lowrange to tarraydef(t.def).highrange do
  643. begin
  644. if i+1-tarraydef(t.def).lowrange<=len then
  645. begin
  646. curconstSegment.concat(Tai_const.Create_8bit(byte(ca^)));
  647. inc(ca);
  648. end
  649. else
  650. {Fill the remaining positions with #0.}
  651. curconstSegment.concat(Tai_const.Create_8bit(0));
  652. end;
  653. p.free;
  654. end
  655. else
  656. { dynamic array nil }
  657. if is_dynamic_array(t.def) then
  658. begin
  659. { Only allow nil initialization }
  660. consume(_NIL);
  661. curconstSegment.concat(Tai_const.Create_32bit(0));
  662. end
  663. else
  664. begin
  665. { we want the ( }
  666. consume(_LKLAMMER);
  667. end;
  668. end;
  669. procvardef:
  670. begin
  671. { Procvars and pointers are no longer compatible. }
  672. { under tp: =nil or =var under fpc: =nil or =@var }
  673. if token=_NIL then
  674. begin
  675. curconstSegment.concat(Tai_const.Create_32bit(0));
  676. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  677. curconstSegment.concat(Tai_const.Create_32bit(0));
  678. consume(_NIL);
  679. exit;
  680. end;
  681. { you can't assign a value other than NIL to a typed constant }
  682. { which is a "procedure of object", because this also requires }
  683. { address of an object/class instance, which is not known at }
  684. { compile time (JM) }
  685. if (po_methodpointer in tprocvardef(t.def).procoptions) then
  686. Message(parser_e_no_procvarobj_const);
  687. { parse the rest too, so we can continue with error checking }
  688. getprocvardef:=tprocvardef(t.def);
  689. p:=comp_expr(true);
  690. getprocvardef:=nil;
  691. if codegenerror then
  692. begin
  693. p.free;
  694. exit;
  695. end;
  696. { let type conversion check everything needed }
  697. inserttypeconv(p,t);
  698. if codegenerror then
  699. begin
  700. p.free;
  701. exit;
  702. end;
  703. { remove typeconvn, that will normally insert a lea
  704. instruction which is not necessary for us }
  705. if p.nodetype=typeconvn then
  706. begin
  707. hp:=ttypeconvnode(p).left;
  708. ttypeconvnode(p).left:=nil;
  709. p.free;
  710. p:=hp;
  711. end;
  712. { remove addrn which we also don't need here }
  713. if p.nodetype=addrn then
  714. begin
  715. hp:=taddrnode(p).left;
  716. taddrnode(p).left:=nil;
  717. p.free;
  718. p:=hp;
  719. end;
  720. { we now need to have a loadn with a procsym }
  721. if (p.nodetype=loadn) and
  722. (tloadnode(p).symtableentry.typ=procsym) then
  723. begin
  724. curconstSegment.concat(Tai_const_symbol.createname(
  725. tprocsym(tloadnode(p).symtableentry).first_procdef.mangledname));
  726. end
  727. else
  728. Message(cg_e_illegal_expression);
  729. p.free;
  730. end;
  731. { reads a typed constant record }
  732. recorddef:
  733. begin
  734. { KAZ }
  735. if (trecorddef(t.def)=rec_tguid) and
  736. ((token=_CSTRING) or (token=_CCHAR) or (token=_ID)) then
  737. begin
  738. p:=comp_expr(true);
  739. inserttypeconv(p,cshortstringtype);
  740. if p.nodetype=stringconstn then
  741. begin
  742. s:=strpas(tstringconstnode(p).value_str);
  743. p.free;
  744. if string2guid(s,tmpguid) then
  745. begin
  746. curconstSegment.concat(Tai_const.Create_32bit(tmpguid.D1));
  747. curconstSegment.concat(Tai_const.Create_16bit(tmpguid.D2));
  748. curconstSegment.concat(Tai_const.Create_16bit(tmpguid.D3));
  749. for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
  750. curconstSegment.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
  751. end
  752. else
  753. Message(parser_e_improper_guid_syntax);
  754. end
  755. else
  756. begin
  757. p.free;
  758. Message(cg_e_illegal_expression);
  759. exit;
  760. end;
  761. end
  762. else
  763. begin
  764. consume(_LKLAMMER);
  765. sorg:='';
  766. aktpos:=0;
  767. srsym := tsym(trecorddef(t.def).symtable.symindex.first);
  768. recsym := nil;
  769. while token<>_RKLAMMER do
  770. begin
  771. s:=pattern;
  772. sorg:=orgpattern;
  773. consume(_ID);
  774. consume(_COLON);
  775. error := false;
  776. recsym := tsym(trecorddef(t.def).symtable.search(s));
  777. if not assigned(recsym) then
  778. begin
  779. Message1(sym_e_illegal_field,sorg);
  780. error := true;
  781. end;
  782. if (not error) and
  783. (not assigned(srsym) or
  784. (s <> srsym.name)) then
  785. { possible variant record (JM) }
  786. begin
  787. { All parts of a variant start at the same offset }
  788. { Also allow jumping from one variant part to another, }
  789. { as long as the offsets match }
  790. if (assigned(srsym) and
  791. (tvarsym(recsym).fieldoffset = tvarsym(srsym).fieldoffset)) or
  792. { srsym is not assigned after parsing w2 in the }
  793. { typed const in the next example: }
  794. { type tr = record case byte of }
  795. { 1: (l1,l2: dword); }
  796. { 2: (w1,w2: word); }
  797. { end; }
  798. { const r: tr = (w1:1;w2:1;l2:5); }
  799. (tvarsym(recsym).fieldoffset = aktpos) then
  800. srsym := recsym
  801. { going backwards isn't allowed in any mode }
  802. else if (tvarsym(recsym).fieldoffset<aktpos) then
  803. begin
  804. Message(parser_e_invalid_record_const);
  805. error := true;
  806. end
  807. { Delphi allows you to skip fields }
  808. else if (m_delphi in aktmodeswitches) then
  809. begin
  810. Message1(parser_w_skipped_fields_before,sorg);
  811. srsym := recsym;
  812. end
  813. { FPC and TP don't }
  814. else
  815. begin
  816. Message1(parser_e_skipped_fields_before,sorg);
  817. error := true;
  818. end;
  819. end;
  820. if error then
  821. consume_all_until(_SEMICOLON)
  822. else
  823. begin
  824. { if needed fill (alignment) }
  825. if tvarsym(srsym).fieldoffset>aktpos then
  826. for i:=1 to tvarsym(srsym).fieldoffset-aktpos do
  827. curconstSegment.concat(Tai_const.Create_8bit(0));
  828. { new position }
  829. aktpos:=tvarsym(srsym).fieldoffset+tvarsym(srsym).vartype.def.size;
  830. { read the data }
  831. readtypedconst(tvarsym(srsym).vartype,nil,writable);
  832. { keep previous field for checking whether whole }
  833. { record was initialized (JM) }
  834. recsym := srsym;
  835. { goto next field }
  836. srsym := tsym(srsym.indexnext);
  837. if token=_SEMICOLON then
  838. consume(_SEMICOLON)
  839. else break;
  840. end;
  841. end;
  842. { are there any fields left? }
  843. if assigned(srsym) and
  844. { don't complain if there only come other variant parts }
  845. { after the last initialized field }
  846. ((recsym=nil) or
  847. (tvarsym(srsym).fieldoffset > tvarsym(recsym).fieldoffset)) then
  848. Message1(parser_w_skipped_fields_after,sorg);
  849. for i:=1 to t.def.size-aktpos do
  850. curconstSegment.concat(Tai_const.Create_8bit(0));
  851. consume(_RKLAMMER);
  852. end;
  853. end;
  854. { reads a typed object }
  855. objectdef:
  856. begin
  857. if is_class_or_interface(t.def) then
  858. begin
  859. p:=comp_expr(true);
  860. if p.nodetype<>niln then
  861. begin
  862. Message(parser_e_type_const_not_possible);
  863. consume_all_until(_RKLAMMER);
  864. end
  865. else
  866. begin
  867. curconstSegment.concat(Tai_const.Create_32bit(0));
  868. end;
  869. p.free;
  870. end
  871. { for objects we allow it only if it doesn't contain a vmt }
  872. else if (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  873. (m_fpc in aktmodeswitches) then
  874. Message(parser_e_type_const_not_possible)
  875. else
  876. begin
  877. consume(_LKLAMMER);
  878. aktpos:=0;
  879. while token<>_RKLAMMER do
  880. begin
  881. s:=pattern;
  882. sorg:=orgpattern;
  883. consume(_ID);
  884. consume(_COLON);
  885. srsym:=nil;
  886. obj:=tobjectdef(t.def);
  887. symt:=obj.symtable;
  888. while (srsym=nil) and assigned(symt) do
  889. begin
  890. srsym:=tsym(symt.search(s));
  891. if assigned(obj) then
  892. obj:=obj.childof;
  893. if assigned(obj) then
  894. symt:=obj.symtable
  895. else
  896. symt:=nil;
  897. end;
  898. if srsym=nil then
  899. begin
  900. Message1(sym_e_id_not_found,sorg);
  901. consume_all_until(_SEMICOLON);
  902. end
  903. else
  904. begin
  905. { check position }
  906. if tvarsym(srsym).fieldoffset<aktpos then
  907. Message(parser_e_invalid_record_const);
  908. { check in VMT needs to be added for TP mode }
  909. if not(m_fpc in aktmodeswitches) and
  910. (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  911. (tobjectdef(t.def).vmt_offset<tvarsym(srsym).fieldoffset) then
  912. begin
  913. for i:=1 to tobjectdef(t.def).vmt_offset-aktpos do
  914. curconstsegment.concat(tai_const.create_8bit(0));
  915. curconstsegment.concat(tai_const_symbol.createname(tobjectdef(t.def).vmt_mangledname));
  916. { this is more general }
  917. aktpos:=tobjectdef(t.def).vmt_offset + pointer_size;
  918. end;
  919. { if needed fill }
  920. if tvarsym(srsym).fieldoffset>aktpos then
  921. for i:=1 to tvarsym(srsym).fieldoffset-aktpos do
  922. curconstSegment.concat(Tai_const.Create_8bit(0));
  923. { new position }
  924. aktpos:=tvarsym(srsym).fieldoffset+tvarsym(srsym).vartype.def.size;
  925. { read the data }
  926. readtypedconst(tvarsym(srsym).vartype,nil,writable);
  927. if token=_SEMICOLON then
  928. consume(_SEMICOLON)
  929. else break;
  930. end;
  931. end;
  932. if not(m_fpc in aktmodeswitches) and
  933. (oo_has_vmt in tobjectdef(t.def).objectoptions) and
  934. (tobjectdef(t.def).vmt_offset>=aktpos) then
  935. begin
  936. for i:=1 to tobjectdef(t.def).vmt_offset-aktpos do
  937. curconstsegment.concat(tai_const.create_8bit(0));
  938. curconstsegment.concat(tai_const_symbol.createname(tobjectdef(t.def).vmt_mangledname));
  939. { this is more general }
  940. aktpos:=tobjectdef(t.def).vmt_offset + pointer_size;
  941. end;
  942. for i:=1 to t.def.size-aktpos do
  943. curconstSegment.concat(Tai_const.Create_8bit(0));
  944. consume(_RKLAMMER);
  945. end;
  946. end;
  947. errordef:
  948. begin
  949. { try to consume something useful }
  950. if token=_LKLAMMER then
  951. consume_all_until(_RKLAMMER)
  952. else
  953. consume_all_until(_SEMICOLON);
  954. end;
  955. else Message(parser_e_type_const_not_possible);
  956. end;
  957. end;
  958. {$ifdef fpc}
  959. {$maxfpuregisters default}
  960. {$endif fpc}
  961. end.
  962. {
  963. $Log$
  964. Revision 1.72 2003-10-21 18:16:13 peter
  965. * IncompatibleTypes() added that will include unit names when
  966. the typenames are the same
  967. Revision 1.71 2003/09/23 17:56:06 peter
  968. * locals and paras are allocated in the code generation
  969. * tvarsym.localloc contains the location of para/local when
  970. generating code for the current procedure
  971. Revision 1.70 2003/09/03 15:55:01 peter
  972. * NEWRA branch merged
  973. Revision 1.69 2003/05/09 17:47:03 peter
  974. * self moved to hidden parameter
  975. * removed hdisposen,hnewn,selfn
  976. Revision 1.68 2003/04/30 20:53:32 florian
  977. * error when address of an abstract method is taken
  978. * fixed some x86-64 problems
  979. * merged some more x86-64 and i386 code
  980. Revision 1.67 2003/04/24 22:29:58 florian
  981. * fixed a lot of PowerPC related stuff
  982. Revision 1.66 2003/04/06 21:11:23 olle
  983. * changed newasmsymbol to newasmsymboldata for data symbols
  984. Revision 1.65 2003/03/17 21:42:32 peter
  985. * allow nil initialization of dynamic array
  986. Revision 1.64 2003/01/02 20:45:08 peter
  987. * fix uninited var
  988. Revision 1.63 2002/12/26 12:34:54 florian
  989. * fixed support for type widechar consts
  990. Revision 1.62 2002/12/07 14:15:33 carl
  991. + add some explicit typecasts to remove some warnings
  992. Revision 1.61 2002/11/25 18:43:33 carl
  993. - removed the invalid if <> checking (Delphi is strange on this)
  994. + implemented abstract warning on instance creation of class with
  995. abstract methods.
  996. * some error message cleanups
  997. Revision 1.60 2002/11/25 17:43:23 peter
  998. * splitted defbase in defutil,symutil,defcmp
  999. * merged isconvertable and is_equal into compare_defs(_ext)
  1000. * made operator search faster by walking the list only once
  1001. Revision 1.59 2002/11/22 22:48:10 carl
  1002. * memory optimization with tconstsym (1.5%)
  1003. Revision 1.58 2002/11/09 15:31:57 carl
  1004. + align ansi/wide string constants
  1005. Revision 1.57 2002/09/06 19:58:31 carl
  1006. * start bugfix 1996
  1007. * 64-bit typed constant now work correctly and fully (bugfix 2001)
  1008. Revision 1.56 2002/09/03 16:26:27 daniel
  1009. * Make Tprocdef.defs protected
  1010. Revision 1.55 2002/08/11 14:32:27 peter
  1011. * renamed current_library to objectlibrary
  1012. Revision 1.54 2002/08/11 13:24:13 peter
  1013. * saving of asmsymbols in ppu supported
  1014. * asmsymbollist global is removed and moved into a new class
  1015. tasmlibrarydata that will hold the info of a .a file which
  1016. corresponds with a single module. Added librarydata to tmodule
  1017. to keep the library info stored for the module. In the future the
  1018. objectfiles will also be stored to the tasmlibrarydata class
  1019. * all getlabel/newasmsymbol and friends are moved to the new class
  1020. Revision 1.53 2002/07/23 12:34:30 daniel
  1021. * Readded old set code. To use it define 'oldset'. Activated by default
  1022. for ppc.
  1023. Revision 1.52 2002/07/22 11:48:04 daniel
  1024. * Sets are now internally sets.
  1025. Revision 1.51 2002/07/20 11:57:56 florian
  1026. * types.pas renamed to defbase.pas because D6 contains a types
  1027. unit so this would conflicts if D6 programms are compiled
  1028. + Willamette/SSE2 instructions to assembler added
  1029. Revision 1.50 2002/07/01 18:46:25 peter
  1030. * internal linker
  1031. * reorganized aasm layer
  1032. Revision 1.49 2002/05/18 13:34:16 peter
  1033. * readded missing revisions
  1034. Revision 1.48 2002/05/16 19:46:44 carl
  1035. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1036. + try to fix temp allocation (still in ifdef)
  1037. + generic constructor calls
  1038. + start of tassembler / tmodulebase class cleanup
  1039. Revision 1.46 2002/05/12 16:53:09 peter
  1040. * moved entry and exitcode to ncgutil and cgobj
  1041. * foreach gets extra argument for passing local data to the
  1042. iterator function
  1043. * -CR checks also class typecasts at runtime by changing them
  1044. into as
  1045. * fixed compiler to cycle with the -CR option
  1046. * fixed stabs with elf writer, finally the global variables can
  1047. be watched
  1048. * removed a lot of routines from cga unit and replaced them by
  1049. calls to cgobj
  1050. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1051. u32bit then the other is typecasted also to u32bit without giving
  1052. a rangecheck warning/error.
  1053. * fixed pascal calling method with reversing also the high tree in
  1054. the parast, detected by tcalcst3 test
  1055. Revision 1.45 2002/04/23 19:16:35 peter
  1056. * add pinline unit that inserts compiler supported functions using
  1057. one or more statements
  1058. * moved finalize and setlength from ninl to pinline
  1059. Revision 1.44 2002/04/20 21:32:24 carl
  1060. + generic FPC_CHECKPOINTER
  1061. + first parameter offset in stack now portable
  1062. * rename some constants
  1063. + move some cpu stuff to other units
  1064. - remove unused constents
  1065. * fix stacksize for some targets
  1066. * fix generic size problems which depend now on EXTEND_SIZE constant
  1067. Revision 1.43 2002/04/15 19:01:53 carl
  1068. + target_info.size_of_pointer -> pointer_Size
  1069. Revision 1.42 2002/04/04 19:06:03 peter
  1070. * removed unused units
  1071. * use tlocation.size in cg.a_*loc*() routines
  1072. Revision 1.41 2002/01/24 18:25:49 peter
  1073. * implicit result variable generation for assembler routines
  1074. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  1075. Revision 1.40 2002/01/06 21:47:32 peter
  1076. * removed getprocvar, use only getprocvardef
  1077. }