ptconst.pas 50 KB

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