ngtcon.pas 79 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174
  1. {
  2. Copyright (c) 1998-2011 by Florian Klaempfl, Jonas Maebe
  3. Generates code/nodes for typed constant declarations
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ngtcon;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,cclasses,constexp,
  22. aasmbase,aasmdata,aasmtai,aasmcnst,
  23. node,nbas,
  24. symconst, symtype, symbase, symdef,symsym;
  25. type
  26. ttypedconstbuilder = class
  27. protected
  28. current_old_block_type : tblock_type;
  29. tcsym: tstaticvarsym;
  30. { this procedure reads typed constants }
  31. procedure read_typed_const_data(def:tdef);
  32. procedure parse_orddef(def: torddef);
  33. procedure parse_floatdef(def: tfloatdef);
  34. procedure parse_classrefdef(def: tclassrefdef);
  35. procedure parse_pointerdef(def: tpointerdef);
  36. procedure parse_setdef(def: tsetdef);
  37. procedure parse_enumdef(def: tenumdef);
  38. procedure parse_stringdef(def: tstringdef);
  39. procedure parse_arraydef(def:tarraydef);virtual;abstract;
  40. procedure parse_procvardef(def:tprocvardef);virtual;abstract;
  41. procedure parse_recorddef(def:trecorddef);virtual;abstract;
  42. procedure parse_objectdef(def:tobjectdef);virtual;abstract;
  43. procedure tc_emit_orddef(def: torddef; var node: tnode);virtual;abstract;
  44. procedure tc_emit_floatdef(def: tfloatdef; var node: tnode);virtual;abstract;
  45. procedure tc_emit_classrefdef(def: tclassrefdef; var node: tnode);virtual;abstract;
  46. procedure tc_emit_pointerdef(def: tpointerdef; var node: tnode);virtual;abstract;
  47. procedure tc_emit_setdef(def: tsetdef; var node: tnode);virtual;abstract;
  48. procedure tc_emit_enumdef(def: tenumdef; var node: tnode);virtual;abstract;
  49. procedure tc_emit_stringdef(def: tstringdef; var node: tnode);virtual;abstract;
  50. public
  51. constructor create(sym: tstaticvarsym);
  52. end;
  53. ttypedconstbuilderclass = class of ttypedconstbuilder;
  54. { should be changed into nested type of tasmlisttypedconstbuilder when
  55. possible }
  56. tbitpackedval = record
  57. curval, nextval: aword;
  58. curbitoffset: smallint;
  59. loadbitsize,packedbitsize: byte;
  60. end;
  61. tasmlisttypedconstbuilder = class(ttypedconstbuilder)
  62. private
  63. fsym: tstaticvarsym;
  64. curoffset: asizeint;
  65. function parse_single_packed_const(def: tdef; var bp: tbitpackedval): boolean;
  66. procedure flush_packed_value(var bp: tbitpackedval);
  67. protected
  68. ftcb: ttai_typedconstbuilder;
  69. fdatalist: tasmlist;
  70. procedure parse_packed_array_def(def: tarraydef);
  71. procedure parse_arraydef(def:tarraydef);override;
  72. procedure parse_procvardef(def:tprocvardef);override;
  73. procedure parse_recorddef(def:trecorddef);override;
  74. procedure parse_objectdef(def:tobjectdef);override;
  75. procedure tc_emit_orddef(def: torddef; var node: tnode);override;
  76. procedure tc_emit_floatdef(def: tfloatdef; var node: tnode); override;
  77. procedure tc_emit_classrefdef(def: tclassrefdef; var node: tnode);override;
  78. procedure tc_emit_pointerdef(def: tpointerdef; var node: tnode);override;
  79. procedure tc_emit_setdef(def: tsetdef; var node: tnode);override;
  80. procedure tc_emit_enumdef(def: tenumdef; var node: tnode);override;
  81. procedure tc_emit_stringdef(def: tstringdef; var node: tnode);override;
  82. public
  83. constructor create(sym: tstaticvarsym);virtual;
  84. procedure parse_into_asmlist;
  85. { the asmlist containing the definition of the parsed entity and another
  86. one containing the data generated for that same entity (e.g. the
  87. string data referenced by an ansistring constant) }
  88. procedure get_final_asmlists(out reslist, datalist: tasmlist);
  89. end;
  90. tasmlisttypedconstbuilderclass = class of tasmlisttypedconstbuilder;
  91. tnodetreetypedconstbuilder = class(ttypedconstbuilder)
  92. protected
  93. resultblock: tblocknode;
  94. statmnt: tstatementnode;
  95. { when parsing a record, the base nade becomes a loadnode of the record,
  96. etc. }
  97. basenode: tnode;
  98. procedure parse_arraydef(def:tarraydef);override;
  99. procedure parse_procvardef(def:tprocvardef);override;
  100. procedure parse_recorddef(def:trecorddef);override;
  101. procedure parse_objectdef(def:tobjectdef);override;
  102. procedure tc_emit_orddef(def: torddef; var node: tnode);override;
  103. procedure tc_emit_floatdef(def: tfloatdef; var node: tnode); override;
  104. procedure tc_emit_classrefdef(def: tclassrefdef; var node: tnode);override;
  105. procedure tc_emit_pointerdef(def: tpointerdef; var node: tnode);override;
  106. procedure tc_emit_setdef(def: tsetdef; var node: tnode);override;
  107. procedure tc_emit_enumdef(def: tenumdef; var node: tnode);override;
  108. procedure tc_emit_stringdef(def: tstringdef; var node: tnode);override;
  109. public
  110. constructor create(sym: tstaticvarsym; previnit: tnode);virtual;
  111. destructor destroy;override;
  112. function parse_into_nodetree: tnode;
  113. end;
  114. tnodetreetypedconstbuilderclass = class of tnodetreetypedconstbuilder;
  115. var
  116. ctypedconstbuilder: ttypedconstbuilderclass;
  117. implementation
  118. uses
  119. SysUtils,
  120. systems,tokens,verbose,
  121. cutils,globals,widestr,scanner,
  122. symtable,
  123. aasmcpu,defutil,defcmp,
  124. { pass 1 }
  125. htypechk,procinfo,
  126. nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  127. { parser specific stuff }
  128. pbase,pexpr,pdecvar,
  129. { codegen }
  130. cpuinfo,cgbase,dbgbase,
  131. wpobase
  132. ;
  133. {$maxfpuregisters 0}
  134. function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectList; var symidx:longint):tsym;inline;
  135. begin
  136. while symidx<SymList.Count do
  137. begin
  138. result:=tsym(def.symtable.SymList[symidx]);
  139. inc(symidx);
  140. if result.typ=fieldvarsym then
  141. exit;
  142. end;
  143. result:=nil;
  144. end;
  145. {*****************************************************************************
  146. read typed const
  147. *****************************************************************************}
  148. procedure ttypedconstbuilder.parse_orddef(def:torddef);
  149. var
  150. n : tnode;
  151. begin
  152. n:=comp_expr(true,false);
  153. { for C-style booleans, true=-1 and false=0) }
  154. if is_cbool(def) then
  155. inserttypeconv(n,def);
  156. tc_emit_orddef(def,n);
  157. n.free;
  158. end;
  159. procedure ttypedconstbuilder.parse_floatdef(def:tfloatdef);
  160. var
  161. n : tnode;
  162. begin
  163. n:=comp_expr(true,false);
  164. tc_emit_floatdef(def,n);
  165. n.free;
  166. end;
  167. procedure ttypedconstbuilder.parse_classrefdef(def:tclassrefdef);
  168. var
  169. n : tnode;
  170. begin
  171. n:=comp_expr(true,false);
  172. case n.nodetype of
  173. loadvmtaddrn:
  174. begin
  175. { update wpo info }
  176. if not assigned(current_procinfo) or
  177. (po_inline in current_procinfo.procdef.procoptions) or
  178. wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname) then
  179. tobjectdef(tclassrefdef(n.resultdef).pointeddef).register_maybe_created_object_type;
  180. end;
  181. end;
  182. tc_emit_classrefdef(def,n);
  183. n.free;
  184. end;
  185. procedure ttypedconstbuilder.parse_pointerdef(def:tpointerdef);
  186. var
  187. p: tnode;
  188. begin
  189. p:=comp_expr(true,false);
  190. tc_emit_pointerdef(def,p);
  191. p.free;
  192. end;
  193. procedure ttypedconstbuilder.parse_setdef(def:tsetdef);
  194. var
  195. p : tnode;
  196. begin
  197. p:=comp_expr(true,false);
  198. tc_emit_setdef(def,p);
  199. p.free;
  200. end;
  201. procedure ttypedconstbuilder.parse_enumdef(def:tenumdef);
  202. var
  203. p : tnode;
  204. begin
  205. p:=comp_expr(true,false);
  206. tc_emit_enumdef(def,p);
  207. p.free;
  208. end;
  209. procedure ttypedconstbuilder.parse_stringdef(def:tstringdef);
  210. var
  211. n : tnode;
  212. begin
  213. n:=comp_expr(true,false);
  214. tc_emit_stringdef(def,n);
  215. n.free;
  216. end;
  217. { ttypedconstbuilder }
  218. procedure ttypedconstbuilder.read_typed_const_data(def:tdef);
  219. var
  220. prev_old_block_type,
  221. old_block_type: tblock_type;
  222. begin
  223. old_block_type:=block_type;
  224. prev_old_block_type:=current_old_block_type;
  225. current_old_block_type:=old_block_type;
  226. block_type:=bt_const;
  227. case def.typ of
  228. orddef :
  229. parse_orddef(torddef(def));
  230. floatdef :
  231. parse_floatdef(tfloatdef(def));
  232. classrefdef :
  233. parse_classrefdef(tclassrefdef(def));
  234. pointerdef :
  235. parse_pointerdef(tpointerdef(def));
  236. setdef :
  237. parse_setdef(tsetdef(def));
  238. enumdef :
  239. parse_enumdef(tenumdef(def));
  240. stringdef :
  241. parse_stringdef(tstringdef(def));
  242. arraydef :
  243. parse_arraydef(tarraydef(def));
  244. procvardef:
  245. parse_procvardef(tprocvardef(def));
  246. recorddef:
  247. parse_recorddef(trecorddef(def));
  248. objectdef:
  249. parse_objectdef(tobjectdef(def));
  250. errordef:
  251. begin
  252. { try to consume something useful }
  253. if token=_LKLAMMER then
  254. consume_all_until(_RKLAMMER)
  255. else
  256. consume_all_until(_SEMICOLON);
  257. end;
  258. else
  259. Message(parser_e_type_const_not_possible);
  260. end;
  261. block_type:=old_block_type;
  262. current_old_block_type:=prev_old_block_type;
  263. end;
  264. constructor ttypedconstbuilder.create(sym: tstaticvarsym);
  265. begin
  266. tcsym:=sym;
  267. end;
  268. {*****************************************************************************
  269. Bitpacked value helpers
  270. *****************************************************************************}
  271. procedure initbitpackval(out bp: tbitpackedval; packedbitsize: byte);
  272. begin
  273. bp.curval:=0;
  274. bp.nextval:=0;
  275. bp.curbitoffset:=0;
  276. bp.packedbitsize:=packedbitsize;
  277. bp.loadbitsize:=packedbitsloadsize(bp.packedbitsize)*8;
  278. end;
  279. {$push}
  280. {$r-}
  281. {$q-}
  282. { (values between quotes below refer to fields of bp; fields not }
  283. { mentioned are unused by this routine) }
  284. { bitpacks "value" as bitpacked value of bitsize "packedbitsize" into }
  285. { "curval", which has already been filled up to "curbitoffset", and }
  286. { stores the spillover if any into "nextval". It also updates }
  287. { curbitoffset to reflect how many bits of currval are now used (can be }
  288. { > AIntBits in case of spillover) }
  289. procedure bitpackval(value: aword; var bp: tbitpackedval);
  290. var
  291. shiftcount: longint;
  292. begin
  293. if (target_info.endian=endian_big) then
  294. begin
  295. { bitpacked format: left-aligned (i.e., "big endian bitness") }
  296. bp.curval:=bp.curval or ((value shl (AIntBits-bp.packedbitsize)) shr bp.curbitoffset);
  297. shiftcount:=((AIntBits-bp.packedbitsize)-bp.curbitoffset);
  298. { carry-over to the next element? }
  299. if (shiftcount<0) then
  300. bp.nextval:=(value and ((aword(1) shl (-shiftcount))-1)) shl
  301. (AIntBits+shiftcount)
  302. end
  303. else
  304. begin
  305. { bitpacked format: right aligned (i.e., "little endian bitness") }
  306. bp.curval:=bp.curval or (value shl bp.curbitoffset);
  307. { carry-over to the next element? }
  308. if (bp.curbitoffset+bp.packedbitsize>AIntBits) then
  309. bp.nextval:=value shr (AIntBits-bp.curbitoffset)
  310. end;
  311. inc(bp.curbitoffset,bp.packedbitsize);
  312. end;
  313. procedure tasmlisttypedconstbuilder.flush_packed_value(var bp: tbitpackedval);
  314. var
  315. bitstowrite: longint;
  316. writeval : AInt;
  317. begin
  318. if (bp.curbitoffset < AIntBits) then
  319. begin
  320. { forced flush -> write multiple of loadsize }
  321. bitstowrite:=align(bp.curbitoffset,bp.loadbitsize);
  322. bp.curbitoffset:=0;
  323. end
  324. else
  325. begin
  326. bitstowrite:=AIntBits;
  327. dec(bp.curbitoffset,AIntBits);
  328. end;
  329. while (bitstowrite>=bp.loadbitsize) do
  330. begin
  331. if (target_info.endian=endian_little) then
  332. begin
  333. { write lowest "loadbitsize" bits }
  334. writeval:=bp.curval and (aint(-1) shr ((sizeof(aint)*8)-bp.loadbitsize));
  335. bp.curval:=bp.curval shr bp.loadbitsize;
  336. end
  337. else
  338. begin
  339. { write highest "loadbitsize" bits }
  340. writeval:=bp.curval shr (AIntBits-bp.loadbitsize);
  341. bp.curval:=bp.curval shl bp.loadbitsize;
  342. end;
  343. case bp.loadbitsize of
  344. 8: ftcb.emit_tai(tai_const.create_8bit(writeval),u8inttype);
  345. 16: ftcb.emit_tai(tai_const.create_16bit(writeval),u16inttype);
  346. 32: ftcb.emit_tai(tai_const.create_32bit(writeval),u32inttype);
  347. 64: ftcb.emit_tai(tai_const.create_64bit(writeval),u64inttype);
  348. else
  349. internalerror(2013111101);
  350. end;
  351. dec(bitstowrite,bp.loadbitsize);
  352. end;
  353. bp.curval:=bp.nextval;
  354. bp.nextval:=0;
  355. end;
  356. {$pop}
  357. { parses a packed array constant }
  358. procedure tasmlisttypedconstbuilder.parse_packed_array_def(def: tarraydef);
  359. var
  360. i : aint;
  361. bp : tbitpackedval;
  362. begin
  363. if not(def.elementdef.typ in [orddef,enumdef]) then
  364. internalerror(2007022010);
  365. { begin of the array }
  366. consume(_LKLAMMER);
  367. initbitpackval(bp,def.elepackedbitsize);
  368. i:=def.lowrange;
  369. { can't use for-loop, fails when cross-compiling from }
  370. { 32 to 64 bit because i is then 64 bit }
  371. while (i<def.highrange) do
  372. begin
  373. { get next item of the packed array }
  374. if not parse_single_packed_const(def.elementdef,bp) then
  375. exit;
  376. consume(_COMMA);
  377. inc(i);
  378. end;
  379. { final item }
  380. if not parse_single_packed_const(def.elementdef,bp) then
  381. exit;
  382. { flush final incomplete value if necessary }
  383. if (bp.curbitoffset <> 0) then
  384. flush_packed_value(bp);
  385. consume(_RKLAMMER);
  386. end;
  387. constructor tasmlisttypedconstbuilder.create(sym: tstaticvarsym);
  388. begin
  389. inherited;
  390. fsym:=sym;
  391. ftcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable]);
  392. fdatalist:=tasmlist.create;
  393. curoffset:=0;
  394. end;
  395. procedure tasmlisttypedconstbuilder.tc_emit_stringdef(def: tstringdef; var node: tnode);
  396. var
  397. strlength : aint;
  398. strval : pchar;
  399. strch : char;
  400. ll : tasmlabofs;
  401. ca : pchar;
  402. winlike : boolean;
  403. hsym : tconstsym;
  404. begin
  405. strval:='';
  406. { load strval and strlength of the constant tree }
  407. if (node.nodetype=stringconstn) or is_wide_or_unicode_string(def) or is_constwidecharnode(node) or
  408. ((node.nodetype=typen) and is_interfacecorba(ttypenode(node).typedef)) then
  409. begin
  410. { convert to the expected string type so that
  411. for widestrings strval is a pcompilerwidestring }
  412. inserttypeconv(node,def);
  413. if (not codegenerror) and
  414. (node.nodetype=stringconstn) then
  415. begin
  416. strlength:=tstringconstnode(node).len;
  417. strval:=tstringconstnode(node).value_str;
  418. { the def may have changed from e.g. RawByteString to
  419. AnsiString(CP_ACP) }
  420. if node.resultdef.typ=stringdef then
  421. def:=tstringdef(node.resultdef)
  422. else
  423. internalerror(2014010501);
  424. end
  425. else
  426. begin
  427. { an error occurred trying to convert the result to a string }
  428. strlength:=-1;
  429. { it's possible that the type conversion could not be
  430. evaluated at compile-time }
  431. if not codegenerror then
  432. CGMessage(parser_e_widestring_to_ansi_compile_time);
  433. end;
  434. end
  435. else if is_constcharnode(node) then
  436. begin
  437. { strval:=pchar(@tordconstnode(node).value);
  438. THIS FAIL on BIG_ENDIAN MACHINES PM }
  439. strch:=chr(tordconstnode(node).value.svalue and $ff);
  440. strval:=@strch;
  441. strlength:=1
  442. end
  443. else if is_constresourcestringnode(node) then
  444. begin
  445. hsym:=tconstsym(tloadnode(node).symtableentry);
  446. strval:=pchar(hsym.value.valueptr);
  447. strlength:=hsym.value.len;
  448. { Delphi-compatible (mis)feature:
  449. Link AnsiString constants to their initializing resourcestring,
  450. enabling them to be (re)translated at runtime.
  451. Wide/UnicodeString are currently rejected above (with incorrect error message).
  452. ShortStrings cannot be handled unless another table is built for them;
  453. considering this acceptable, because Delphi rejects them altogether.
  454. }
  455. if (not is_shortstring(def)) and
  456. ((tcsym.owner.symtablelevel<=main_program_level) or
  457. (current_old_block_type=bt_const)) then
  458. begin
  459. current_asmdata.ResStrInits.Concat(
  460. TTCInitItem.Create(tcsym,curoffset,
  461. current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',hsym.owner,hsym.name),AT_DATA))
  462. );
  463. Include(tcsym.varoptions,vo_force_finalize);
  464. end;
  465. end
  466. else
  467. begin
  468. Message(parser_e_illegal_expression);
  469. strlength:=-1;
  470. end;
  471. if strlength>=0 then
  472. begin
  473. case def.stringtype of
  474. st_shortstring:
  475. begin
  476. ftcb.maybe_begin_aggregate(def);
  477. if strlength>=def.size then
  478. begin
  479. message2(parser_w_string_too_long,strpas(strval),tostr(def.size-1));
  480. strlength:=def.size-1;
  481. end;
  482. ftcb.emit_tai(Tai_const.Create_8bit(strlength),cansichartype);
  483. { room for the string data + terminating #0 }
  484. getmem(ca,def.size);
  485. move(strval^,ca^,strlength);
  486. { zero-terminate and fill with spaces if size is shorter }
  487. fillchar(ca[strlength],def.size-strlength-1,' ');
  488. ca[strlength]:=#0;
  489. ca[def.size-1]:=#0;
  490. ftcb.emit_tai(Tai_string.Create_pchar(ca,def.size-1),getarraydef(cansichartype,def.size-1));
  491. ftcb.maybe_end_aggregate(def);
  492. end;
  493. st_ansistring:
  494. begin
  495. { an empty ansi string is nil! }
  496. if (strlength=0) then
  497. begin
  498. ll.lab:=nil;
  499. ll.ofs:=0;
  500. end
  501. else
  502. ll:=ctai_typedconstbuilder.emit_ansistring_const(fdatalist,strval,strlength,def.encoding,true);
  503. ftcb.emit_string_offset(ll,strlength,def.stringtype,false,charpointertype);
  504. end;
  505. st_unicodestring,
  506. st_widestring:
  507. begin
  508. { an empty wide/unicode string is nil! }
  509. if (strlength=0) then
  510. begin
  511. ll.lab:=nil;
  512. ll.ofs:=0;
  513. winlike:=false;
  514. end
  515. else
  516. begin
  517. winlike:=(def.stringtype=st_widestring) and (tf_winlikewidestring in target_info.flags);
  518. ll:=ctai_typedconstbuilder.emit_unicodestring_const(fdatalist,
  519. strval,
  520. def.encoding,
  521. winlike);
  522. { Collect Windows widestrings that need initialization at startup.
  523. Local initialized vars are excluded because they are initialized
  524. at function entry instead. }
  525. if winlike and
  526. ((tcsym.owner.symtablelevel<=main_program_level) or
  527. (current_old_block_type=bt_const)) then
  528. begin
  529. if ll.ofs<>0 then
  530. internalerror(2012051704);
  531. current_asmdata.WideInits.Concat(
  532. TTCInitItem.Create(tcsym,curoffset,ll.lab)
  533. );
  534. ll.lab:=nil;
  535. ll.ofs:=0;
  536. Include(tcsym.varoptions,vo_force_finalize);
  537. end;
  538. end;
  539. ftcb.emit_string_offset(ll,strlength,def.stringtype,winlike,widecharpointertype);
  540. end;
  541. else
  542. internalerror(200107081);
  543. end;
  544. end;
  545. end;
  546. procedure tasmlisttypedconstbuilder.tc_emit_orddef(def: torddef; var node: tnode);
  547. var
  548. intvalue: tconstexprint;
  549. procedure do_error;
  550. begin
  551. if is_constnode(node) then
  552. IncompatibleTypes(node.resultdef, def)
  553. else if not(parse_generic) then
  554. Message(parser_e_illegal_expression);
  555. end;
  556. begin
  557. case def.ordtype of
  558. pasbool8,
  559. bool8bit,
  560. pasbool16,
  561. bool16bit,
  562. pasbool32,
  563. bool32bit,
  564. pasbool64,
  565. bool64bit:
  566. begin
  567. if is_constboolnode(node) then
  568. begin
  569. testrange(def,tordconstnode(node).value,false,false);
  570. ftcb.emit_ord_const(tordconstnode(node).value.svalue,def)
  571. end
  572. else
  573. do_error;
  574. end;
  575. uchar :
  576. begin
  577. if is_constwidecharnode(node) then
  578. inserttypeconv(node,cansichartype);
  579. if is_constcharnode(node) or
  580. ((m_delphi in current_settings.modeswitches) and
  581. is_constwidecharnode(node) and
  582. (tordconstnode(node).value <= 255)) then
  583. ftcb.emit_ord_const(byte(tordconstnode(node).value.svalue),def)
  584. else
  585. do_error;
  586. end;
  587. uwidechar :
  588. begin
  589. if is_constcharnode(node) then
  590. inserttypeconv(node,cwidechartype);
  591. if is_constwidecharnode(node) then
  592. ftcb.emit_ord_const(word(tordconstnode(node).value.svalue),def)
  593. else
  594. do_error;
  595. end;
  596. s8bit,u8bit,
  597. u16bit,s16bit,
  598. s32bit,u32bit,
  599. s64bit,u64bit :
  600. begin
  601. if is_constintnode(node) then
  602. begin
  603. testrange(def,tordconstnode(node).value,false,false);
  604. ftcb.emit_ord_const(tordconstnode(node).value.svalue,def);
  605. end
  606. else
  607. do_error;
  608. end;
  609. scurrency:
  610. begin
  611. if is_constintnode(node) then
  612. intvalue:=tordconstnode(node).value*10000
  613. { allow bootstrapping }
  614. else if is_constrealnode(node) then
  615. intvalue:=PInt64(@trealconstnode(node).value_currency)^
  616. else
  617. begin
  618. intvalue:=0;
  619. IncompatibleTypes(node.resultdef, def);
  620. end;
  621. ftcb.emit_ord_const(intvalue,def);
  622. end;
  623. else
  624. internalerror(200611052);
  625. end;
  626. end;
  627. procedure tasmlisttypedconstbuilder.tc_emit_floatdef(def: tfloatdef; var node: tnode);
  628. var
  629. value : bestreal;
  630. begin
  631. value:=0.0;
  632. if is_constrealnode(node) then
  633. value:=trealconstnode(node).value_real
  634. else if is_constintnode(node) then
  635. value:=tordconstnode(node).value
  636. else if is_constnode(node) then
  637. IncompatibleTypes(node.resultdef, def)
  638. else
  639. Message(parser_e_illegal_expression);
  640. case def.floattype of
  641. s32real :
  642. ftcb.emit_tai(tai_realconst.create_s32real(ts32real(value)),def);
  643. s64real :
  644. {$ifdef ARM}
  645. if is_double_hilo_swapped then
  646. ftcb.emit_tai(tai_realconst.create_s64real_hiloswapped(ts64real(value)),def)
  647. else
  648. {$endif ARM}
  649. ftcb.emit_tai(tai_realconst.create_s64real(ts64real(value)),def);
  650. s80real :
  651. ftcb.emit_tai(tai_realconst.create_s80real(value,s80floattype.size),def);
  652. sc80real :
  653. ftcb.emit_tai(tai_realconst.create_s80real(value,sc80floattype.size),def);
  654. s64comp :
  655. { the round is necessary for native compilers where comp isn't a float }
  656. ftcb.emit_tai(tai_realconst.create_s64compreal(round(value)),def);
  657. s64currency:
  658. ftcb.emit_tai(tai_realconst.create_s64compreal(round(value*10000)),def);
  659. s128real:
  660. ftcb.emit_tai(tai_realconst.create_s128real(value),def);
  661. else
  662. internalerror(200611053);
  663. end;
  664. end;
  665. procedure tasmlisttypedconstbuilder.tc_emit_classrefdef(def: tclassrefdef; var node: tnode);
  666. begin
  667. case node.nodetype of
  668. loadvmtaddrn:
  669. begin
  670. if not def_is_related(tobjectdef(tclassrefdef(node.resultdef).pointeddef),tobjectdef(def.pointeddef)) then
  671. IncompatibleTypes(node.resultdef, def);
  672. { TODO for correct type? }
  673. ftcb.emit_tai(Tai_const.Create_sym(current_asmdata.RefAsmSymbol(Tobjectdef(tclassrefdef(node.resultdef).pointeddef).vmt_mangledname,AT_DATA)),voidpointertype);
  674. end;
  675. niln:
  676. ftcb.emit_tai(Tai_const.Create_sym(nil),voidpointertype);
  677. else if is_constnode(node) then
  678. IncompatibleTypes(node.resultdef, def)
  679. else
  680. Message(parser_e_illegal_expression);
  681. end;
  682. end;
  683. procedure tasmlisttypedconstbuilder.tc_emit_pointerdef(def: tpointerdef; var node: tnode);
  684. var
  685. hp : tnode;
  686. srsym : tsym;
  687. pd : tprocdef;
  688. ca : pchar;
  689. pw : pcompilerwidestring;
  690. i,len : longint;
  691. ll : tasmlabel;
  692. varalign : shortint;
  693. datadef : tdef;
  694. datatcb : ttai_typedconstbuilder;
  695. begin
  696. { remove equal typecasts for pointer/nil addresses }
  697. if (node.nodetype=typeconvn) then
  698. with Ttypeconvnode(node) do
  699. if (left.nodetype in [addrn,niln]) and equal_defs(def,node.resultdef) then
  700. begin
  701. hp:=left;
  702. left:=nil;
  703. node.free;
  704. node:=hp;
  705. end;
  706. { allows horrible ofs(typeof(TButton)^) code !! }
  707. if (node.nodetype=addrn) then
  708. with Taddrnode(node) do
  709. if left.nodetype=derefn then
  710. begin
  711. hp:=tderefnode(left).left;
  712. tderefnode(left).left:=nil;
  713. node.free;
  714. node:=hp;
  715. end;
  716. { const pointer ? }
  717. if (node.nodetype = pointerconstn) then
  718. begin
  719. ftcb.queue_init(def);
  720. ftcb.queue_typeconvn(ptrsinttype,def);
  721. {$if sizeof(TConstPtrUInt)=8}
  722. ftcb.queue_emit_ordconst(int64(tpointerconstnode(node).value),ptrsinttype);
  723. {$else}
  724. {$if sizeof(TConstPtrUInt)=4}
  725. ftcb.queue_emit_ordconst(longint(tpointerconstnode(node).value),ptrsinttype);
  726. {$else}
  727. internalerror(200404122);
  728. {$endif} {$endif}
  729. end
  730. { nil pointer ? }
  731. else if node.nodetype=niln then
  732. ftcb.emit_tai(Tai_const.Create_sym(nil),def)
  733. { maybe pchar ? }
  734. else
  735. if is_char(def.pointeddef) and
  736. (node.nodetype<>addrn) then
  737. begin
  738. { create a tcb for the string data (it's placed in a separate
  739. asmlist) }
  740. ftcb.start_internal_data_builder(fdatalist,sec_rodata,'',datatcb,ll);
  741. if node.nodetype=stringconstn then
  742. varalign:=size_2_align(tstringconstnode(node).len)
  743. else
  744. varalign:=0;
  745. varalign:=const_align(varalign);
  746. { represent the string data as an array }
  747. if node.nodetype=stringconstn then
  748. begin
  749. len:=tstringconstnode(node).len;
  750. { For tp7 the maximum lentgh can be 255 }
  751. if (m_tp7 in current_settings.modeswitches) and
  752. (len>255) then
  753. len:=255;
  754. getmem(ca,len+1);
  755. move(tstringconstnode(node).value_str^,ca^,len+1);
  756. datadef:=getarraydef(cansichartype,len+1);
  757. datatcb.maybe_begin_aggregate(datadef);
  758. datatcb.emit_tai(Tai_string.Create_pchar(ca,len+1),datadef);
  759. datatcb.maybe_end_aggregate(datadef);
  760. end
  761. else if is_constcharnode(node) then
  762. begin
  763. datadef:=getarraydef(cansichartype,2);
  764. datatcb.maybe_begin_aggregate(datadef);
  765. datatcb.emit_tai(Tai_string.Create(char(byte(tordconstnode(node).value.svalue))+#0),datadef);
  766. datatcb.maybe_end_aggregate(datadef);
  767. end
  768. else
  769. begin
  770. IncompatibleTypes(node.resultdef, def);
  771. datadef:=getarraydef(cansichartype,1);
  772. end;
  773. ftcb.finish_internal_data_builder(datatcb,ll,datadef,varalign);
  774. { we now emit the address of the first element of the array
  775. containing the string data }
  776. ftcb.queue_init(def);
  777. { address of ... }
  778. ftcb.queue_addrn(def.pointeddef,def);
  779. { ... the first element ... }
  780. ftcb.queue_vecn(datadef,0);
  781. { ... of the string array }
  782. ftcb.queue_emit_asmsym(ll,datadef);
  783. end
  784. { maybe pwidechar ? }
  785. else
  786. if is_widechar(def.pointeddef) and
  787. (node.nodetype<>addrn) then
  788. begin
  789. if (node.nodetype in [stringconstn,ordconstn]) then
  790. begin
  791. { convert to unicodestring stringconstn }
  792. inserttypeconv(node,cunicodestringtype);
  793. if (node.nodetype=stringconstn) and
  794. (tstringconstnode(node).cst_type in [cst_widestring,cst_unicodestring]) then
  795. begin
  796. { create a tcb for the string data (it's placed in a separate
  797. asmlist) }
  798. ftcb.start_internal_data_builder(fdatalist,sec_rodata,'',datatcb,ll);
  799. datatcb:=ctai_typedconstbuilder.create([tcalo_is_lab,tcalo_make_dead_strippable]);
  800. pw:=pcompilerwidestring(tstringconstnode(node).value_str);
  801. { include terminating #0 }
  802. datadef:=getarraydef(cwidechartype,tstringconstnode(node).len+1);
  803. datatcb.maybe_begin_aggregate(datadef);
  804. for i:=0 to tstringconstnode(node).len-1 do
  805. datatcb.emit_tai(Tai_const.Create_16bit(pw^.data[i]),cwidechartype);
  806. { ending #0 }
  807. datatcb.emit_tai(Tai_const.Create_16bit(0),cwidechartype);
  808. datatcb.maybe_end_aggregate(datadef);
  809. { concat add the string data to the fdatalist }
  810. ftcb.finish_internal_data_builder(datatcb,ll,datadef,const_align(sizeof(pint)));
  811. { we now emit the address of the first element of the array
  812. containing the string data }
  813. ftcb.queue_init(def);
  814. { address of ... }
  815. ftcb.queue_addrn(def.pointeddef,def);
  816. { ... the first element ... }
  817. ftcb.queue_vecn(datadef,0);
  818. { ... of the string array }
  819. ftcb.queue_emit_asmsym(ll,datadef);
  820. end;
  821. end
  822. else
  823. IncompatibleTypes(node.resultdef, def);
  824. end
  825. else
  826. if (node.nodetype=addrn) or
  827. is_proc2procvar_load(node,pd) then
  828. begin
  829. { insert typeconv }
  830. inserttypeconv(node,def);
  831. hp:=node;
  832. while assigned(hp) and (hp.nodetype in [addrn,typeconvn,subscriptn,vecn]) do
  833. hp:=tunarynode(hp).left;
  834. if (hp.nodetype=loadn) then
  835. begin
  836. hp:=node;
  837. ftcb.queue_init(def);
  838. while assigned(hp) and (hp.nodetype<>loadn) do
  839. begin
  840. case hp.nodetype of
  841. vecn :
  842. begin
  843. if is_constintnode(tvecnode(hp).right) then
  844. ftcb.queue_vecn(tvecnode(hp).left.resultdef,get_ordinal_value(tvecnode(hp).right))
  845. else
  846. Message(parser_e_illegal_expression);
  847. end;
  848. subscriptn :
  849. ftcb.queue_subscriptn(tabstractrecorddef(tsubscriptnode(hp).left.resultdef),tsubscriptnode(hp).vs);
  850. typeconvn :
  851. begin
  852. if not(ttypeconvnode(hp).convtype in [tc_equal,tc_proc_2_procvar]) then
  853. Message(parser_e_illegal_expression)
  854. else
  855. ftcb.queue_typeconvn(ttypeconvnode(hp).left.resultdef,hp.resultdef);
  856. end;
  857. addrn :
  858. ftcb.queue_addrn(taddrnode(hp).left.resultdef,hp.resultdef);
  859. else
  860. Message(parser_e_illegal_expression);
  861. end;
  862. hp:=tunarynode(hp).left;
  863. end;
  864. srsym:=tloadnode(hp).symtableentry;
  865. case srsym.typ of
  866. procsym :
  867. begin
  868. pd:=tprocdef(tprocsym(srsym).ProcdefList[0]);
  869. if Tprocsym(srsym).ProcdefList.Count>1 then
  870. Message(parser_e_no_overloaded_procvars);
  871. if po_abstractmethod in pd.procoptions then
  872. Message(type_e_cant_take_address_of_abstract_method)
  873. else
  874. ftcb.queue_emit_proc(pd);
  875. end;
  876. staticvarsym :
  877. ftcb.queue_emit_staticvar(tstaticvarsym(srsym));
  878. labelsym :
  879. ftcb.queue_emit_label(tlabelsym(srsym));
  880. constsym :
  881. if tconstsym(srsym).consttyp=constresourcestring then
  882. ftcb.queue_emit_const(tconstsym(srsym))
  883. else
  884. Message(type_e_variable_id_expected);
  885. else
  886. Message(type_e_variable_id_expected);
  887. end;
  888. end
  889. else
  890. Message(parser_e_illegal_expression);
  891. end
  892. else
  893. { allow typeof(Object type)}
  894. if (node.nodetype=inlinen) and
  895. (tinlinenode(node).inlinenumber=in_typeof_x) then
  896. begin
  897. if (tinlinenode(node).left.nodetype=typen) then
  898. begin
  899. // TODO correct type?
  900. ftcb.emit_tai(Tai_const.createname(
  901. tobjectdef(tinlinenode(node).left.resultdef).vmt_mangledname,AT_DATA,0),
  902. voidpointertype);
  903. end
  904. else
  905. Message(parser_e_illegal_expression);
  906. end
  907. else
  908. Message(parser_e_illegal_expression);
  909. end;
  910. procedure tasmlisttypedconstbuilder.tc_emit_setdef(def: tsetdef; var node: tnode);
  911. type
  912. setbytes = array[0..31] of byte;
  913. Psetbytes = ^setbytes;
  914. var
  915. i: longint;
  916. begin
  917. if node.nodetype=setconstn then
  918. begin
  919. { be sure to convert to the correct result, else
  920. it can generate smallset data instead of normalset (PFV) }
  921. inserttypeconv(node,def);
  922. { we only allow const sets }
  923. if (node.nodetype<>setconstn) or
  924. assigned(tsetconstnode(node).left) then
  925. Message(parser_e_illegal_expression)
  926. else
  927. begin
  928. ftcb.maybe_begin_aggregate(def);
  929. tsetconstnode(node).adjustforsetbase;
  930. { this writing is endian-dependant }
  931. if source_info.endian = target_info.endian then
  932. begin
  933. for i:=0 to node.resultdef.size-1 do
  934. ftcb.emit_tai(tai_const.create_8bit(Psetbytes(tsetconstnode(node).value_set)^[i]),u8inttype);
  935. end
  936. else
  937. begin
  938. for i:=0 to node.resultdef.size-1 do
  939. ftcb.emit_tai(tai_const.create_8bit(reverse_byte(Psetbytes(tsetconstnode(node).value_set)^[i])),u8inttype);
  940. end;
  941. ftcb.maybe_end_aggregate(def);
  942. end;
  943. end
  944. else
  945. Message(parser_e_illegal_expression);
  946. end;
  947. procedure tasmlisttypedconstbuilder.tc_emit_enumdef(def: tenumdef; var node: tnode);
  948. begin
  949. if node.nodetype=ordconstn then
  950. begin
  951. if equal_defs(node.resultdef,def) or
  952. is_subequal(node.resultdef,def) then
  953. begin
  954. testrange(def,tordconstnode(node).value,false,false);
  955. case longint(node.resultdef.size) of
  956. 1 : ftcb.emit_tai(Tai_const.Create_8bit(Byte(tordconstnode(node).value.svalue)),def);
  957. 2 : ftcb.emit_tai(Tai_const.Create_16bit(Word(tordconstnode(node).value.svalue)),def);
  958. 4 : ftcb.emit_tai(Tai_const.Create_32bit(Longint(tordconstnode(node).value.svalue)),def);
  959. end;
  960. end
  961. else
  962. IncompatibleTypes(node.resultdef,def);
  963. end
  964. else
  965. Message(parser_e_illegal_expression);
  966. end;
  967. { parse a single constant and add it to the packed const info }
  968. { represented by curval etc (see explanation of bitpackval for }
  969. { what the different parameters mean) }
  970. function tasmlisttypedconstbuilder.parse_single_packed_const(def: tdef; var bp: tbitpackedval): boolean;
  971. var
  972. node: tnode;
  973. begin
  974. result:=true;
  975. node:=comp_expr(true,false);
  976. if (node.nodetype <> ordconstn) or
  977. (not equal_defs(node.resultdef,def) and
  978. not is_subequal(node.resultdef,def)) then
  979. begin
  980. incompatibletypes(node.resultdef,def);
  981. node.free;
  982. consume_all_until(_SEMICOLON);
  983. result:=false;
  984. exit;
  985. end;
  986. if (Tordconstnode(node).value<qword(low(Aword))) or (Tordconstnode(node).value>qword(high(Aword))) then
  987. message3(type_e_range_check_error_bounds,tostr(Tordconstnode(node).value),tostr(low(Aword)),tostr(high(Aword)))
  988. else
  989. bitpackval(Tordconstnode(node).value.uvalue,bp);
  990. if (bp.curbitoffset>=AIntBits) then
  991. flush_packed_value(bp);
  992. node.free;
  993. end;
  994. procedure tasmlisttypedconstbuilder.get_final_asmlists(out reslist, datalist: tasmlist);
  995. var
  996. asmsym: tasmsymbol;
  997. addstabx: boolean;
  998. sec: TAsmSectiontype;
  999. secname: ansistring;
  1000. begin
  1001. addstabx:=false;
  1002. if fsym.globalasmsym then
  1003. begin
  1004. if (target_dbg.id=dbg_stabx) and
  1005. (cs_debuginfo in current_settings.moduleswitches) and
  1006. not assigned(current_asmdata.GetAsmSymbol(fsym.name)) then
  1007. addstabx:=true;
  1008. asmsym:=current_asmdata.DefineAsmSymbol(fsym.mangledname,AB_GLOBAL,AT_DATA)
  1009. end
  1010. else
  1011. asmsym:=current_asmdata.DefineAsmSymbol(fsym.mangledname,AB_LOCAL,AT_DATA);
  1012. if vo_has_section in fsym.varoptions then
  1013. begin
  1014. sec:=sec_user;
  1015. secname:=fsym.section;
  1016. end
  1017. else
  1018. begin
  1019. { Certain types like windows WideString are initialized at runtime and cannot
  1020. be placed into readonly memory }
  1021. if (fsym.varspez=vs_const) and
  1022. not (vo_force_finalize in fsym.varoptions) then
  1023. sec:=sec_rodata
  1024. else
  1025. sec:=sec_data;
  1026. secname:=asmsym.Name;
  1027. end;
  1028. reslist:=ftcb.get_final_asmlist(asmsym,fsym.vardef,sec,secname,fsym.vardef.alignment);
  1029. if addstabx then
  1030. begin
  1031. { see same code in ncgutil.insertbssdata }
  1032. reslist.insert(tai_directive.Create(asd_reference,fsym.name));
  1033. reslist.insert(tai_symbol.Create(current_asmdata.DefineAsmSymbol(fsym.name,AB_LOCAL,AT_DATA),0));
  1034. end;
  1035. datalist:=fdatalist;
  1036. end;
  1037. procedure tasmlisttypedconstbuilder.parse_arraydef(def:tarraydef);
  1038. var
  1039. n : tnode;
  1040. i : longint;
  1041. len : asizeint;
  1042. ch : array[0..1] of char;
  1043. ca : pbyte;
  1044. int_const: tai_const;
  1045. char_size: integer;
  1046. oldoffset: asizeint;
  1047. dummy : byte;
  1048. begin
  1049. { dynamic array nil }
  1050. if is_dynamic_array(def) then
  1051. begin
  1052. { Only allow nil initialization }
  1053. consume(_NIL);
  1054. ftcb.emit_tai(Tai_const.Create_sym(nil),def);
  1055. end
  1056. { packed array constant }
  1057. else if is_packed_array(def) and
  1058. ((def.elepackedbitsize mod 8 <> 0) or
  1059. not ispowerof2(def.elepackedbitsize div 8,i)) then
  1060. begin
  1061. parse_packed_array_def(def);
  1062. end
  1063. { normal array const between brackets }
  1064. else if try_to_consume(_LKLAMMER) then
  1065. begin
  1066. ftcb.maybe_begin_aggregate(def);
  1067. oldoffset:=curoffset;
  1068. curoffset:=0;
  1069. { in case of a generic subroutine, it might be we cannot
  1070. determine the size yet }
  1071. if assigned(current_procinfo) and (df_generic in current_procinfo.procdef.defoptions) then
  1072. begin
  1073. while true do
  1074. begin
  1075. read_typed_const_data(def.elementdef);
  1076. if token=_RKLAMMER then
  1077. begin
  1078. consume(_RKLAMMER);
  1079. break;
  1080. end
  1081. else
  1082. consume(_COMMA);
  1083. end;
  1084. end
  1085. else
  1086. begin
  1087. for i:=def.lowrange to def.highrange-1 do
  1088. begin
  1089. read_typed_const_data(def.elementdef);
  1090. Inc(curoffset,def.elementdef.size);
  1091. if token=_RKLAMMER then
  1092. begin
  1093. Message1(parser_e_more_array_elements_expected,tostr(def.highrange-i));
  1094. consume(_RKLAMMER);
  1095. exit;
  1096. end
  1097. else
  1098. consume(_COMMA);
  1099. end;
  1100. read_typed_const_data(def.elementdef);
  1101. consume(_RKLAMMER);
  1102. end;
  1103. curoffset:=oldoffset;
  1104. ftcb.maybe_end_aggregate(def);
  1105. end
  1106. { if array of char then we allow also a string }
  1107. else if is_anychar(def.elementdef) then
  1108. begin
  1109. ftcb.maybe_begin_aggregate(def);
  1110. char_size:=def.elementdef.size;
  1111. n:=comp_expr(true,false);
  1112. if n.nodetype=stringconstn then
  1113. begin
  1114. len:=tstringconstnode(n).len;
  1115. case char_size of
  1116. 1:
  1117. begin
  1118. if (tstringconstnode(n).cst_type in [cst_unicodestring,cst_widestring]) then
  1119. inserttypeconv(n,getansistringdef);
  1120. if n.nodetype<>stringconstn then
  1121. internalerror(2010033003);
  1122. ca:=pointer(tstringconstnode(n).value_str);
  1123. end;
  1124. 2:
  1125. begin
  1126. inserttypeconv(n,cunicodestringtype);
  1127. if n.nodetype<>stringconstn then
  1128. internalerror(2010033003);
  1129. ca:=pointer(pcompilerwidestring(tstringconstnode(n).value_str)^.data)
  1130. end;
  1131. else
  1132. internalerror(2010033005);
  1133. end;
  1134. { For tp7 the maximum lentgh can be 255 }
  1135. if (m_tp7 in current_settings.modeswitches) and
  1136. (len>255) then
  1137. len:=255;
  1138. end
  1139. else if is_constcharnode(n) then
  1140. begin
  1141. case char_size of
  1142. 1:
  1143. ch[0]:=chr(tordconstnode(n).value.uvalue and $ff);
  1144. 2:
  1145. begin
  1146. inserttypeconv(n,cwidechartype);
  1147. if not is_constwidecharnode(n) then
  1148. internalerror(2010033001);
  1149. widechar(ch):=widechar(tordconstnode(n).value.uvalue and $ffff);
  1150. end;
  1151. else
  1152. internalerror(2010033002);
  1153. end;
  1154. ca:=@ch;
  1155. len:=1;
  1156. end
  1157. else if is_constwidecharnode(n) and (current_settings.sourcecodepage<>CP_UTF8) then
  1158. begin
  1159. case char_size of
  1160. 1:
  1161. begin
  1162. inserttypeconv(n,cansichartype);
  1163. if not is_constcharnode(n) then
  1164. internalerror(2010033001);
  1165. ch[0]:=chr(tordconstnode(n).value.uvalue and $ff);
  1166. end;
  1167. 2:
  1168. widechar(ch):=widechar(tordconstnode(n).value.uvalue and $ffff);
  1169. else
  1170. internalerror(2010033002);
  1171. end;
  1172. ca:=@ch;
  1173. len:=1;
  1174. end
  1175. else
  1176. begin
  1177. Message(parser_e_illegal_expression);
  1178. len:=0;
  1179. { avoid crash later on }
  1180. dummy:=0;
  1181. ca:=@dummy;
  1182. end;
  1183. if len>(def.highrange-def.lowrange+1) then
  1184. Message(parser_e_string_larger_array);
  1185. for i:=0 to def.highrange-def.lowrange do
  1186. begin
  1187. if i<len then
  1188. begin
  1189. case char_size of
  1190. 1:
  1191. int_const:=Tai_const.Create_char(char_size,pbyte(ca)^);
  1192. 2:
  1193. int_const:=Tai_const.Create_char(char_size,pword(ca)^);
  1194. else
  1195. internalerror(2010033004);
  1196. end;
  1197. inc(ca, char_size);
  1198. end
  1199. else
  1200. {Fill the remaining positions with #0.}
  1201. int_const:=Tai_const.Create_char(char_size,0);
  1202. ftcb.emit_tai(int_const,def.elementdef)
  1203. end;
  1204. ftcb.maybe_end_aggregate(def);
  1205. n.free;
  1206. end
  1207. else
  1208. begin
  1209. { we want the ( }
  1210. consume(_LKLAMMER);
  1211. end;
  1212. end;
  1213. procedure tasmlisttypedconstbuilder.parse_procvardef(def:tprocvardef);
  1214. var
  1215. tmpn,n : tnode;
  1216. pd : tprocdef;
  1217. havepd,
  1218. haveblock: boolean;
  1219. begin
  1220. { Procvars and pointers are no longer compatible. }
  1221. { under tp: =nil or =var under fpc: =nil or =@var }
  1222. if try_to_consume(_NIL) then
  1223. begin
  1224. ftcb.maybe_begin_aggregate(def);
  1225. { we need the procdef type called by the procvar here, not the
  1226. procvar record }
  1227. ftcb.emit_tai_procvar2procdef(Tai_const.Create_sym(nil),def);
  1228. if not def.is_addressonly then
  1229. ftcb.emit_tai(Tai_const.Create_sym(nil),voidpointertype);
  1230. ftcb.maybe_end_aggregate(def);
  1231. exit;
  1232. end;
  1233. { you can't assign a value other than NIL to a typed constant }
  1234. { which is a "procedure of object", because this also requires }
  1235. { address of an object/class instance, which is not known at }
  1236. { compile time (JM) }
  1237. if (po_methodpointer in def.procoptions) then
  1238. Message(parser_e_no_procvarobj_const);
  1239. { parse the rest too, so we can continue with error checking }
  1240. getprocvardef:=def;
  1241. n:=comp_expr(true,false);
  1242. getprocvardef:=nil;
  1243. if codegenerror then
  1244. begin
  1245. n.free;
  1246. exit;
  1247. end;
  1248. { let type conversion check everything needed }
  1249. inserttypeconv(n,def);
  1250. if codegenerror then
  1251. begin
  1252. n.free;
  1253. exit;
  1254. end;
  1255. { in case of a nested procdef initialised with a global routine }
  1256. ftcb.maybe_begin_aggregate(def);
  1257. { to handle type conversions }
  1258. ftcb.queue_init(def);
  1259. { remove typeconvs, that will normally insert a lea
  1260. instruction which is not necessary for us }
  1261. while n.nodetype=typeconvn do
  1262. begin
  1263. ftcb.queue_typeconvn(ttypeconvnode(n).left.resultdef,n.resultdef);
  1264. tmpn:=ttypeconvnode(n).left;
  1265. ttypeconvnode(n).left:=nil;
  1266. n.free;
  1267. n:=tmpn;
  1268. end;
  1269. { remove addrn which we also don't need here }
  1270. if n.nodetype=addrn then
  1271. begin
  1272. ftcb.queue_addrn(taddrnode(n).left.resultdef,n.resultdef);
  1273. tmpn:=taddrnode(n).left;
  1274. taddrnode(n).left:=nil;
  1275. n.free;
  1276. n:=tmpn;
  1277. end;
  1278. pd:=nil;
  1279. { we now need to have a loadn with a procsym }
  1280. havepd:=
  1281. (n.nodetype=loadn) and
  1282. (tloadnode(n).symtableentry.typ=procsym);
  1283. { or a staticvarsym representing a block }
  1284. haveblock:=
  1285. (n.nodetype=loadn) and
  1286. (tloadnode(n).symtableentry.typ=staticvarsym) and
  1287. (sp_internal in tloadnode(n).symtableentry.symoptions);
  1288. if havepd or
  1289. haveblock then
  1290. begin
  1291. if havepd then
  1292. begin
  1293. pd:=tloadnode(n).procdef;
  1294. ftcb.queue_emit_proc(pd);
  1295. end
  1296. else
  1297. begin
  1298. ftcb.queue_emit_staticvar(tstaticvarsym(tloadnode(n).symtableentry));
  1299. end;
  1300. { nested procvar typed consts can only be initialised with nil
  1301. (checked above) or with a global procedure (checked here),
  1302. because in other cases we need a valid frame pointer }
  1303. if is_nested_pd(def) then
  1304. begin
  1305. if haveblock or
  1306. is_nested_pd(pd) then
  1307. Message(parser_e_no_procvarnested_const);
  1308. ftcb.emit_tai(Tai_const.Create_sym(nil),voidpointertype);
  1309. end;
  1310. ftcb.maybe_end_aggregate(def);
  1311. end
  1312. else if n.nodetype=pointerconstn then
  1313. begin
  1314. ftcb.maybe_begin_aggregate(def);
  1315. ftcb.emit_tai_procvar2procdef(Tai_const.Create_pint(tpointerconstnode(n).value),def);
  1316. if not def.is_addressonly then
  1317. ftcb.emit_tai(Tai_const.Create_sym(nil),voidpointertype);
  1318. end
  1319. else
  1320. Message(parser_e_illegal_expression);
  1321. n.free;
  1322. end;
  1323. procedure tasmlisttypedconstbuilder.parse_recorddef(def:trecorddef);
  1324. var
  1325. n : tnode;
  1326. symidx : longint;
  1327. recsym,
  1328. srsym : tsym;
  1329. hs : string;
  1330. sorg,s : TIDString;
  1331. tmpguid : tguid;
  1332. recoffset,
  1333. fillbytes : aint;
  1334. bp : tbitpackedval;
  1335. error,
  1336. is_packed: boolean;
  1337. startoffset: aint;
  1338. procedure handle_stringconstn;
  1339. begin
  1340. hs:=strpas(tstringconstnode(n).value_str);
  1341. if string2guid(hs,tmpguid) then
  1342. ftcb.emit_guid_const(tmpguid)
  1343. else
  1344. Message(parser_e_improper_guid_syntax);
  1345. end;
  1346. var
  1347. i : longint;
  1348. SymList:TFPHashObjectList;
  1349. begin
  1350. { GUID }
  1351. if (def=rec_tguid) and (token=_ID) then
  1352. begin
  1353. n:=comp_expr(true,false);
  1354. if n.nodetype=stringconstn then
  1355. handle_stringconstn
  1356. else
  1357. begin
  1358. inserttypeconv(n,rec_tguid);
  1359. if n.nodetype=guidconstn then
  1360. ftcb.emit_guid_const(tguidconstnode(n).value)
  1361. else
  1362. Message(parser_e_illegal_expression);
  1363. end;
  1364. n.free;
  1365. exit;
  1366. end;
  1367. if (def=rec_tguid) and ((token=_CSTRING) or (token=_CCHAR)) then
  1368. begin
  1369. n:=comp_expr(true,false);
  1370. inserttypeconv(n,cshortstringtype);
  1371. if n.nodetype=stringconstn then
  1372. handle_stringconstn
  1373. else
  1374. Message(parser_e_illegal_expression);
  1375. n.free;
  1376. exit;
  1377. end;
  1378. ftcb.maybe_begin_aggregate(def);
  1379. { bitpacked record? }
  1380. is_packed:=is_packed_record_or_object(def);
  1381. if (is_packed) then
  1382. begin
  1383. { loadbitsize = 8, bitpacked records are always padded to }
  1384. { a multiple of a byte. packedbitsize will be set separately }
  1385. { for each field }
  1386. initbitpackval(bp,0);
  1387. bp.loadbitsize:=8;
  1388. end;
  1389. { normal record }
  1390. consume(_LKLAMMER);
  1391. recoffset:=0;
  1392. sorg:='';
  1393. symidx:=0;
  1394. symlist:=def.symtable.SymList;
  1395. srsym:=get_next_varsym(def,symlist,symidx);
  1396. recsym := nil;
  1397. startoffset:=curoffset;
  1398. while token<>_RKLAMMER do
  1399. begin
  1400. s:=pattern;
  1401. sorg:=orgpattern;
  1402. consume(_ID);
  1403. consume(_COLON);
  1404. error := false;
  1405. recsym := tsym(def.symtable.Find(s));
  1406. if not assigned(recsym) then
  1407. begin
  1408. Message1(sym_e_illegal_field,sorg);
  1409. error := true;
  1410. end;
  1411. if (not error) and
  1412. (not assigned(srsym) or
  1413. (s <> srsym.name)) then
  1414. { possible variant record (JM) }
  1415. begin
  1416. { All parts of a variant start at the same offset }
  1417. { Also allow jumping from one variant part to another, }
  1418. { as long as the offsets match }
  1419. if (assigned(srsym) and
  1420. (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
  1421. { srsym is not assigned after parsing w2 in the }
  1422. { typed const in the next example: }
  1423. { type tr = record case byte of }
  1424. { 1: (l1,l2: dword); }
  1425. { 2: (w1,w2: word); }
  1426. { end; }
  1427. { const r: tr = (w1:1;w2:1;l2:5); }
  1428. (tfieldvarsym(recsym).fieldoffset = recoffset) then
  1429. begin
  1430. srsym:=recsym;
  1431. { symidx should contain the next symbol id to search }
  1432. symidx:=SymList.indexof(srsym)+1;
  1433. end
  1434. { going backwards isn't allowed in any mode }
  1435. else if (tfieldvarsym(recsym).fieldoffset<recoffset) then
  1436. begin
  1437. Message(parser_e_invalid_record_const);
  1438. error := true;
  1439. end
  1440. { Delphi allows you to skip fields }
  1441. else if (m_delphi in current_settings.modeswitches) then
  1442. begin
  1443. Message1(parser_w_skipped_fields_before,sorg);
  1444. srsym := recsym;
  1445. end
  1446. { FPC and TP don't }
  1447. else
  1448. begin
  1449. Message1(parser_e_skipped_fields_before,sorg);
  1450. error := true;
  1451. end;
  1452. end;
  1453. if error then
  1454. consume_all_until(_SEMICOLON)
  1455. else
  1456. begin
  1457. { if needed fill (alignment) }
  1458. if tfieldvarsym(srsym).fieldoffset>recoffset then
  1459. begin
  1460. if not(is_packed) then
  1461. fillbytes:=0
  1462. else
  1463. begin
  1464. flush_packed_value(bp);
  1465. { curoffset is now aligned to the next byte }
  1466. recoffset:=align(recoffset,8);
  1467. { offsets are in bits in this case }
  1468. fillbytes:=(tfieldvarsym(srsym).fieldoffset-recoffset) div 8;
  1469. end;
  1470. for i:=1 to fillbytes do
  1471. ftcb.emit_tai(Tai_const.Create_8bit(0),u8inttype)
  1472. end;
  1473. { new position }
  1474. recoffset:=tfieldvarsym(srsym).fieldoffset;
  1475. if not(is_packed) then
  1476. inc(recoffset,tfieldvarsym(srsym).vardef.size)
  1477. else
  1478. inc(recoffset,tfieldvarsym(srsym).vardef.packedbitsize);
  1479. { read the data }
  1480. ftcb.next_field:=tfieldvarsym(srsym);
  1481. if not(is_packed) or
  1482. { only orddefs and enumdefs are bitpacked, as in gcc/gpc }
  1483. not(tfieldvarsym(srsym).vardef.typ in [orddef,enumdef]) then
  1484. begin
  1485. if is_packed then
  1486. begin
  1487. flush_packed_value(bp);
  1488. recoffset:=align(recoffset,8);
  1489. end;
  1490. curoffset:=startoffset+tfieldvarsym(srsym).fieldoffset;
  1491. read_typed_const_data(tfieldvarsym(srsym).vardef);
  1492. end
  1493. else
  1494. begin
  1495. bp.packedbitsize:=tfieldvarsym(srsym).vardef.packedbitsize;
  1496. parse_single_packed_const(tfieldvarsym(srsym).vardef,bp);
  1497. end;
  1498. { keep previous field for checking whether whole }
  1499. { record was initialized (JM) }
  1500. recsym := srsym;
  1501. { goto next field }
  1502. srsym:=get_next_varsym(def,SymList,symidx);
  1503. if token=_SEMICOLON then
  1504. consume(_SEMICOLON)
  1505. else if (token=_COMMA) and (m_mac in current_settings.modeswitches) then
  1506. consume(_COMMA)
  1507. else
  1508. break;
  1509. end;
  1510. end;
  1511. curoffset:=startoffset;
  1512. { are there any fields left, but don't complain if there only
  1513. come other variant parts after the last initialized field }
  1514. if assigned(srsym) and
  1515. (
  1516. (recsym=nil) or
  1517. (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)
  1518. ) then
  1519. Message1(parser_w_skipped_fields_after,sorg);
  1520. if not error then
  1521. begin
  1522. if not(is_packed) then
  1523. fillbytes:=0
  1524. else
  1525. begin
  1526. flush_packed_value(bp);
  1527. recoffset:=align(recoffset,8);
  1528. fillbytes:=def.size-(recoffset div 8);
  1529. end;
  1530. for i:=1 to fillbytes do
  1531. ftcb.emit_tai(Tai_const.Create_8bit(0),u8inttype);
  1532. end;
  1533. ftcb.maybe_end_aggregate(def);
  1534. consume(_RKLAMMER);
  1535. end;
  1536. procedure tasmlisttypedconstbuilder.parse_objectdef(def:tobjectdef);
  1537. var
  1538. n : tnode;
  1539. i : longint;
  1540. obj : tobjectdef;
  1541. srsym : tsym;
  1542. st : tsymtable;
  1543. objoffset : aint;
  1544. s,sorg : TIDString;
  1545. vmtwritten : boolean;
  1546. startoffset:aint;
  1547. begin
  1548. { no support for packed object }
  1549. if is_packed_record_or_object(def) then
  1550. begin
  1551. Message(type_e_no_const_packed_record);
  1552. exit;
  1553. end;
  1554. { only allow nil for implicit pointer object types }
  1555. if is_implicit_pointer_object_type(def) then
  1556. begin
  1557. n:=comp_expr(true,false);
  1558. if n.nodetype<>niln then
  1559. begin
  1560. Message(parser_e_type_const_not_possible);
  1561. consume_all_until(_SEMICOLON);
  1562. end
  1563. else
  1564. ftcb.emit_tai(Tai_const.Create_sym(nil),def);
  1565. n.free;
  1566. exit;
  1567. end;
  1568. { for objects we allow it only if it doesn't contain a vmt }
  1569. if (oo_has_vmt in def.objectoptions) and
  1570. (m_fpc in current_settings.modeswitches) then
  1571. begin
  1572. Message(parser_e_type_object_constants);
  1573. exit;
  1574. end;
  1575. ftcb.maybe_begin_aggregate(def);
  1576. consume(_LKLAMMER);
  1577. startoffset:=curoffset;
  1578. objoffset:=0;
  1579. vmtwritten:=false;
  1580. while token<>_RKLAMMER do
  1581. begin
  1582. s:=pattern;
  1583. sorg:=orgpattern;
  1584. consume(_ID);
  1585. consume(_COLON);
  1586. srsym:=nil;
  1587. obj:=tobjectdef(def);
  1588. st:=obj.symtable;
  1589. while (srsym=nil) and assigned(st) do
  1590. begin
  1591. srsym:=tsym(st.Find(s));
  1592. if assigned(obj) then
  1593. obj:=obj.childof;
  1594. if assigned(obj) then
  1595. st:=obj.symtable
  1596. else
  1597. st:=nil;
  1598. end;
  1599. if (srsym=nil) or
  1600. (srsym.typ<>fieldvarsym) then
  1601. begin
  1602. if (srsym=nil) then
  1603. Message1(sym_e_id_not_found,sorg)
  1604. else
  1605. Message1(sym_e_illegal_field,sorg);
  1606. consume_all_until(_RKLAMMER);
  1607. break;
  1608. end
  1609. else
  1610. with tfieldvarsym(srsym) do
  1611. begin
  1612. { check position }
  1613. if fieldoffset<objoffset then
  1614. message(parser_e_invalid_record_const);
  1615. { check in VMT needs to be added for TP mode }
  1616. if not(vmtwritten) and
  1617. not(m_fpc in current_settings.modeswitches) and
  1618. (oo_has_vmt in def.objectoptions) and
  1619. (def.vmt_offset<fieldoffset) then
  1620. begin
  1621. ftcb.next_field:=tfieldvarsym(def.vmt_field);
  1622. ftcb.emit_tai(tai_const.createname(def.vmt_mangledname,AT_DATA,0),tfieldvarsym(def.vmt_field).vardef);
  1623. objoffset:=def.vmt_offset+tfieldvarsym(def.vmt_field).vardef.size;
  1624. vmtwritten:=true;
  1625. end;
  1626. ftcb.next_field:=tfieldvarsym(srsym);
  1627. { new position }
  1628. objoffset:=fieldoffset+vardef.size;
  1629. { read the data }
  1630. curoffset:=startoffset+fieldoffset;
  1631. read_typed_const_data(vardef);
  1632. if not try_to_consume(_SEMICOLON) then
  1633. break;
  1634. end;
  1635. end;
  1636. curoffset:=startoffset;
  1637. if not(m_fpc in current_settings.modeswitches) and
  1638. (oo_has_vmt in def.objectoptions) and
  1639. (def.vmt_offset>=objoffset) then
  1640. begin
  1641. for i:=1 to def.vmt_offset-objoffset do
  1642. ftcb.emit_tai(tai_const.create_8bit(0),u8inttype);
  1643. // TODO VMT type proper tdef?
  1644. ftcb.emit_tai(tai_const.createname(def.vmt_mangledname,AT_DATA,0),voidpointertype);
  1645. { this is more general }
  1646. objoffset:=def.vmt_offset + sizeof(pint);
  1647. end;
  1648. ftcb.maybe_end_aggregate(def);
  1649. consume(_RKLAMMER);
  1650. end;
  1651. procedure tasmlisttypedconstbuilder.parse_into_asmlist;
  1652. begin
  1653. read_typed_const_data(tcsym.vardef);
  1654. end;
  1655. { tnodetreetypedconstbuilder }
  1656. procedure tnodetreetypedconstbuilder.parse_arraydef(def: tarraydef);
  1657. var
  1658. n : tnode;
  1659. i : longint;
  1660. orgbase: tnode;
  1661. begin
  1662. { dynamic array nil }
  1663. if is_dynamic_array(def) then
  1664. begin
  1665. { Only allow nil initialization }
  1666. consume(_NIL);
  1667. addstatement(statmnt,cassignmentnode.create_internal(basenode,cnilnode.create));
  1668. basenode:=nil;
  1669. end
  1670. { array const between brackets }
  1671. else if try_to_consume(_LKLAMMER) then
  1672. begin
  1673. orgbase:=basenode;
  1674. for i:=def.lowrange to def.highrange-1 do
  1675. begin
  1676. basenode:=cvecnode.create(orgbase.getcopy,ctypeconvnode.create_explicit(genintconstnode(i),tarraydef(def).rangedef));
  1677. read_typed_const_data(def.elementdef);
  1678. if token=_RKLAMMER then
  1679. begin
  1680. Message1(parser_e_more_array_elements_expected,tostr(def.highrange-i));
  1681. consume(_RKLAMMER);
  1682. exit;
  1683. end
  1684. else
  1685. consume(_COMMA);
  1686. end;
  1687. basenode:=cvecnode.create(orgbase,ctypeconvnode.create_explicit(genintconstnode(def.highrange),tarraydef(def).rangedef));
  1688. read_typed_const_data(def.elementdef);
  1689. consume(_RKLAMMER);
  1690. end
  1691. { if array of char then we allow also a string }
  1692. else if is_anychar(def.elementdef) then
  1693. begin
  1694. n:=comp_expr(true,false);
  1695. addstatement(statmnt,cassignmentnode.create_internal(basenode,n));
  1696. basenode:=nil;
  1697. end
  1698. else
  1699. begin
  1700. { we want the ( }
  1701. consume(_LKLAMMER);
  1702. end;
  1703. end;
  1704. procedure tnodetreetypedconstbuilder.parse_procvardef(def: tprocvardef);
  1705. begin
  1706. addstatement(statmnt,cassignmentnode.create_internal(basenode,comp_expr(true,false)));
  1707. basenode:=nil;
  1708. end;
  1709. procedure tnodetreetypedconstbuilder.parse_recorddef(def: trecorddef);
  1710. var
  1711. n,n2 : tnode;
  1712. SymList:TFPHashObjectList;
  1713. orgbasenode : tnode;
  1714. symidx : longint;
  1715. recsym,
  1716. srsym : tsym;
  1717. sorg,s : TIDString;
  1718. recoffset : aint;
  1719. error,
  1720. is_packed: boolean;
  1721. procedure handle_stringconstn;
  1722. begin
  1723. addstatement(statmnt,cassignmentnode.create_internal(basenode,n));
  1724. basenode:=nil;
  1725. n:=nil;
  1726. end;
  1727. begin
  1728. { GUID }
  1729. if (def=rec_tguid) and (token=_ID) then
  1730. begin
  1731. n:=comp_expr(true,false);
  1732. if n.nodetype=stringconstn then
  1733. handle_stringconstn
  1734. else
  1735. begin
  1736. inserttypeconv(n,rec_tguid);
  1737. if n.nodetype=guidconstn then
  1738. begin
  1739. n2:=cstringconstnode.createstr(guid2string(tguidconstnode(n).value));
  1740. n.free;
  1741. n:=n2;
  1742. handle_stringconstn;
  1743. end
  1744. else
  1745. Message(parser_e_illegal_expression);
  1746. end;
  1747. n.free;
  1748. exit;
  1749. end;
  1750. if (def=rec_tguid) and ((token=_CSTRING) or (token=_CCHAR)) then
  1751. begin
  1752. n:=comp_expr(true,false);
  1753. inserttypeconv(n,cshortstringtype);
  1754. if n.nodetype=stringconstn then
  1755. handle_stringconstn
  1756. else
  1757. Message(parser_e_illegal_expression);
  1758. n.free;
  1759. exit;
  1760. end;
  1761. { bitpacked record? }
  1762. is_packed:=is_packed_record_or_object(def);
  1763. { normal record }
  1764. consume(_LKLAMMER);
  1765. recoffset:=0;
  1766. sorg:='';
  1767. symidx:=0;
  1768. symlist:=def.symtable.SymList;
  1769. srsym:=get_next_varsym(def,symlist,symidx);
  1770. recsym := nil;
  1771. orgbasenode:=basenode;
  1772. basenode:=nil;
  1773. while token<>_RKLAMMER do
  1774. begin
  1775. s:=pattern;
  1776. sorg:=orgpattern;
  1777. consume(_ID);
  1778. consume(_COLON);
  1779. error := false;
  1780. recsym := tsym(def.symtable.Find(s));
  1781. if not assigned(recsym) then
  1782. begin
  1783. Message1(sym_e_illegal_field,sorg);
  1784. error := true;
  1785. end;
  1786. if (not error) and
  1787. (not assigned(srsym) or
  1788. (s <> srsym.name)) then
  1789. { possible variant record (JM) }
  1790. begin
  1791. { All parts of a variant start at the same offset }
  1792. { Also allow jumping from one variant part to another, }
  1793. { as long as the offsets match }
  1794. if (assigned(srsym) and
  1795. (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
  1796. { srsym is not assigned after parsing w2 in the }
  1797. { typed const in the next example: }
  1798. { type tr = record case byte of }
  1799. { 1: (l1,l2: dword); }
  1800. { 2: (w1,w2: word); }
  1801. { end; }
  1802. { const r: tr = (w1:1;w2:1;l2:5); }
  1803. (tfieldvarsym(recsym).fieldoffset = recoffset) then
  1804. begin
  1805. srsym:=recsym;
  1806. { symidx should contain the next symbol id to search }
  1807. symidx:=SymList.indexof(srsym)+1;
  1808. end
  1809. { going backwards isn't allowed in any mode }
  1810. else if (tfieldvarsym(recsym).fieldoffset<recoffset) then
  1811. begin
  1812. Message(parser_e_invalid_record_const);
  1813. error := true;
  1814. end
  1815. { Delphi allows you to skip fields }
  1816. else if (m_delphi in current_settings.modeswitches) then
  1817. begin
  1818. Message1(parser_w_skipped_fields_before,sorg);
  1819. srsym := recsym;
  1820. end
  1821. { FPC and TP don't }
  1822. else
  1823. begin
  1824. Message1(parser_e_skipped_fields_before,sorg);
  1825. error := true;
  1826. end;
  1827. end;
  1828. if error then
  1829. consume_all_until(_SEMICOLON)
  1830. else
  1831. begin
  1832. { skipping fill bytes happens automatically, since we only
  1833. initialize the defined fields }
  1834. { new position }
  1835. recoffset:=tfieldvarsym(srsym).fieldoffset;
  1836. if not(is_packed) then
  1837. inc(recoffset,tfieldvarsym(srsym).vardef.size)
  1838. else
  1839. inc(recoffset,tfieldvarsym(srsym).vardef.packedbitsize);
  1840. { read the data }
  1841. if is_packed and
  1842. { only orddefs and enumdefs are bitpacked, as in gcc/gpc }
  1843. not(tfieldvarsym(srsym).vardef.typ in [orddef,enumdef]) then
  1844. recoffset:=align(recoffset,8);
  1845. basenode:=csubscriptnode.create(srsym,orgbasenode.getcopy);
  1846. read_typed_const_data(tfieldvarsym(srsym).vardef);
  1847. { keep previous field for checking whether whole }
  1848. { record was initialized (JM) }
  1849. recsym := srsym;
  1850. { goto next field }
  1851. srsym:=get_next_varsym(def,SymList,symidx);
  1852. if token=_SEMICOLON then
  1853. consume(_SEMICOLON)
  1854. else if (token=_COMMA) and (m_mac in current_settings.modeswitches) then
  1855. consume(_COMMA)
  1856. else
  1857. break;
  1858. end;
  1859. end;
  1860. { are there any fields left, but don't complain if there only
  1861. come other variant parts after the last initialized field }
  1862. if assigned(srsym) and
  1863. (
  1864. (recsym=nil) or
  1865. (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)
  1866. ) then
  1867. Message1(parser_w_skipped_fields_after,sorg);
  1868. orgbasenode.free;
  1869. basenode:=nil;
  1870. consume(_RKLAMMER);
  1871. end;
  1872. procedure tnodetreetypedconstbuilder.parse_objectdef(def: tobjectdef);
  1873. var
  1874. n,
  1875. orgbasenode : tnode;
  1876. obj : tobjectdef;
  1877. srsym : tsym;
  1878. st : tsymtable;
  1879. objoffset : aint;
  1880. s,sorg : TIDString;
  1881. begin
  1882. { no support for packed object }
  1883. if is_packed_record_or_object(def) then
  1884. begin
  1885. Message(type_e_no_const_packed_record);
  1886. exit;
  1887. end;
  1888. { only allow nil for implicit pointer object types }
  1889. if is_implicit_pointer_object_type(def) then
  1890. begin
  1891. n:=comp_expr(true,false);
  1892. if n.nodetype<>niln then
  1893. begin
  1894. Message(parser_e_type_const_not_possible);
  1895. consume_all_until(_SEMICOLON);
  1896. end
  1897. else
  1898. begin
  1899. addstatement(statmnt,cassignmentnode.create_internal(basenode,n));
  1900. n:=nil;
  1901. basenode:=nil;
  1902. end;
  1903. n.free;
  1904. exit;
  1905. end;
  1906. { for objects we allow it only if it doesn't contain a vmt }
  1907. if (oo_has_vmt in def.objectoptions) and
  1908. (m_fpc in current_settings.modeswitches) then
  1909. begin
  1910. Message(parser_e_type_object_constants);
  1911. exit;
  1912. end;
  1913. consume(_LKLAMMER);
  1914. objoffset:=0;
  1915. orgbasenode:=basenode;
  1916. basenode:=nil;
  1917. while token<>_RKLAMMER do
  1918. begin
  1919. s:=pattern;
  1920. sorg:=orgpattern;
  1921. consume(_ID);
  1922. consume(_COLON);
  1923. srsym:=nil;
  1924. obj:=tobjectdef(def);
  1925. st:=obj.symtable;
  1926. while (srsym=nil) and assigned(st) do
  1927. begin
  1928. srsym:=tsym(st.Find(s));
  1929. if assigned(obj) then
  1930. obj:=obj.childof;
  1931. if assigned(obj) then
  1932. st:=obj.symtable
  1933. else
  1934. st:=nil;
  1935. end;
  1936. if (srsym=nil) or
  1937. (srsym.typ<>fieldvarsym) then
  1938. begin
  1939. if (srsym=nil) then
  1940. Message1(sym_e_id_not_found,sorg)
  1941. else
  1942. Message1(sym_e_illegal_field,sorg);
  1943. consume_all_until(_RKLAMMER);
  1944. break;
  1945. end
  1946. else
  1947. with tfieldvarsym(srsym) do
  1948. begin
  1949. { check position }
  1950. if fieldoffset<objoffset then
  1951. message(parser_e_invalid_record_const);
  1952. { new position }
  1953. objoffset:=fieldoffset+vardef.size;
  1954. { read the data }
  1955. basenode:=csubscriptnode.create(srsym,orgbasenode.getcopy);
  1956. read_typed_const_data(vardef);
  1957. if not try_to_consume(_SEMICOLON) then
  1958. break;
  1959. end;
  1960. end;
  1961. consume(_RKLAMMER);
  1962. end;
  1963. procedure tnodetreetypedconstbuilder.tc_emit_orddef(def: torddef; var node: tnode);
  1964. begin
  1965. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  1966. basenode:=nil;
  1967. node:=nil;
  1968. end;
  1969. procedure tnodetreetypedconstbuilder.tc_emit_floatdef(def: tfloatdef; var node: tnode);
  1970. begin
  1971. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  1972. basenode:=nil;
  1973. node:=nil;
  1974. end;
  1975. procedure tnodetreetypedconstbuilder.tc_emit_classrefdef(def: tclassrefdef; var node: tnode);
  1976. begin
  1977. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  1978. basenode:=nil;
  1979. node:=nil;
  1980. end;
  1981. procedure tnodetreetypedconstbuilder.tc_emit_pointerdef(def: tpointerdef; var node: tnode);
  1982. begin
  1983. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  1984. basenode:=nil;
  1985. node:=nil;
  1986. end;
  1987. procedure tnodetreetypedconstbuilder.tc_emit_setdef(def: tsetdef; var node: tnode);
  1988. begin
  1989. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  1990. basenode:=nil;
  1991. node:=nil;
  1992. end;
  1993. procedure tnodetreetypedconstbuilder.tc_emit_enumdef(def: tenumdef; var node: tnode);
  1994. begin
  1995. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  1996. basenode:=nil;
  1997. node:=nil;
  1998. end;
  1999. procedure tnodetreetypedconstbuilder.tc_emit_stringdef(def: tstringdef; var node: tnode);
  2000. begin
  2001. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  2002. basenode:=nil;
  2003. node:=nil;
  2004. end;
  2005. constructor tnodetreetypedconstbuilder.create(sym: tstaticvarsym; previnit: tnode);
  2006. begin
  2007. inherited create(sym);
  2008. basenode:=cloadnode.create(sym,sym.owner);
  2009. resultblock:=internalstatements(statmnt);
  2010. if assigned(previnit) then
  2011. addstatement(statmnt,previnit);
  2012. end;
  2013. destructor tnodetreetypedconstbuilder.destroy;
  2014. begin
  2015. freeandnil(basenode);
  2016. freeandnil(resultblock);
  2017. inherited destroy;
  2018. end;
  2019. function tnodetreetypedconstbuilder.parse_into_nodetree: tnode;
  2020. begin
  2021. read_typed_const_data(tcsym.vardef);
  2022. result:=self.resultblock;
  2023. self.resultblock:=nil;
  2024. end;
  2025. begin
  2026. { default to asmlist version, best for most targets }
  2027. ctypedconstbuilder:=tasmlisttypedconstbuilder;
  2028. end.