ptconst.pas 49 KB

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